Container Widgets
The following widget classes will inherit from a new ContainerWidget class:
- Pile
- Columns
- Overlay
- WidgetWrap
- ListBox
- HListBox (when completed)
Container widgets will provide a uniform way to access their children and will share much of their rendering code by describing the child widget layout to the ContainerWidget class at a high level. Inserting and removing children will be possible with some of the widget types.
Decorator Widgets
(Using the term "Decorator" from Design Patterns, not Python .. if you have a better name please let me know -Ian)
The following widget classes will inherit from a new DecoratorWidget class:
- AttrWrap
- BoxAdapter
- Padding
- Filler
- LineBox
- ScrollBar, FixedHint, WeightHint and FlowHint (when completed)
Decorator widgets are widgets whose purpose is to add embellishment to the widget they wrap. They wrap exactly one widget, and any widgets that are used as part of the embellishment are typically not accessed directly.
Widget Visitor
(Again, "Visitor" is from Design Patterns)
A WidgetVisitor is created by calling a new visitor() method on a Canvas object. Typically this would be called on the canvas returned by rendering the topmost widget.
The visitor object gives access to the widget that rendered the canvas as well as:
- widget's top-left coordinates, initially (0,0)
- widget's size (rendered and actual)
- focus state
- visitor to parent widget (not including decorator widgets) initially None
- the set_focus() "path" to the topmost parent, initially []
- list of decorator widgets wrapping this widget
- visitor to child widgets
- visitor to descendant (child-of child etc.) widgets based on screen coordinates
- visitor to descendant widget based on focus
The distinction between container and decorator widgets is most pronounced when using the WidgetVisitor class. Decorator widgets will be "passed through" and collected into a list when the visitor is traversing the widget tree. This will simplify access to widgets because adding or removing decorators will not affect the set_focus() "path", so code that specifies a path to a widget will not have to change.
For example, consider the following widget tree:
AttrWrap('body')
w: Frame
header: AttrWrap('title')
w: Text("This is the title.")
body: ListBox
0: Text("foo")
1: Padding('center',5)
w: AttrWrap('bright')
w: Text("bar")
2: Text("baz")
We have the following:
visitor.widget => Frame
visitor.decorators => [AttrWrap('body')]
visitor.keys() => ['header', 'body']
visitor['body'].widget => ListBox
visitor['body'].decorators => []
visitor['body'].keys() => [0, 1, 2]
visitor['body'][1].wiget => Text("bar")
visitor['body'][1].decorators => [Padding('center',5), AttrWrap('bright')]
visitor['body'][1].keys() => []
visitor['body'][1].path = ['body',1]
