The remaining content in this section has not been updated since July 2002. It's likely be very outdated in some parts.
The program starts from the function
“main
” in the module
“main
”: this creates an instance of
wxGlade (a subclass of wxApp
), which in turn
creates a wxGladeFrame
: this is the main window
of the app, i.e. the one with the palette of buttons. The
initialization of wxGladeFrame
consists of
three steps:
Creation of the three frames of the app, the palette itself, the tree and the property window
Loading of the code generator modules. The
“codegen/
” subdirectory is
scanned to find the available code generators: when a python
module is found, the app tries to load it and to access its
'writer' attribute: if this is successfully accomplished, such
'writer' object is considered a valid code generator, and is
inserted into the 'common.code_writers' dictionary (the key used
is the 'language' attribute of the writer itself)
Loading of the widget and sizer modules. To load the
widgets, the file
“widgets/widgets.txt
” is read,
and the app tries to import every widget module listed on such
file. For every module successfully imported, the
“initialize
” function is
then called: this function sets up the builder and code generator
functions for a particular widget (explained later), and returns a
wxBitmapButton
instance to be added to the
main palette. The loading of the sizers is more or less the same,
except that all the sizers are in the same module,
“edit_sizers
”, and the
initialization function (called
“init_gui
”) returns a list of
wxBitmapButton
objects
When the user clicks on a button of a top-level widget (a Frame
or a Dialog), the method
“add_toplevel_object
” of
wxGladeFrame
is called: this is responsible for
the addition of the widget to the application. This happens in this
way:
the name of the class of the widget to add is obtained: this
is done with the use of the
“common.refs
” dictionary, which maps the
ids of the buttons of the palette to the class names of the
widgets.
with the name just obtained, the appropriate factory
function for the widget to add is got from the
“common.widgets
” dictionary. This
function must accept three parameters: a reference to the parent
widget (None
in this case), a reference to the sizer
to which the widget will be added (again None
for
top-level windows) and the zero-based position inside the sizer
(once again, this is unused for top-level windows)
the call of the factory function actually builds the widgets
and inserts it in the “common.app_tree
”
tree with a call to its method
“insert
”. The
“__init__
” method of the widget
also builds all the Properties of the object and stores them in
the 'self.properties' dictionary
This is similar to the addition of a top-level widget, but the action is performed in two steps:
when the user clicks on the button in the palette, the
method “add_object
” of
wxGladeFrame
is called: this sets the
global variables “common.adding_widget
”
and “common.adding_sizer
” to
True
, and stores the class name of the sizer to add
in the global “common.widget_to_add
”
(the name is obtained from the
“common.refs
” dictionary as described
above)
when the user left-clicks the mouse inside the previously
added top-level widget, its “drop_sizer
”
method is called, which is responsible of the addition of the
sizer: it calls the factory function for the sizer (passing self
as the first argument), which will build the object and add it to
the tree
This step is more or less the same as step 3:
“wxGladeFrame.add_object
” is
called in response to a button click
when the user ``drops'' the widget inside a slot in a sizer,
the method “on_drop_widget
” of
edit_sizers.SizerSlot
is called, which in turn calls
the appropriate factory function with arguments
“self.parent
”,
“self.sizer
” and
“self.pos
” (i.e. the parent, sizer and
position inside the sizer of the slot that will be replaced).
Factory functions of non-top-level objects call, apart from
“common.app_tree.insert
” to insert the
object in the tree, the method
“add_item
” of
“edit_sizers.SizerBase
”, to
add the object to the sizer and to remove the slot. For managed
widgets/sizers, the
“__init__
” method also
builds the Properties which control the layout of the object
inside a sizer, and stores them in the
“self.sizer_properties
”
dictionary.
When the user selects a widget the property window changes to
display the properties of the selected object: this is done by the
functions “show_properties
” of
edit_windows.EditBase
and
edit_sizers.SizerBase
, which are called inside
two event handlers for focus and tree selection events.
When the value of a Property is changed, its setter function is
called to update the aspect/layout of the widget the Property belongs
to: such function is obtained from a call to the widget's
“__getitem__
” method, which must
return a 2-tuple (getter, setter) for the Property
This operation is performed by the
“common.app_tree
” Tree: for every Node of
the tree, an “object” XML element is generated, with the
following attributes: name, class, base (class). Each object contains
an element for each Property (generated by the
“write
” method of Property) and
then an “object” element for all its sub-widgets and/or
sizers. Properties in the “sizer_properties
”
dictionary are treated in a different way, as well as the children of
a sizer, which are sub-elements of
“sizeritem
” objects: see the source code for
details.
This is done by
“xml_parse.XmlWidgetBuilder
”, a
subclass of
xml.sax.handler.ContentHandler
.
Basically, the steps involved are the following:
when the start of an “object” element is
reached, a XMLWidgetObject
instance is
created and pushed onto a stack of the objects created: such
object in turn calls the appropriate ``XML builder'' function (got
from the “common.widgets_from_xml
”
dictionary) that creates the widget: this function is similar to
the factory function used to build the widget during an
interactive session, see the code for details and
differences
when the end of an “object” element is reached,
the object at the top of the stack is removed, and its widget (see
the source of XmlWidgetObject
) is laid
out
when the end of a Property element is reached, the
appropriate setter function of the owner of the Property is
called. This is the default behaviour, suitable for simple
properties. For more complex properties, whose XML representation
consists of more sub-elements, each widget can define a particular
handler: see for example FontHandler
in
edit_windows.WindowBase
This section is the result of a cut & paste of the comment
at the beginning of
“codegen/py_codegen.py
”. It is
*VERY* incomplete. The ContentHandler
subclass
which drives the code generation is
xml_parse.CodeWriter
.
How the code is generated: every time the end of an object is
reached during the parsing of the XML tree, either the function
“add_object
” or the function
“add_class
” is called: the
latter when the object is a top-level one, the former when it is not.
In the last case, “add_object
”
calls the appropriate ``writer'' function for the specific object,
found in the “obj_builders
” dictionary. Such
function accepts one argument, the CodeObject
representing the object for which the code has to be written, and
returns 3 lists of strings, representing the lines to add to the
“__init__
”,
“__set_properties
” and
“__do_layout
” methods of the
parent object.
The lines in the
“__init__
” list will be added
in reverse order.