an alternative approach to layout management

There is nothing wrong with sizers -- they are useful and powerful, and I have successfully used them to build some fairly complex dialogs.

However, as my company has been moving from REALbasic to Python, we have been wanting a smoother transition path from RB's approach (which amounts to absolute positions, combined with the ability to lock an item's left, top, right, and bottom sides to the corresponding window side in any combination) to wx. At the same time, though, we want to take advantage of the powerful wx philosophy of having layouts defined dynamically, relative to the actual sizes of things on whatever platform it's running on.

We've come up with an approach that we think combines the best of both worlds, at least for our purposes. It allows layouts to be defined very quickly and easily, while still being dynamic (in ways far more powerful than what RB easily supports). It can also be combined with the traditional sizer approach as desired.

I'm to the point where I could use some constructive input on it. Our intent is to polish it up nicely and publish it as FOSS. If there is anyone here who has substantial experience in wxPython, but has occasionally felt that there should be an easier way to manage layouts, please contact me off-list. I'll send you the little demo we have at this point, along with some explanation, and I would be very interested to hear any advice you have on it.

Thanks,
- Joe

Hello,

take a look to AUIDockingWindowsMgr in the wxDemo

···

2008/11/19 Joe Strout joe@strout.net

There is nothing wrong with sizers – they are useful and powerful, and I have successfully used them to build some fairly complex dialogs.

However, as my company has been moving from REALbasic to Python, we have been wanting a smoother transition path from RB’s approach (which amounts to absolute positions, combined with the ability to lock an item’s left, top, right, and bottom sides to the corresponding window side in any combination) to wx. At the same time, though, we want to take advantage of the powerful wx philosophy of having layouts defined dynamically, relative to the actual sizes of things on whatever platform it’s running on.

We’ve come up with an approach that we think combines the best of both worlds, at least for our purposes. It allows layouts to be defined very quickly and easily, while still being dynamic (in ways far more powerful than what RB easily supports). It can also be combined with the traditional sizer approach as desired.

I’m to the point where I could use some constructive input on it. Our intent is to polish it up nicely and publish it as FOSS. If there is anyone here who has substantial experience in wxPython, but has occasionally felt that there should be an easier way to manage layouts, please contact me off-list. I’ll send you the little demo we have at this point, along with some explanation, and I would be very interested to hear any advice you have on it.

Thanks,

  • Joe

wxpython-users mailing list

wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users


Saludos / Best regards

Mario Lacunza
Software Architect - Webmaster

Email: mlacunza [AT] gmail [DOT] com

http://www.lacunza.info
Lima - Peru

Joe Strout wrote:

If there is anyone here who has substantial experience in wxPython, but has occasionally felt that there should be an easier way to manage layouts,

That would be a good fraction of this list :wink:

I'd start the discussion here -- if it gets to be too much, we can move it off-list then.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Hi Mario,

take a look to AUIDockingWindowsMgr in the wxDemo

Thank you. I don't think that's addressing the same need, though. In fact, from what I can tell, you could combine AUI with our new layout approach (assuming you can embed arbitrary panels in an AUI app).

Would you like to take a look at what we have so far, and see whether I am way off base on that? It's quite small, so I've taken the liberty of attaching it. You should be able to unpack this, and then "python demo1.py" to see run the demo. Then examine demo.txt to see how that layout was defined, and read the docstring on the FlexPanel module for a very brief explanation of the format.

The long-term idea here is that we could make a visual GUI builder that would let you start by just dragging your widgets around on the panel, storing absolute positions. But then you could right-click (or click a pop-up widget of some sort) on any of the position terms, and it would suggest a set of other, more dynamic ways of encoding the same thing. For example, if button 2 is next to button 1, it could suggest things for its posLeft like 'button1.right + gap' or 'parent.midX + halfgap' or whatever may apply.

In this way, you have a very natural transition from a quick hacked-together static UI, to one that's dynamic and flexible. You don't have to switch to a completely different approach to get the benefits of a dynamic UI; you can just fix up your initial layout, window by window.

But we don't have a layout builder yet, we just have this text format. But already I find it much easier. For example, we had a half-dozen messages today on how to center a button within its parent panel. With FlexPanel, that would have been simply:

     posMidX = parent.MidX

with no mystery about it. What do you think?

Best,
- Joe

FlexPanel.zip (6.18 KB)

Nuts! The Python list replies-to the sender, and this list replies-to the list. Just when I finally get used to the python list, I screw up on this one. :slight_smile: Obviously I meant that last message to go only to Mario.

Oh well, sorry for the noise, but now I guess the cat is out of the bag -- if anyone wants to check out what we have so far, feel free. Just please keep in mind that this is in a very early pre-0.1 half-baked state at the moment, and interfaces and names and such are quite likely to change. If you have any thoughts about it, please send them to me and I'll do my best to incorporate all the feedback.

Best,
- Joe

Fair enough, especially since I just hit "Send" too quick a few moments ago and sent the demo archive to the list.

In addition to what I said there, here's a quick overview. I've made a subclass of Panel currently called "FlexPanel" which, instead of using sizers, repositions its children in its resize event. How does it know where to move them? Well, each child can have zero or more "position terms" associated with it. Each term has an identifier which must be one of the following:

     posLeft posRight posWidth posMidX
     posTop posBottom posHeight posMidY

Then it has an expression, which is stored and re-evaluated whenever the panel needs to be laid out (for example, when it is resized). The expression is evaluated with eval() in a context that defines the following variables:

     self: a position provider for the panel containing this item [1]
     parent: synonym for 'self'
     me: a position provider for the item being positioned [1]
     <item name>: a position provider for the named item within the parent
     gap: standard (horizontal or vertical as appropriate) gap between controls
     halfgap: equal to gap/2
     labelgap: standard gap between a label and the control it's labelling [2]
     leftMargin: standard gutter on left side of window [2]
     rightMargin: standard gutter on right side of window [2]
     topMargin: standard gutter on top side of window [3]
     bottomMargin: standard gutter on bottom side of window [3]
     maxWidth: function that returns the maximum width of the given items
     maxHeight: function that returns the maximum height of the given items

Notes: [1] A "position provider" is a wrapper for a wx.Window that provides
the following attributes: left, right, width, midX, top, bottom, height, midY.
  In addition, you can access any other attribute the object would normally
have (such as Name).
[2] These variables are defined only for horizontal position terms.
[3] These variables are defined only for vertical position terms.

Since the position terms are expressions, it is perfectly valid to specify a
calculation such as 'parent.midX / 2' (without the quotes). So basically this
allows you to set the position or width of anything, relative to anything else
(including some common platform-specific values like the margins and the gap
between controls).

You can set up these things manually, but I also made a simple parser that takes
a text file containing stuff like this...

# Create a couple of labels at the top of the panel, one
# on the left side, and the other on the right.
label1: wx.StaticText
  label: "Left Label"
  posTop: topMargin
  posLeft: leftMargin

label2: wx.StaticText
  label: "Right-Aligned Label"
  posTop: topMargin
  posRight: rightMargin

# Add a big expanding button, centered vertically, and extending
# from 140 pixels on the left to 40 pixels from the right edge.
stretchBtn: wx.Button
  label: "Stretchy"
  posMidY: parent.midY
  posLeft: 140
  posRight: parent.right - 40
  bind EVT_BUTTON: self.OnClick

...and sets it all up for you (including binding the events, if you include one or more "bind" specifiers). (More examples are included in the "demo.txt" file in the archive.)

So that's the big picture -- I've found defining layouts in this format to be quick and easy even without a visual layout builder, but the long-term intent of the design is to allow such a builder to be bolted on neatly in the future.

Cheers,
- Joe

···

On Nov 19, 2008, at 2:25 PM, Christopher Barker wrote:

If there is anyone here who has substantial experience in wxPython, but has occasionally felt that there should be an easier way to manage layouts,

That would be a good fraction of this list :wink:

I'd start the discussion here -- if it gets to be too much, we can move it off-list then.

Joe Strout wrote:

There is nothing wrong with sizers -- they are useful and powerful, and I have successfully used them to build some fairly complex dialogs.

However, as my company has been moving from REALbasic to Python, we have been wanting a smoother transition path from RB's approach (which amounts to absolute positions, combined with the ability to lock an item's left, top, right, and bottom sides to the corresponding window side in any combination) to wx. At the same time, though, we want to take advantage of the powerful wx philosophy of having layouts defined dynamically, relative to the actual sizes of things on whatever platform it's running on.

We've come up with an approach that we think combines the best of both worlds, at least for our purposes. It allows layouts to be defined very quickly and easily, while still being dynamic (in ways far more powerful than what RB easily supports). It can also be combined with the traditional sizer approach as desired.

I'm to the point where I could use some constructive input on it. Our intent is to polish it up nicely and publish it as FOSS. If there is anyone here who has substantial experience in wxPython, but has occasionally felt that there should be an easier way to manage layouts, please contact me off-list. I'll send you the little demo we have at this point, along with some explanation, and I would be very interested to hear any advice you have on it.

You may want to take a look at wxLayoutConstraints, it sounds similar to what you are doing. Layout constraints are what we had before sizers and although they've been pretty much ignored for the last eight years or so they are still there and probably always will be. There is also the wx.lib.anchors module which uses layout constraints to implement an anchor/spring approach to layout.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Thanks, Robin and Tim. You're right, what we're doing is similar to wxLayoutConstraints, though not quite the same. There are features of Python (such as eval) which allow it to be done more elegantly here (IMHO) than would be practical in C++. The wxLayoutConstraints approach, being based on C++, seems comparatively more cumbersome.

However, there are important ideas there and I'm going to study it more deeply to see what we can learn from it.

Best,
- Joe

···

On Nov 19, 2008, at 3:23 PM, Robin Dunn wrote:

You may want to take a look at wxLayoutConstraints, it sounds similar to what you are doing. Layout constraints are what we had before sizers and although they've been pretty much ignored for the last eight years or so they are still there and probably always will be.

Hello Joe,

I just come back from the street, here in Lima - Peru we have the APEC conference with many Country Presidents (includes Mr Bush and others) here, so we have thursday and friday freedays! (for security reasons), right now is 2.03AM (-5 GMT) tomorrow we check your code.

I’ll develop an App (the Admin) then it “make” another App (client) :slight_smile: based on some params definitions for the user (GUI controls, validations etc etc) and stored it in database, so when the client app read the param from the DB this should be able to create the new application at run time… Im interesting in your approach, let me see and tomorrow I send my comments.

···

2008/11/19 Joe Strout joe@strout.net

Hi Mario,

take a look to AUIDockingWindowsMgr in the wxDemo

Thank you. I don’t think that’s addressing the same need, though. In fact, from what I can tell, you could combine AUI with our new layout approach (assuming you can embed arbitrary panels in an AUI app).


Saludos / Best regards

Mario Lacunza
Software Architect - Webmaster

Email: mlacunza [AT] gmail [DOT] com
http://www.lacunza.info
Lima - Peru