## Working with generated source code

As a simple rule; Don't modify the code in generated _init_* methods unless you know what you are doing.

Boa currently generates / maintains the source code for:

- The wxApp class / modules

- The modules dictionary
- References, importing and the creation of the main frame

- Frame classes / modules (Frames, Dialogs and MDI frames)

- Importing of needed wxPython modules
- Window identifiers: wxID_* Each method has it's own window id list
- Special methods: _init_*

- _init_ctrls: Create and setup visual controls
- _init_utils: Create and setup non visible objects
- _init_coll_*: Create and setup of collections

- Event method declarations: On*
  Note: Boa only defines the methods, it does not maintain their code bodies, this is your responsibility

### Unsupported controls

If you want to add controls or objects not available on the Palette, simply add your code to the __init__ method below the call to _init_ctrls(). Don't add it in the Special methods listed above. Your code will be lost. Also, don't add your own window identifier to the list Boa maintains. Define your own window ids in a seperate list.
Note: Boa now has Custom Classes, see below.

### Generated code policy

Although is is possible to change the generated code by hand, it is not advised, and under normal circumstances, not necessary.

If you really need to modify generated code, keep the following in mind:

- Appart from custom classes only controls defined on the Palette may be used.
- Constructors need all parameters passed, and in keyword argument form
- Only methods defined or identified as property setter methods may be used
- Whitespace (blank lines) is significant for collection methods.
  They are in the form:
  Initialiser (optional)
  blank line
  Item definitions (1 or more lines)
  blank line
  Finaliser (optional)
- The window identifier list does not need to be updated manually when you remove components by hand from the source. It will be corrected the next time that the Designer is opened and posted.
- You may change the id property of a component in the source to special wxPython identifiers and the Designer will not overwrite these changes.
  Don't remove the generated id from the id definition list when you change it in the source.
  E.g. you may change the id of a wxButton to wxID_OK on a dialog and then you don't have to hook an event handler to EndModal OK it.

In summary, if Boa can't generate the code, it will also not be able to parse it.

### Special frame attributes

For frame like classes, you may define special attributes that the designer will respect and preserve in the generated source.

All instance attributes defined between the top of the __init__ method and the _init_ctrls() method call will be available to the Designer as valid names bound to properties.

For an attribute to qualify, it has to have a simple deduceable type; Python builtin or wxPython objects.
If for example the attribute is bound to a variable passed in as a parameter, you have to first initialise it to a literal of the same type. This value will be used at design time.

e.g.

    def __init__(self, parent, myFrameCaption):
        self.frameCaption = 'Design time frame caption'
        self.frameCaption = myFrameCaption
        self._init_ctrls(parent)

Now you may add this attribute as a parameter or property value in the source by hand.

e.g. (actually on one line)

    wxFrame.__init__(self, size = (-1, -1), id = wxID_WXFRAME1, pos = (-1, -1),
      title = self.frameCaption, parent = prnt, name = '', style = wxDEFAULT_FRAME_STYLE)

In the Inspector property values recognised as special attributes will display as bold values and cannot be edited in the property editor (yet).

See Examples/advanced/SpecialAttributes/wxFrame1.py

### Attribute mixin classes

Attribute Mixin classes can be used to centralise special frame attribute declarations that can be shared between frames.

The AttrMixin class must end with the postfix _AttrMixin, must be imported in the form from module import class and it's module must be in the same directory as the frame module.

Your frame should multiply-inherit from wxFrame and the mixin class and the call to the inherited mixin constructor must be placed before the _init_ctrls call.
e.g.

    class AttrMixinFrame(wxFrame, Test_AttrMixin):
        ...
        def __init__(self, parent):
            Test_AttrMixin.__init__(self)

            self._init_ctrls(parent)

See Examples/advanced/AttrMixins

### Defining custom classes

You may now define classes equivalent to standard wxPython classes which need not be defined on the palette in order to use in the Designer.

Custom Classes can be defined as a class attribute named _custom_classes containing a dictionary defining wxPython classes and their custom equivalents. Note that this class attribute must be set at the top of the class definition before the first method.

e.g.

    class wxFrame1(wxFrame):
        _custom_classes = {'wxTreeCtrl': ['MyTreeCtrl', 'AdvancedTreeCtrl']}
        def _init_utils(self):
            pass

These custom classes will then be available to the Designer and will act as equivalent to the corresponding wxPython class, but will generate source for the custom definition.

One implication is that you loose the constructor. Because Boa will generate the creation code for the object the constructor signature has to be the same as the wxPython class.

See Examples/advanced/CustomClasses/wxFrame1.py

### Frame panels

This allows you derive from wxPanel (Palette->New->wxFramePanel) and visually design a container that can be used as a custom class in frames or dialogs.

Note that it's a simple implementation with the same limitations as custom classes.
e.g. When adding your custom panel to the frame as a custom class, it will display in the designer as a blank wxPanel (because that is it's equivalent class. See Custom classes above).

To use, create a new custom panel from the Palette, name, design and save it.
Next go to the frame module where you want to use it, add an import statement for it and add the _custom_classes attribute for it.
e.g.

    from wxMyPanel1 import wxMyPanel1
    from wxMyPanel2 import wxMyPanel2
    ...
    class wxFrame1(wxFrame):
        _custom_classes = {'wxPanel': ['wxMyPanel1', 'wxMyPanel2']}
        def _init_utils(self):
            pass

See Examples/advanced/FramePanels

Boa Constructor - Application Help - Working with generated source code