[PEAK] A layout and styling framework for UI components

Phillip J. Eby pje at telecommunity.com
Fri Dec 7 09:11:23 EST 2007


At 10:44 AM 12/7/2007 +0200, niki wrote:
>Phillip J. Eby wrote:
>
>>Requirements
>>------------
>>One of the biggest complications involved is that GUI components 
>>must typically be initialized in a top-down fashion, beginning with 
>>a parent frame followed by its child controls.  However, in writing 
>>programs, it is much easier and clearer to specify objects in a 
>>bottom-up form, e.g.:
>>     Frame(children=[Control1(), Control2(), ...])
>>(Notice that an expression like this actually creates the parent 
>>*after* its children.)
>
>Small note. wx can handle such creation order by using 2 phase
>construction (designed for loading from XRC)
>
>         f = PreFrame(children=[PreControl1() ... ])
>
>the second pass is:
>         f.Create(parent, ....)
>         for c in f.children:
>                 c.Create(f, ...)

Right - we want to avoid 2-phase construction altogether, and in any 
case the requirement to include arbitrary interaction components and 
abstract presentation components/templates prevents this from being usable.


>>"Renderer" Objects
>>------------------
>>A renderer is a relatively simple object that exists to hold the 
>>state for, and co-ordinate the process of, rendering the 
>>presentation for an object.  It performs widget construction and 
>>pre/per/post-child processing, after first being "configured" for 
>>the object(s) being rendered.  It also holds references to the 
>>target object, the resulting rendering, and a parent renderer if 
>>any.  Renderers will also be able to "manage" context managers, 
>>such that the rendering process can be wrapped by context managers 
>>(such as the application of nested style sheets).
>
>Why not call them Builder objects? Don't they implement this pattern?

Not really.  If anything, it's more like a cross between an Abstract 
Factory and a Template Method, crossed with some Chains of 
Responsibility.  If you force-fit the builder pattern onto this, then 
the Renderer would be the "director" part of the pattern, rather than 
the builder part (which would be the stylesheet rules and the 
handlers they register with the Renderer).


>>Rules and Cascading
>>-------------------
>>[...]
>>example, if you have this hierarchy:
>>      class Foo(object): pass
>>      class Bar(Foo): pass
>>      class MyStyles(rendering.DefaultStyles): pass
>>Then the order of rule precedence for a Bar instance is:
>>     * Rules defined in DefaultStyles[object]
>>     * Rules defined in MyStyles[object]
>>     * Rules defined in DefaultStyles[Foo]
>>     * Rules defined in MyStyles[Foo]
>>     * Rules defined in DefaultStyles[Bar]
>>     * Rules defined in MyStyles[Bar]
>>Note that more-specific rules are executed *later*, which thus 
>>gives them the opportunity to override things that are set up by a 
>>less-specific rule.  (Note: a given stylesheet may contain only one 
>>rule for a given target type, and once defined, it cannot be 
>>changed.  Among other things, this allows for caching.)
>
>This way overriding is not possible. Or an override should find and
>change all side effects from previous rules?

You don't need to find and change them - you just set what you want 
and inherit the rest.  Remember, rules only configure the renderer 
with settings and handlers; they don't directly operate on the result.


>There are examples of using
>CSS for styling wx, aren't they enough?

Keep in mind that this "styling" includes what objects to create in 
the first place; I don't know how you'd do that with CSS.


>>What's Left
>>-----------
>>This post doesn't actually cover how layouts will work, although it 
>>can be taken as a given that most layout requirements can be met 
>>through simple hierarchical construction and specifying of options 
>>on renderers.  I will probably post again at a later time regarding 
>>more sophisticated layout possibilities, but it will likely be 
>>after work on how to "hint" or "tag" interaction components (such 
>>as commands, fields, etc.) for use in rendering menus, toolbars, 
>>dialogs, and such.
>
>Automatic layout can be very ugly.

This isn't automatic layout per se.  Remember that individual 
components can contain "hints", and the stylesheet can contain 
arbitrary code to support customizing the layout.


>Simple task to align text in label
>and edit control is impossible to do unless baseline property is
>handled.

Yep, that will be handled by rendering the pair from a single Field 
object.  Also, when we (eventually) have Lout-style layout formulas, 
baseline alignment will probably be the default way of horizontally 
aligning widgets.


>  Nice UI should account for whitespace balance etc. Best example
>is photoshop and by chance it's layout (EVE) is open source as part of
>Adobe Source Libraries. http://sourceforge.net/projects/adobe-source/

Yep, and EVE is based on a trellis-like system, interestingly 
enough.  Unfortunately, I was not able to find any documents 
explaining EVE's layout algorithm, whitespace handling, etc.




More information about the PEAK mailing list