2 # Purpose:      XRC editor, XML_tree class 
   3 # Author:       Roman Rolinsky <rolinsky@mema.ucl.ac.be> 
   7 from xxx 
import *                       # xxx imports globals and params 
  11 # Constant to define standart window name 
  12 STD_NAME 
= '_XRCED_T_W' 
  18     def __init__(self
, name
): 
  21     def write(self
, data
): 
  23             encoding 
= g
.currentEncoding
 
  25             encoding 
= wx
.GetDefaultPyEncoding() 
  27             self
.buffer += data
.encode(encoding
) 
  28         except UnicodeEncodeError: 
  29             self
.buffer += data
.encode(encoding
, 'xmlcharrefreplace') 
  32         wx
.MemoryFSHandler
.AddFile(self
.name
, self
.buffer) 
  34 ################################################################################ 
  36 # Redefine writing to include encoding 
  37 class MyDocument(minidom
.Document
): 
  39         minidom
.Document
.__init
__(self
) 
  41     def writexml(self
, writer
, indent
="", addindent
="", newl
="", encoding
=""): 
  42         if encoding
: encdstr 
= 'encoding="%s"' % encoding
 
  44         writer
.write('<?xml version="1.0" %s?>\n' % encdstr
) 
  45         for node 
in self
.childNodes
: 
  46             node
.writexml(writer
, indent
, addindent
, newl
) 
  48 ################################################################################ 
  50 # Ids for menu commands 
  59     STATUS_BAR 
= wx
.NewId() 
  61     STATIC_TEXT 
= wx
.NewId() 
  62     TEXT_CTRL 
= wx
.NewId() 
  65     BITMAP_BUTTON 
= wx
.NewId() 
  66     RADIO_BUTTON 
= wx
.NewId() 
  67     SPIN_BUTTON 
= wx
.NewId() 
  68     TOGGLE_BUTTON 
= wx
.NewId() 
  70     STATIC_BOX 
= wx
.NewId() 
  71     CHECK_BOX 
= wx
.NewId() 
  72     RADIO_BOX 
= wx
.NewId() 
  73     COMBO_BOX 
= wx
.NewId() 
  76     STATIC_LINE 
= wx
.NewId() 
  77     STATIC_BITMAP 
= wx
.NewId() 
  81     SCROLL_BAR 
= wx
.NewId() 
  82     TREE_CTRL 
= wx
.NewId() 
  83     LIST_CTRL 
= wx
.NewId() 
  84     CHECK_LIST 
= wx
.NewId() 
  86     CHOICEBOOK 
= wx
.NewId() 
  88     SPLITTER_WINDOW 
= wx
.NewId() 
  90     SCROLLED_WINDOW 
= wx
.NewId() 
  91     HTML_WINDOW 
= wx
.NewId() 
  92     CALENDAR_CTRL 
= wx
.NewId() 
  93     DATE_CTRL 
= wx
.NewId() 
  94     FILE_PICKER_CTRL 
= wx
.NewId() 
  95     GENERIC_DIR_CTRL 
= wx
.NewId() 
  96     SPIN_CTRL 
= wx
.NewId() 
  99     WIZARD_PAGE 
= wx
.NewId() 
 100     WIZARD_PAGE_SIMPLE 
= wx
.NewId() 
 103     STATUS_BAR 
= wx
.NewId() 
 105     BOX_SIZER 
= wx
.NewId() 
 106     STATIC_BOX_SIZER 
= wx
.NewId() 
 107     GRID_SIZER 
= wx
.NewId() 
 108     FLEX_GRID_SIZER 
= wx
.NewId() 
 109     GRID_BAG_SIZER 
= wx
.NewId() 
 110     STD_DIALOG_BUTTON_SIZER 
= wx
.NewId() 
 113     TOOL_BAR 
= wx
.NewId() 
 116     MENU_ITEM 
= wx
.NewId() 
 117     SEPARATOR 
= wx
.NewId() 
 119     OK_BUTTON 
= wx
.NewId() 
 120     YES_BUTTON 
= wx
.NewId() 
 121     SAVE_BUTTON 
= wx
.NewId() 
 122     APPLY_BUTTON 
= wx
.NewId() 
 123     NO_BUTTON 
= wx
.NewId() 
 124     CANCEL_BUTTON 
= wx
.NewId() 
 125     HELP_BUTTON 
= wx
.NewId() 
 126     CONTEXT_HELP_BUTTON 
= wx
.NewId() 
 132     for i 
in range(99): wx
.NewId()   # reserve IDs for custom controls 
 139     ID_EXPAND 
= wx
.NewId() 
 140     ID_COLLAPSE 
= wx
.NewId() 
 141     ID_PASTE_SIBLING 
= wx
.NewId() 
 142     ID_TOOL_PASTE 
= wx
.NewId() 
 143     ID_SUBCLASS 
= wx
.NewId() 
 145     def __init__(self
, parent
): 
 146         self
.ID_DELETE 
= parent
.ID_DELETE
 
 147         wx
.EVT_MENU_RANGE(parent
, ID_NEW
.PANEL
, ID_NEW
.LAST
, parent
.OnCreate
) 
 148         wx
.EVT_MENU_RANGE(parent
, 1000 + ID_NEW
.PANEL
, 1000 + ID_NEW
.LAST
, parent
.OnReplace
) 
 149         wx
.EVT_MENU(parent
, self
.ID_COLLAPSE
, parent
.OnCollapse
) 
 150         wx
.EVT_MENU(parent
, self
.ID_EXPAND
, parent
.OnExpand
) 
 151         wx
.EVT_MENU(parent
, self
.ID_PASTE_SIBLING
, parent
.OnPaste
) 
 152         wx
.EVT_MENU(parent
, self
.ID_SUBCLASS
, parent
.OnSubclass
) 
 153         # We connect to tree, but process in frame 
 154         wx
.EVT_MENU_HIGHLIGHT_ALL(g
.tree
, parent
.OnPullDownHighlight
) 
 156         # Mapping from IDs to element names 
 158             ID_NEW
.PANEL
: 'wxPanel', 
 159             ID_NEW
.DIALOG
: 'wxDialog', 
 160             ID_NEW
.FRAME
: 'wxFrame', 
 161             ID_NEW
.WIZARD
: 'wxWizard', 
 162             ID_NEW
.WIZARD_PAGE
: 'wxWizardPage', 
 163             ID_NEW
.WIZARD_PAGE_SIMPLE
: 'wxWizardPageSimple', 
 164             ID_NEW
.TOOL_BAR
: 'wxToolBar', 
 166             ID_NEW
.STATUS_BAR
: 'wxStatusBar', 
 167             ID_NEW
.MENU_BAR
: 'wxMenuBar', 
 168             ID_NEW
.MENU
: 'wxMenu', 
 169             ID_NEW
.MENU_ITEM
: 'wxMenuItem', 
 170             ID_NEW
.BITMAP
: 'wxBitmap', 
 171             ID_NEW
.ICON
: 'wxIcon', 
 172             ID_NEW
.SEPARATOR
: 'separator', 
 174             ID_NEW
.STATIC_TEXT
: 'wxStaticText', 
 175             ID_NEW
.TEXT_CTRL
: 'wxTextCtrl', 
 177             ID_NEW
.BUTTON
: 'wxButton', 
 178             ID_NEW
.BITMAP_BUTTON
: 'wxBitmapButton', 
 179             ID_NEW
.RADIO_BUTTON
: 'wxRadioButton', 
 180             ID_NEW
.SPIN_BUTTON
: 'wxSpinButton', 
 181             ID_NEW
.TOGGLE_BUTTON
: 'wxToggleButton', 
 183             ID_NEW
.STATIC_BOX
: 'wxStaticBox', 
 184             ID_NEW
.CHECK_BOX
: 'wxCheckBox', 
 185             ID_NEW
.RADIO_BOX
: 'wxRadioBox', 
 186             ID_NEW
.COMBO_BOX
: 'wxComboBox', 
 187             ID_NEW
.LIST_BOX
: 'wxListBox', 
 188             ID_NEW
.CHECK_LIST
: 'wxCheckListBox', 
 190             ID_NEW
.STATIC_LINE
: 'wxStaticLine', 
 191             ID_NEW
.STATIC_BITMAP
: 'wxStaticBitmap', 
 192             ID_NEW
.CHOICE
: 'wxChoice', 
 193             ID_NEW
.SLIDER
: 'wxSlider', 
 194             ID_NEW
.GAUGE
: 'wxGauge', 
 195             ID_NEW
.SCROLL_BAR
: 'wxScrollBar', 
 196             ID_NEW
.TREE_CTRL
: 'wxTreeCtrl', 
 197             ID_NEW
.LIST_CTRL
: 'wxListCtrl', 
 198             ID_NEW
.NOTEBOOK
: 'wxNotebook', 
 199             ID_NEW
.CHOICEBOOK
: 'wxChoicebook', 
 200             ID_NEW
.LISTBOOK
: 'wxListbook', 
 201             ID_NEW
.SPLITTER_WINDOW
: 'wxSplitterWindow', 
 202             ID_NEW
.GRID
: 'wxGrid', 
 203             ID_NEW
.SCROLLED_WINDOW
: 'wxScrolledWindow', 
 204             ID_NEW
.HTML_WINDOW
: 'wxHtmlWindow', 
 205             ID_NEW
.CALENDAR_CTRL
: 'wxCalendarCtrl', 
 206             ID_NEW
.DATE_CTRL
: 'wxDatePickerCtrl', 
 207             ID_NEW
.FILE_PICKER_CTRL
: 'wxFilePickerCtrl', 
 208             ID_NEW
.GENERIC_DIR_CTRL
: 'wxGenericDirCtrl', 
 209             ID_NEW
.SPIN_CTRL
: 'wxSpinCtrl', 
 211             ID_NEW
.BOX_SIZER
: 'wxBoxSizer', 
 212             ID_NEW
.STATIC_BOX_SIZER
: 'wxStaticBoxSizer', 
 213             ID_NEW
.GRID_SIZER
: 'wxGridSizer', 
 214             ID_NEW
.FLEX_GRID_SIZER
: 'wxFlexGridSizer', 
 215             ID_NEW
.GRID_BAG_SIZER
: 'wxGridBagSizer', 
 216             ID_NEW
.STD_DIALOG_BUTTON_SIZER
: 'wxStdDialogButtonSizer', 
 217             ID_NEW
.SPACER
: 'spacer', 
 218             ID_NEW
.UNKNOWN
: 'unknown', 
 220             ID_NEW
.OK_BUTTON
: 'wxButton', 
 221             ID_NEW
.YES_BUTTON
: 'wxButton', 
 222             ID_NEW
.SAVE_BUTTON
: 'wxButton', 
 223             ID_NEW
.APPLY_BUTTON
: 'wxButton', 
 224             ID_NEW
.NO_BUTTON
: 'wxButton', 
 225             ID_NEW
.CANCEL_BUTTON
: 'wxButton', 
 226             ID_NEW
.HELP_BUTTON
: 'wxButton', 
 227             ID_NEW
.CONTEXT_HELP_BUTTON
: 'wxButton', 
 230             (ID_NEW
.PANEL
, 'Panel', 'Create panel'), 
 231             (ID_NEW
.DIALOG
, 'Dialog', 'Create dialog'), 
 232             (ID_NEW
.FRAME
, 'Frame', 'Create frame'), 
 233             (ID_NEW
.WIZARD
, 'Wizard', 'Create wizard'), 
 235             (ID_NEW
.TOOL_BAR
, 'ToolBar', 'Create toolbar'), 
 236             (ID_NEW
.MENU_BAR
, 'MenuBar', 'Create menubar'), 
 237             (ID_NEW
.MENU
, 'Menu', 'Create menu'), 
 239             (ID_NEW
.BITMAP
, 'Bitmap', 'Create bitmap'), 
 240             (ID_NEW
.ICON
, 'Icon', 'Create icon'), 
 243              (ID_NEW
.PANEL
, 'Panel', 'Create panel'), 
 244              (ID_NEW
.NOTEBOOK
, 'Notebook', 'Create notebook control'), 
 245              (ID_NEW
.CHOICEBOOK
, 'Choicebook', 'Create choicebook control'), 
 246              (ID_NEW
.LISTBOOK
, 'Listbook', 'Create listbook control'), 
 247              (ID_NEW
.SPLITTER_WINDOW
, 'SplitterWindow', 'Create splitter window'), 
 248              (ID_NEW
.TOOL_BAR
, 'ToolBar', 'Create toolbar'), 
 249              (ID_NEW
.STATUS_BAR
, 'StatusBar', 'Create status bar'), 
 250 #             (ID_NEW.WIZARD_PAGE, 'WizardPage', 'Create wizard page'), 
 251              (ID_NEW
.WIZARD_PAGE_SIMPLE
, 'WizardPageSimple', 'Create simple wizard page'), 
 254              (ID_NEW
.BOX_SIZER
, 'BoxSizer', 'Create box sizer'), 
 255              (ID_NEW
.STATIC_BOX_SIZER
, 'StaticBoxSizer', 
 256               'Create static box sizer'), 
 257              (ID_NEW
.GRID_SIZER
, 'GridSizer', 'Create grid sizer'), 
 258              (ID_NEW
.FLEX_GRID_SIZER
, 'FlexGridSizer', 
 259               'Create flexgrid sizer'), 
 260              (ID_NEW
.GRID_BAG_SIZER
, 'GridBagSizer', 
 261               'Create gridbag sizer'), 
 262 #             (ID_NEW.STD_DIALOG_BUTTON_SIZER, 'StdDialogButtonSizer', 
 263 #              'Create standard button sizer'), 
 264              (ID_NEW
.SPACER
, 'Spacer', 'Create spacer'), 
 267             ['control', 'Various controls', 
 268              (ID_NEW
.STATIC_TEXT
, 'Label', 'Create label'), 
 269              (ID_NEW
.STATIC_BITMAP
, 'Bitmap', 'Create bitmap'), 
 270              (ID_NEW
.STATIC_LINE
, 'Line', 'Create line'), 
 271              (ID_NEW
.TEXT_CTRL
, 'TextBox', 'Create text box'), 
 272              (ID_NEW
.CHOICE
, 'Choice', 'Create choice'), 
 273              (ID_NEW
.SLIDER
, 'Slider', 'Create slider'), 
 274              (ID_NEW
.GAUGE
, 'Gauge', 'Create gauge'), 
 275              (ID_NEW
.SPIN_CTRL
, 'SpinCtrl', 'Create spin'), 
 276              (ID_NEW
.SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'), 
 277              (ID_NEW
.TREE_CTRL
, 'TreeCtrl', 'Create tree'), 
 278              (ID_NEW
.LIST_CTRL
, 'ListCtrl', 'Create list'), 
 279 #             (ID_NEW.GRID, 'Grid', 'Create grid'), 
 280              (ID_NEW
.SCROLLED_WINDOW
, 'ScrolledWindow', 'Create scrolled window'), 
 281              (ID_NEW
.HTML_WINDOW
, 'HtmlWindow', 'Create HTML window'), 
 282              (ID_NEW
.CALENDAR_CTRL
, 'CalendarCtrl', 'Create calendar control'), 
 283              (ID_NEW
.DATE_CTRL
, 'DatePickerCtrl', 'Create date picker control'), 
 284 #             (ID_NEW.FILE_PICKER_CTRL, 'FilePickerCtrl', 'Create file picker control'), 
 285              (ID_NEW
.GENERIC_DIR_CTRL
, 'GenericDirCtrl', 'Create generic dir control'), 
 286              (ID_NEW
.UNKNOWN
, 'Unknown', 'Create custom control placeholder'), 
 288             ['button', 'Buttons', 
 289              (ID_NEW
.BUTTON
, 'Button', 'Create button'), 
 290              (ID_NEW
.BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'), 
 291              (ID_NEW
.RADIO_BUTTON
, 'RadioButton', 'Create radio button'), 
 292              (ID_NEW
.SPIN_BUTTON
, 'SpinButton', 'Create spin button'), 
 293              (ID_NEW
.TOGGLE_BUTTON
, 'ToggleButton', 'Create toggle button'), 
 296              (ID_NEW
.STATIC_BOX
, 'StaticBox', 'Create static box'), 
 297              (ID_NEW
.CHECK_BOX
, 'CheckBox', 'Create check box'), 
 298              (ID_NEW
.RADIO_BOX
, 'RadioBox', 'Create radio box'), 
 299              (ID_NEW
.COMBO_BOX
, 'ComboBox', 'Create combo box'), 
 300              (ID_NEW
.LIST_BOX
, 'ListBox', 'Create list box'), 
 301              (ID_NEW
.CHECK_LIST
, 'CheckListBox', 'Create checklist box'), 
 303             ['container', 'Containers', 
 304              (ID_NEW
.PANEL
, 'Panel', 'Create panel'), 
 305              (ID_NEW
.NOTEBOOK
, 'Notebook', 'Create notebook control'), 
 306              (ID_NEW
.CHOICEBOOK
, 'Choicebook', 'Create choicebook control'), 
 307              (ID_NEW
.LISTBOOK
, 'Listbook', 'Create listbook control'), 
 308              (ID_NEW
.SPLITTER_WINDOW
, 'SplitterWindow', 'Create splitter window'), 
 309              (ID_NEW
.TOOL_BAR
, 'ToolBar', 'Create toolbar'), 
 310              (ID_NEW
.STATUS_BAR
, 'StatusBar', 'Create status bar'), 
 311              (ID_NEW
.MENU_BAR
, 'MenuBar', 'Create menubar'), 
 312 #             (ID_NEW.WIZARD_PAGE, 'Wizard Page', 'Create wizard page'), 
 313              (ID_NEW
.WIZARD_PAGE_SIMPLE
, 'WizardPageSimple', 'Create simple wizard page'), 
 316              (ID_NEW
.BOX_SIZER
, 'BoxSizer', 'Create box sizer'), 
 317              (ID_NEW
.STATIC_BOX_SIZER
, 'StaticBoxSizer', 
 318               'Create static box sizer'), 
 319              (ID_NEW
.GRID_SIZER
, 'GridSizer', 'Create grid sizer'), 
 320              (ID_NEW
.FLEX_GRID_SIZER
, 'FlexGridSizer', 
 321               'Create flexgrid sizer'), 
 322              (ID_NEW
.GRID_BAG_SIZER
, 'GridBagSizer', 
 323               'Create gridbag sizer'), 
 324              (ID_NEW
.SPACER
, 'Spacer', 'Create spacer'), 
 325              (ID_NEW
.STD_DIALOG_BUTTON_SIZER
, 'StdDialogButtonSizer', 
 326               'Create standard button sizer'), 
 329         self
.menuControls 
= [ 
 330             (ID_NEW
.MENU
, 'Menu', 'Create menu'), 
 331             (ID_NEW
.MENU_ITEM
, 'MenuItem', 'Create menu item'), 
 332             (ID_NEW
.SEPARATOR
, 'Separator', 'Create separator'), 
 334         self
.toolBarControls 
= [ 
 335             (ID_NEW
.TOOL
, 'Tool', 'Create tool'), 
 336             (ID_NEW
.SEPARATOR
, 'Separator', 'Create separator'), 
 337             ['control', 'Various controls', 
 338              (ID_NEW
.STATIC_TEXT
, 'Label', 'Create label'), 
 339              (ID_NEW
.STATIC_BITMAP
, 'Bitmap', 'Create bitmap'), 
 340              (ID_NEW
.STATIC_LINE
, 'Line', 'Create line'), 
 341              (ID_NEW
.TEXT_CTRL
, 'TextBox', 'Create text box'), 
 342              (ID_NEW
.CHOICE
, 'Choice', 'Create choice'), 
 343              (ID_NEW
.SLIDER
, 'Slider', 'Create slider'), 
 344              (ID_NEW
.GAUGE
, 'Gauge', 'Create gauge'), 
 345              (ID_NEW
.SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'), 
 346              (ID_NEW
.LIST_CTRL
, 'ListCtrl', 'Create list control'), 
 348             ['button', 'Buttons', 
 349              (ID_NEW
.BUTTON
, 'Button', 'Create button'), 
 350              (ID_NEW
.BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'), 
 351              (ID_NEW
.RADIO_BUTTON
, 'RadioButton', 'Create radio button'), 
 352              (ID_NEW
.SPIN_BUTTON
, 'SpinButton', 'Create spin button'), 
 355              (ID_NEW
.STATIC_BOX
, 'StaticBox', 'Create static box'), 
 356              (ID_NEW
.CHECK_BOX
, 'CheckBox', 'Create check box'), 
 357              (ID_NEW
.RADIO_BOX
, 'RadioBox', 'Create radio box'), 
 358              (ID_NEW
.COMBO_BOX
, 'ComboBox', 'Create combo box'), 
 359              (ID_NEW
.LIST_BOX
, 'ListBox', 'Create list box'), 
 360              (ID_NEW
.CHECK_LIST
, 'CheckListBox', 'Create checklist box'), 
 364             (ID_NEW
.OK_BUTTON
, 'OK Button', 'Create standard button'), 
 365             (ID_NEW
.YES_BUTTON
, 'YES Button', 'Create standard button'), 
 366             (ID_NEW
.SAVE_BUTTON
, 'SAVE Button',  'Create standard button'), 
 367             (ID_NEW
.APPLY_BUTTON
, 'APPLY Button',  'Create standard button'), 
 368             (ID_NEW
.NO_BUTTON
, 'NO Button',  'Create standard button'), 
 369             (ID_NEW
.CANCEL_BUTTON
, 'CANCEL Button',  'Create standard button'), 
 370             (ID_NEW
.HELP_BUTTON
, 'HELP Button',  'Create standard button'), 
 371             (ID_NEW
.CONTEXT_HELP_BUTTON
, 'CONTEXT HELP Button', 'Create standard button'), 
 373         self
.stdButtonIDs 
= { 
 374             ID_NEW
.OK_BUTTON
: ('wxID_OK', '&Ok'), 
 375             ID_NEW
.YES_BUTTON
: ('wxID_YES', '&Yes'), 
 376             ID_NEW
.SAVE_BUTTON
: ('wxID_SAVE', '&Save'), 
 377             ID_NEW
.APPLY_BUTTON
: ('wxID_APPLY', '&Apply'), 
 378             ID_NEW
.NO_BUTTON
: ('wxID_NO', '&No'), 
 379             ID_NEW
.CANCEL_BUTTON
: ('wxID_CANCEL', '&Cancel'), 
 380             ID_NEW
.HELP_BUTTON
: ('wxID_HELP', '&Help'), 
 381             ID_NEW
.CONTEXT_HELP_BUTTON
: ('wxID_CONTEXT_HELP', '&Help'), 
 383         self
.custom 
= ['custom', 'User-defined controls'] 
 386     def addCustom(self
, klass
): 
 387         n 
= len(self
.custom
)-2 
 388         self
.custom
.append((ID_NEW
.CUSTOM 
+ n
, klass
)) 
 389         self
.customMap
[ID_NEW
.CUSTOM 
+ n
] = klass
 
 392 ################################################################################ 
 394 # Set menu to list items. 
 395 # Each menu command is a tuple (id, label, help) 
 396 # submenus are lists [id, label, help, submenu] 
 397 # and separators are any other type. Shift is for making 
 398 # alternative sets of IDs. (+1000). 
 399 def SetMenu(m
, list, shift
=False): 
 401         if type(l
) == types
.TupleType
: 
 403             if shift
:  l 
= (1000 + l
[0],) + l
[1:] 
 405         elif type(l
) == types
.ListType
: 
 407             SetMenu(subMenu
, l
[2:], shift
) 
 408             m
.AppendMenu(wx
.NewId(), l
[0], subMenu
, l
[1]) 
 412 ################################################################################ 
 416     def __init__(self
, pos
, size
): 
 417         colour 
= g
.tree
.COLOUR_HL
 
 418         if size
.width 
== -1: size
.width 
= 0 
 419         if size
.height 
== -1: size
.height 
= 0 
 421         l1 
= wx
.Window(w
, -1, pos
, wx
.Size(size
.width
, 2)) 
 422         l1
.SetBackgroundColour(colour
) 
 423         l2 
= wx
.Window(w
, -1, pos
, wx
.Size(2, size
.height
)) 
 424         l2
.SetBackgroundColour(colour
) 
 425         l3 
= wx
.Window(w
, -1, wx
.Point(pos
.x 
+ size
.width 
- 2, pos
.y
), wx
.Size(2, size
.height
)) 
 426         l3
.SetBackgroundColour(colour
) 
 427         l4 
= wx
.Window(w
, -1, wx
.Point(pos
.x
, pos
.y 
+ size
.height 
- 2), wx
.Size(size
.width
, 2)) 
 428         l4
.SetBackgroundColour(colour
) 
 429         self
.lines 
= [l1
, l2
, l3
, l4
] 
 430         if wx
.Platform 
== '__WXMSW__': 
 432                 l
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
 433         g
.testWin
.highLight 
= self
 
 435     # Repainting is not always done for these windows on Windows 
 436     def OnPaint(self
, evt
): 
 437         w 
= evt
.GetEventObject() 
 441     # Move highlight to a new position 
 442     def Replace(self
, pos
, size
): 
 443         if size
.width 
== -1: size
.width 
= 0 
 444         if size
.height 
== -1: size
.height 
= 0 
 445         self
.lines
[0].SetDimensions(pos
.x
, pos
.y
, size
.width
, 2) 
 446         self
.lines
[1].SetDimensions(pos
.x
, pos
.y
, 2, size
.height
) 
 447         self
.lines
[2].SetDimensions(pos
.x 
+ size
.width 
- 2, pos
.y
, 2, size
.height
) 
 448         self
.lines
[3].SetDimensions(pos
.x
, pos
.y 
+ size
.height 
- 2, size
.width
, 2) 
 451         map(wx
.Window
.Destroy
, self
.lines
) 
 452         g
.testWin
.highLight 
= None 
 454         map(wx
.Window
.Refresh
, self
.lines
) 
 456 # Same for drop target 
 457 class HighLightDTBox(HighLightBox
): 
 459     def __init__(self
, pos
, size
): 
 460         colour 
= g
.tree
.COLOUR_DT
 
 461         if size
.width 
== -1: size
.width 
= 0 
 462         if size
.height 
== -1: size
.height 
= 0 
 464         l1 
= wx
.Window(w
, -1, pos
, wx
.Size(size
.width
, 2)) 
 465         l1
.SetBackgroundColour(colour
) 
 466         l2 
= wx
.Window(w
, -1, pos
, wx
.Size(2, size
.height
)) 
 467         l2
.SetBackgroundColour(colour
) 
 468         l3 
= wx
.Window(w
, -1, wx
.Point(pos
.x 
+ size
.width 
- 2, pos
.y
), wx
.Size(2, size
.height
)) 
 469         l3
.SetBackgroundColour(colour
) 
 470         l4 
= wx
.Window(w
, -1, wx
.Point(pos
.x
, pos
.y 
+ size
.height 
- 2), wx
.Size(size
.width
, 2)) 
 471         l4
.SetBackgroundColour(colour
) 
 472         self
.lines 
= [l1
, l2
, l3
, l4
] 
 477         map(wx
.Window
.Destroy
, self
.lines
) 
 478         g
.testWin
.highLightDT 
= None 
 480 def updateHL(hl
, hlClass
, pos
, size
): 
 481     # Need to recreate window if size did not change to force update 
 482     if hl 
and hl
.size 
== size
: 
 486         hl
.Replace(pos
, size
) 
 488         hl 
= hlClass(pos
, size
) 
 492 ################################################################################ 
 494 class XML_Tree(wx
.TreeCtrl
): 
 495     def __init__(self
, parent
, id): 
 497         self
.COLOUR_COMMENT  
= wx
.Colour(0, 0, 255) 
 498         self
.COLOUR_REF      
= wx
.Colour(0, 0, 128) 
 499         self
.COLOUR_HIDDEN   
= wx
.Colour(128, 128, 128) 
 500         self
.COLOUR_HL       
= wx
.Colour(255, 0, 0) 
 501         self
.COLOUR_DT       
= wx
.Colour(0, 64, 0) 
 503         wx
.TreeCtrl
.__init
__(self
, parent
, id, 
 504                              style 
= wx
.TR_HAS_BUTTONS | wx
.TR_MULTIPLE | wx
.TR_EDIT_LABELS
) 
 505         self
.SetBackgroundColour(wx
.Colour(224, 248, 224)) 
 506         self
.fontComment 
= wx
.FFont(self
.GetFont().GetPointSize(), 
 507                                     self
.GetFont().GetFamily(), 
 510         wx
.EVT_TREE_SEL_CHANGED(self
, self
.GetId(), self
.OnSelChanged
) 
 511         # One works on Linux, another on Windows 
 512         if wx
.Platform 
== '__WXGTK__': # !!! MAC too? 
 513             wx
.EVT_TREE_ITEM_ACTIVATED(self
, self
.GetId(), self
.OnItemActivated
) 
 515             wx
.EVT_LEFT_DCLICK(self
, self
.OnDClick
) 
 516         wx
.EVT_RIGHT_DOWN(self
, self
.OnRightDown
) 
 517         wx
.EVT_TREE_ITEM_EXPANDED(self
, self
.GetId(), self
.OnItemExpandedCollapsed
) 
 518         wx
.EVT_TREE_ITEM_COLLAPSED(self
, self
.GetId(), self
.OnItemExpandedCollapsed
) 
 519         self
.Bind(wx
.EVT_TREE_BEGIN_LABEL_EDIT
, self
.OnBeginLabelEdit
) 
 520         self
.Bind(wx
.EVT_TREE_END_LABEL_EDIT
, self
.OnEndLabelEdit
) 
 522         self
.selection 
= None 
 523         self
.selectionChanging 
= False 
 524         self
.needUpdate 
= False 
 525         self
.pendingHighLight 
= None 
 526         self
.ctrl 
= self
.shift 
= False 
 529         il 
= wx
.ImageList(16, 16, True) 
 530         self
.rootImage 
= il
.Add(images
.getTreeRootImage().Scale(16,16).ConvertToBitmap()) 
 531         xxxComment
.image 
= il
.Add(images
.getTreeCommentImage().Scale(16,16).ConvertToBitmap()) 
 532         xxxObject
.image 
= il
.Add(images
.getTreeDefaultImage().Scale(16,16).ConvertToBitmap()) 
 533         xxxPanel
.image 
= il
.Add(images
.getTreePanelImage().Scale(16,16).ConvertToBitmap()) 
 534         xxxDialog
.image 
= il
.Add(images
.getTreeDialogImage().Scale(16,16).ConvertToBitmap()) 
 535         xxxFrame
.image 
= il
.Add(images
.getTreeFrameImage().Scale(16,16).ConvertToBitmap()) 
 536         xxxMenuBar
.image 
= il
.Add(images
.getTreeMenuBarImage().Scale(16,16).ConvertToBitmap()) 
 537         xxxMenu
.image 
= il
.Add(images
.getTreeMenuImage().Scale(16,16).ConvertToBitmap()) 
 538         xxxMenuItem
.image 
= il
.Add(images
.getTreeMenuItemImage().Scale(16,16).ConvertToBitmap()) 
 539         xxxToolBar
.image 
= il
.Add(images
.getTreeToolBarImage().Scale(16,16).ConvertToBitmap()) 
 540         xxxTool
.image 
= il
.Add(images
.getTreeToolImage().Scale(16,16).ConvertToBitmap()) 
 541         xxxSeparator
.image 
= il
.Add(images
.getTreeSeparatorImage().Scale(16,16).ConvertToBitmap()) 
 542         xxxSizer
.imageH 
= il
.Add(images
.getTreeSizerHImage().Scale(16,16).ConvertToBitmap()) 
 543         xxxSizer
.imageV 
= il
.Add(images
.getTreeSizerVImage().Scale(16,16).ConvertToBitmap()) 
 544         xxxStaticBoxSizer
.imageH 
= il
.Add(images
.getTreeStaticBoxSizerHImage().Scale(16,16).ConvertToBitmap()) 
 545         xxxStaticBoxSizer
.imageV 
= il
.Add(images
.getTreeStaticBoxSizerVImage().Scale(16,16).ConvertToBitmap()) 
 546         xxxGridSizer
.image 
= il
.Add(images
.getTreeSizerGridImage().Scale(16,16).ConvertToBitmap()) 
 547         xxxFlexGridSizer
.image 
= il
.Add(images
.getTreeSizerFlexGridImage().Scale(16,16).ConvertToBitmap()) 
 549         self
.SetImageList(il
) 
 551     def RegisterKeyEvents(self
): 
 552         wx
.EVT_KEY_DOWN(self
, g
.tools
.OnKeyDown
) 
 553         wx
.EVT_KEY_UP(self
, g
.tools
.OnKeyUp
) 
 554         wx
.EVT_ENTER_WINDOW(self
, g
.tools
.OnMouse
) 
 555         wx
.EVT_LEAVE_WINDOW(self
, g
.tools
.OnMouse
) 
 557     def ExpandAll(self
, item
): 
 558         if self
.ItemHasChildren(item
): 
 560             i
, cookie 
= self
.GetFirstChild(item
) 
 564                 i
, cookie 
= self
.GetNextChild(item
, cookie
) 
 567     def CollapseAll(self
, item
): 
 568         if self
.ItemHasChildren(item
): 
 569             i
, cookie 
= self
.GetFirstChild(item
) 
 573                 i
, cookie 
= self
.GetNextChild(item
, cookie
) 
 581         self
.DeleteAllItems() 
 582         # Add minimal structure 
 583         if self
.dom
: self
.dom
.unlink() 
 584         self
.dom 
= MyDocument() 
 585         self
.dummyNode 
= self
.dom
.createComment('dummy node') 
 587         self
.mainNode 
= self
.dom
.createElement('resource') 
 588         self
.dom
.appendChild(self
.mainNode
) 
 589         self
.rootObj 
= xxxMainNode(self
.dom
) 
 590         self
.root 
= self
.AddRoot('XML tree', self
.rootImage
, 
 591                                  data
=wx
.TreeItemData(self
.rootObj
)) 
 592         self
.itemColour 
= self
.GetItemTextColour(self
.root
) 
 593         self
.SetItemHasChildren(self
.root
) 
 594         self
.testElem 
= self
.dom
.createElement('dummy') 
 595         self
.mainNode
.appendChild(self
.testElem
) 
 596         self
.Expand(self
.root
) 
 598     # Clear old data and set new 
 599     def SetData(self
, dom
): 
 601         self
.DeleteAllItems() 
 602         # Add minimal structure 
 603         if self
.dom
: self
.dom
.unlink() 
 605         self
.dummyNode 
= self
.dom
.createComment('dummy node') 
 606         # Find 'resource' child, add it's children 
 607         self
.mainNode 
= dom
.documentElement
 
 608         self
.rootObj 
= xxxMainNode(self
.dom
) 
 609         self
.root 
= self
.AddRoot('XML tree', self
.rootImage
, 
 610                                  data
=wx
.TreeItemData(self
.rootObj
)) 
 611         self
.SetItemHasChildren(self
.root
) 
 612         nodes 
= self
.mainNode
.childNodes
[:] 
 615                 self
.AddNode(self
.root
, None, node
) 
 617                 self
.mainNode
.removeChild(node
) 
 619         if self
.mainNode
.firstChild
: 
 620             self
.testElem 
= self
.dom
.createElement('dummy') 
 621             self
.mainNode
.insertBefore(self
.testElem
, self
.mainNode
.firstChild
) 
 623             self
.testElem 
= self
.dom
.createElement('dummy') 
 624             self
.mainNode
.appendChild(self
.testElem
) 
 625         self
.Expand(self
.root
) 
 627     # Add tree item for given parent item if node is DOM element node with 
 628     # object/object_ref tag. xxxParent is parent xxx object 
 629     def AddNode(self
, itemParent
, xxxParent
, node
): 
 630         # Set item data to current node 
 632             xxx 
= MakeXXXFromDOM(xxxParent
, node
) 
 634             print 'ERROR: MakeXXXFromDom(%s, %s)' % (xxxParent
, node
) 
 636         treeObj 
= xxx
.treeObject() 
 638         item 
= self
.AppendItem(itemParent
, treeObj
.treeName(), 
 639                                image
=treeObj
.treeImage(), 
 640                                data
=wx
.TreeItemData(xxx
)) 
 641         # Different color for comments and references 
 642         if xxx
.className 
== 'comment': 
 643             self
.SetItemTextColour(item
, self
.COLOUR_COMMENT
) 
 644             self
.SetItemFont(item
, self
.fontComment
) 
 646             self
.SetItemTextColour(item
, self
.COLOUR_REF
) 
 647         elif treeObj
.hasStyle 
and treeObj
.params
.get('hidden', False): 
 648             self
.SetItemTextColour(item
, self
.COLOUR_HIDDEN
) 
 649         # Try to find children objects 
 650         if treeObj
.hasChildren
: 
 651             nodes 
= treeObj
.node
.childNodes
[:] 
 654                     self
.AddNode(item
, treeObj
, n
) 
 655                 elif n
.nodeType 
!= minidom
.Node
.ELEMENT_NODE
: 
 656                     treeObj
.node
.removeChild(n
) 
 659     # Insert new item at specific position 
 660     def InsertNode(self
, itemParent
, parent
, elem
, nextItem
): 
 661         # Insert in XML tree and wxWin 
 662         xxx 
= MakeXXXFromDOM(parent
, elem
) 
 663         # If nextItem is None, we append to parent, otherwise insert before it 
 665             node 
= self
.GetPyData(nextItem
).node
 
 666             parent
.node
.insertBefore(elem
, node
) 
 667             # Inserting before is difficult, se we insert after or first child 
 668             index 
= self
.ItemIndex(nextItem
) 
 669             newItem 
= self
.InsertItemBefore(itemParent
, index
, 
 670                         xxx
.treeName(), image
=xxx
.treeImage()) 
 671             self
.SetPyData(newItem
, xxx
) 
 673             parent
.node
.appendChild(elem
) 
 674             newItem 
= self
.AppendItem(itemParent
, xxx
.treeName(), image
=xxx
.treeImage(), 
 675                                       data
=wx
.TreeItemData(xxx
)) 
 676         treeObj 
= xxx
.treeObject() 
 677         # Different color for references and comments 
 678         if xxx
.className 
== 'comment': 
 679             self
.SetItemTextColour(newItem
, self
.COLOUR_COMMENT
) 
 680             self
.SetItemFont(newItem
, self
.fontComment
) 
 682             self
.SetItemTextColour(newItem
, self
.COLOUR_REF
) 
 683         elif treeObj
.hasStyle 
and treeObj
.params
.get('hidden', False): 
 684             self
.SetItemTextColour(newItem
, self
.COLOUR_HIDDEN
) 
 687             treeObj 
= xxx
.treeObject() 
 688             for n 
in treeObj
.node
.childNodes
: 
 690                     self
.AddNode(newItem
, treeObj
, n
) 
 693     # Remove leaf of tree, return it's data object 
 694     def RemoveLeaf(self
, leaf
): 
 695         xxx 
= self
.GetPyData(leaf
) 
 697         parent 
= node
.parentNode
 
 698         parent
.removeChild(node
) 
 702     # Find position relative to the top-level window 
 703     def FindNodePos(self
, item
, obj
=None): 
 705         if item 
== g
.testWin
.item
: return wx
.Point(0, 0) 
 706         itemParent 
= self
.GetItemParent(item
) 
 708         if not obj
: obj 
= self
.FindNodeObject(item
) 
 709         if self
.GetPyData(itemParent
).treeObject().__class
__ in \
 
 710                [xxxNotebook
, xxxChoicebook
, xxxListbook
]: 
 711             book 
= self
.FindNodeObject(itemParent
) 
 713             for i 
in range(book
.GetPageCount()): 
 714                 if book
.GetPage(i
) == obj
: 
 715                     if book
.GetSelection() != i
: 
 717                         # Remove highlight - otherwise highlight window won't be visible 
 718                         if g
.testWin
.highLight
: 
 719                             g
.testWin
.highLight
.Remove() 
 721         # For sizers and notebooks we must select the first window-like parent 
 722         winParent 
= itemParent
 
 723         while self
.GetPyData(winParent
).isSizer
: 
 724             winParent 
= self
.GetItemParent(winParent
) 
 725         # Notebook children are layed out in a little strange way 
 726         # wxGTK places NB panels relative to the NB parent 
 727         if wx
.Platform 
== '__WXGTK__': 
 728             if self
.GetPyData(itemParent
).treeObject().__class
__ == xxxNotebook
: 
 729                 winParent 
= self
.GetItemParent(winParent
) 
 730         parentPos 
= self
.FindNodePos(winParent
) 
 731         pos 
= obj
.GetPosition() 
 732         # Position (-1,-1) is really (0,0) 
 733         if pos 
== (-1,-1): pos 
= (0,0) 
 734         return parentPos 
+ pos
 
 736     # Find window (or sizer) corresponding to a tree item. 
 737     def FindNodeObject(self
, item
): 
 739         # If top-level, return testWin (or panel its panel) 
 740         if item 
== testWin
.item
: return testWin
.panel
 
 741         itemParent 
= self
.GetItemParent(item
) 
 742         xxx 
= self
.GetPyData(item
).treeObject() 
 743         parentWin 
= self
.FindNodeObject(itemParent
) 
 744         # Top-level sizer? return window's sizer 
 745         if xxx
.isSizer 
and isinstance(parentWin
, wx
.Window
): 
 746             return parentWin
.GetSizer() 
 747         elif xxx
.__class
__ in [xxxMenu
, xxxMenuItem
, xxxSeparator
]:  return None 
 748         elif xxx
.__class
__ in [xxxToolBar
, xxxMenuBar
]: 
 749             # If it's the main toolbar or menubar, we can't really select it 
 750             if xxx
.parent
.__class
__ == xxxFrame
:  return None 
 751         elif isinstance(xxx
.parent
, xxxToolBar
): 
 752             # Select complete toolbar 
 754         elif isinstance(xxx
.parent
, xxxStdDialogButtonSizer
): 
 755             # This sizer returns non-existing children 
 756             for ch 
in parentWin
.GetChildren(): 
 757                 if ch
.GetWindow() and ch
.GetWindow().GetName() == xxx
.name
: 
 758                     return ch
.GetWindow() 
 760         elif xxx
.parent
.__class
__ in [xxxChoicebook
, xxxListbook
]: 
 761             # First window is controld 
 762             return parentWin
.GetChildren()[self
.ItemIndex(item
)+1] 
 763         # Otherwise get parent's object and it's child 
 764         child 
= parentWin
.GetChildren()[self
.WindowIndex(item
)] 
 765         # Return window or sizer for sizer items 
 766         if child
.GetClassName() == 'wxSizerItem': 
 767             if child
.IsWindow(): child 
= child
.GetWindow() 
 768             elif child
.IsSizer(): 
 769                 child 
= child
.GetSizer() 
 772     def OnSelChanged(self
, evt
): 
 773         if self
.selectionChanging
: return 
 774         self
.selectionChanging 
= True 
 775         wx
.TreeCtrl
.UnselectAll(self
) 
 776         self
.ChangeSelection(evt
.GetItem()) 
 777         wx
.TreeCtrl
.SelectItem(self
, evt
.GetItem()) 
 778         self
.selectionChanging 
= False 
 779         g
.frame
.SetStatusText('') 
 782     # Override to use like single-selection tree 
 783     def GetSelection(self
): 
 784         return self
.selection
 
 786     def SelectItem(self
, item
): 
 788         self
.ChangeSelection(item
) 
 789         wx
.TreeCtrl
.SelectItem(self
, item
) 
 791     def UnselectAll(self
): 
 792         self
.selection 
= None 
 794         wx
.TreeCtrl
.UnselectAll(self
) 
 797     def ChangeSelection(self
, item
): 
 799         # !!! problem with wxGTK - GetOldItem is Ok if nothing selected 
 800         #oldItem = evt.GetOldItem() 
 802         oldItem 
= self
.selection
 
 804             xxx 
= self
.GetPyData(oldItem
) 
 805             # If some data was modified, apply changes 
 806             if g
.panel
.IsModified(): 
 807                 self
.Apply(xxx
, oldItem
) 
 809                     if g
.testWin
.highLight
: 
 810                         g
.testWin
.highLight
.Remove() 
 811                     self
.needUpdate 
= True 
 812                 status 
= 'Changes were applied' 
 813         if status
: g
.frame
.SetStatusText(status
) 
 816             self
.selection 
= None 
 819             self
.selection 
= item
 
 820         xxx 
= self
.GetPyData(item
) 
 825         # Highlighting is done in OnIdle 
 826         self
.pendingHighLight 
= self
.selection
 
 828     # Check if item is in testWin subtree 
 829     def IsHighlatable(self
, item
): 
 830         if item 
== g
.testWin
.item
: return False 
 831         while item 
!= self
.root
: 
 832             item 
= self
.GetItemParent(item
) 
 833             if item 
== g
.testWin
.item
: 
 837     # Highlight selected item 
 838     def HighLight(self
, item
): 
 839         self
.pendingHighLight 
= None 
 840         # Can highlight only with some top-level windows 
 841         if not g
.testWin 
or self
.GetPyData(g
.testWin
.item
).treeObject().__class
__ \
 
 842             not in [xxxDialog
, xxxPanel
, xxxFrame
]: 
 844         # If a control from another window is selected, remove highlight 
 845         if not self
.IsHighlatable(item
): 
 846             if g
.testWin
.highLight
: g
.testWin
.highLight
.Remove() 
 848         # Get window/sizer object 
 849         obj 
= self
.FindNodeObject(item
) 
 850         xxx 
= self
.GetPyData(item
).treeObject() 
 851         # Remove existing HL if item not found or is hidden 
 852         if not obj 
or xxx
.hasStyle 
and xxx
.params
.get('hidden', False): 
 853             if g
.testWin
.highLight
: g
.testWin
.highLight
.Remove() 
 855         pos 
= self
.FindNodePos(item
, obj
)          
 858         # Negative positions are not working quite well 
 859         # If highlight object has the same size SetDimension does not repaint it 
 860         # so we must remove the old HL window 
 861         g
.testWin
.highLight 
= updateHL(g
.testWin
.highLight
, HighLightBox
, pos
, size
) 
 862         g
.testWin
.highLight
.item 
= item
 
 863         g
.testWin
.highLight
.obj 
= obj
 
 865     def ShowTestWindow(self
, item
): 
 866         xxx 
= self
.GetPyData(item
) 
 867         if g
.panel
.IsModified(): 
 868             self
.Apply(xxx
, item
)       # apply changes 
 869         availableViews 
= ['wxFrame', 'wxPanel', 'wxDialog',   
 870                           'wxMenuBar', 'wxToolBar', 'wxWizard',   
 871                           'wxWizardPageSimple'] 
 873         # Walk up the tree until we find an item that has a view 
 874         while item 
and self
.GetPyData(item
).treeObject().className 
not in availableViews
: 
 875             item 
= self
.GetItemParent(item
) 
 876         if not item 
or not item
.IsOk(): 
 877             wx
.LogMessage('No view for this element (yet)') 
 880         if g
.testWin
:     # Reset old 
 882             self
.SetItemBold(g
.testWin
.item
, False) 
 885             self
.CreateTestWin(item
) 
 888         # Maybe an error occurred, so we need to test 
 890             self
.SetItemBold(g
.testWin
.item
) 
 891             # Select original item 
 892             self
.ChangeSelection(originalItem
) 
 894     # Double-click on Linux 
 895     def OnItemActivated(self
, evt
): 
 896         if evt
.GetItem() != self
.root
: 
 897             self
.ShowTestWindow(evt
.GetItem()) 
 899     # Double-click on Windows 
 900     def OnDClick(self
, evt
): 
 901         item
, flags 
= self
.HitTest(evt
.GetPosition()) 
 902         if flags 
in [wx
.TREE_HITTEST_ONITEMBUTTON
, wx
.TREE_HITTEST_ONITEMLABEL
]: 
 903             if item 
!= self
.root
: self
.ShowTestWindow(item
) 
 907     def OnItemExpandedCollapsed(self
, evt
): 
 908         # Update tool palette 
 912     # (re)create test window 
 913     def CreateTestWin(self
, item
): 
 915         # Create a window with this resource 
 916         xxx 
= self
.GetPyData(item
).treeObject() 
 917         # Close old window, remember where it was 
 920             pos 
= testWin
.GetPosition() 
 921             if item 
== testWin
.item
: 
 922                 # Remember highlight if same top-level window 
 923                 if testWin
.highLight
: 
 924                     highLight 
= testWin
.highLight
.item
 
 925                 if xxx
.className 
== 'wxPanel': 
 926                     if testWin
.highLight
: 
 927                         testWin
.pendingHighLight 
= highLight
 
 928                         testWin
.highLight
.Remove() 
 929                     testWin
.panel
.Destroy() 
 933                     testWin 
= g
.testWin 
= None 
 936                 testWin 
= g
.testWin 
= None 
 940         memFile 
= MemoryFile('xxx.xrc') 
 941         # Create memory XML file 
 942         elem 
= xxx
.node
.cloneNode(True) 
 947         elem
.setAttribute('name', STD_NAME
) 
 948         oldTestNode 
= self
.testElem
 
 950         self
.mainNode
.replaceChild(elem
, oldTestNode
) 
 952         # Replace wizard page class temporarily 
 953         if xxx
.__class
__ in [xxxWizardPage
, xxxWizardPageSimple
]: 
 954             oldCl 
= elem
.getAttribute('class') 
 955             elem
.setAttribute('class', 'wxPanel') 
 956         parent 
= elem
.parentNode
 
 957         encd 
= self
.rootObj
.params
['encoding'].value() 
 958         if not encd
: encd 
= None 
 960             self
.dom
.writexml(memFile
, encoding
=encd
) 
 963             wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1]) 
 964             wx
.LogError('Error writing temporary file') 
 965         memFile
.close()                 # write to wxMemoryFS 
 966         xmlFlags 
= xrc
.XRC_NO_SUBCLASSING
 
 967         # Use translations if encoding is not specified 
 968         if not g
.currentEncoding
: 
 969             xmlFlags 
!= xrc
.XRC_USE_LOCALE
 
 970         res 
= xrc
.XmlResource('', xmlFlags
) 
 971         res
.InitAllHandlers() 
 972         xrc
.XmlResource
.Set(res
)        # set as global 
 976         res
.Load('memory:xxx.xrc') 
 978             if xxx
.__class
__ == xxxFrame
: 
 979                 # Frame can't have many children, 
 980                 # but it's first child possibly can... 
 981     #            child = self.GetFirstChild(item)[0] 
 982     #            if child.IsOk() and self.GetPyData(child).__class__ == xxxPanel: 
 983     #                # Clean-up before recursive call or error 
 984     #                wx.MemoryFSHandler.RemoveFile('xxx.xrc') 
 986     #                self.CreateTestWin(child) 
 988                 # This currently works under GTK, but not under MSW 
 989                 testWin 
= g
.testWin 
= wx
.PreFrame() 
 990                 res
.LoadOnFrame(testWin
, g
.frame
, STD_NAME
) 
 992                 testWin
.panel 
= testWin
 
 993                 #testWin.CreateStatusBar() 
 994                 testWin
.SetClientSize(testWin
.GetBestSize()) 
 995                 testWin
.SetPosition(pos
) 
 997             elif xxx
.__class
__ == xxxPanel
: 
1000                     testWin 
= g
.testWin 
= wx
.Frame(g
.frame
, -1, 'Panel: ' + name
, 
1001                                                    pos
=pos
, name
=STD_NAME
) 
1002                 testWin
.panel 
= res
.LoadPanel(testWin
, STD_NAME
) 
1003                 testWin
.panel
.SetSize(testWin
.GetClientSize()) 
1004                 #testWin.SetClientSize(testWin.GetSize()) 
1006             elif xxx
.__class
__ == xxxDialog
: 
1007                 testWin 
= g
.testWin 
= res
.LoadDialog(g
.frame
, STD_NAME
) 
1008                 testWin
.panel 
= testWin
 
1010                 testWin
.SetPosition(pos
) 
1012                 # Dialog's default code does not produce wx.EVT_CLOSE 
1013                 wx
.EVT_BUTTON(testWin
, wx
.ID_OK
, self
.OnCloseTestWin
) 
1014                 wx
.EVT_BUTTON(testWin
, wx
.ID_CANCEL
, self
.OnCloseTestWin
) 
1015             elif xxx
.__class
__ == xxxWizard
: 
1016                 wiz 
= wx
.wizard
.PreWizard() 
1017                 res
.LoadOnObject(wiz
, g
.frame
, STD_NAME
, 'wxWizard') 
1018                 # Find first page (don't know better way) 
1020                 for w 
in wiz
.GetChildren(): 
1021                     if isinstance(w
, wx
.wizard
.WizardPage
): 
1025                     wx
.LogError('Wizard is empty') 
1027                     # Wizard should be modal 
1028                     self
.SetItemBold(item
) 
1030                     self
.SetItemBold(item
, False) 
1032             elif xxx
.__class
__ in [xxxWizardPage
, xxxWizardPageSimple
]: 
1035                     testWin 
= g
.testWin 
= wx
.Frame(g
.frame
, -1, 'Wizard page: ' + name
, 
1036                                                   pos
=pos
, name
=STD_NAME
) 
1037                 testWin
.panel 
= wx
.PrePanel() 
1038                 res
.LoadOnObject(testWin
.panel
, testWin
, STD_NAME
, 'wxPanel') 
1039                 testWin
.SetClientSize(testWin
.GetBestSize()) 
1041             elif xxx
.__class
__ == xxxMenuBar
: 
1042                 testWin 
= g
.testWin 
= wx
.Frame(g
.frame
, -1, 'MenuBar: ' + name
, 
1043                                               pos
=pos
, name
=STD_NAME
) 
1044                 testWin
.panel 
= None 
1045                 # Set status bar to display help 
1046                 testWin
.CreateStatusBar() 
1047                 testWin
.menuBar 
= res
.LoadMenuBar(STD_NAME
) 
1048                 testWin
.SetMenuBar(testWin
.menuBar
) 
1050             elif xxx
.__class
__ == xxxToolBar
: 
1051                 testWin 
= g
.testWin 
= wx
.Frame(g
.frame
, -1, 'ToolBar: ' + name
, 
1052                                               pos
=pos
, name
=STD_NAME
) 
1053                 testWin
.panel 
= None 
1054                 # Set status bar to display help 
1055                 testWin
.CreateStatusBar() 
1056                 testWin
.toolBar 
= res
.LoadToolBar(testWin
, STD_NAME
) 
1057                 testWin
.SetToolBar(testWin
.toolBar
) 
1059             # Catch some events, set highlight 
1062                 wx
.EVT_CLOSE(testWin
, self
.OnCloseTestWin
) 
1063                 wx
.EVT_SIZE(testWin
, self
.OnSizeTestWin
) 
1066                     testWin
.panel
.SetDropTarget(DropTarget()) 
1068                     testWin
.SetDropTarget(DropTarget()) 
1070                 testWin
.highLight 
= testWin
.highLightDT 
= None 
1071                 if highLight 
and not self
.pendingHighLight
: 
1072                     self
.HighLight(highLight
) 
1075                 self
.SetItemBold(item
, False) 
1076                 g
.testWinPos 
= g
.testWin
.GetPosition() 
1079             inf 
= sys
.exc_info() 
1080             wx
.LogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1]) 
1081             wx
.LogError('Error loading resource') 
1083         res
.Unload('xxx.xrc') 
1084         xrc
.XmlResource
.Set(None) 
1085         wx
.MemoryFSHandler
.RemoveFile('xxx.xrc') 
1087     def CloseTestWindow(self
): 
1088         if not g
.testWin
: return 
1089         self
.SetItemBold(g
.testWin
.item
, False) 
1090         g
.frame
.tb
.ToggleTool(g
.frame
.ID_TOOL_LOCATE
, False) 
1091         g
.testWinPos 
= g
.testWin
.GetPosition() 
1095     def OnCloseTestWin(self
, evt
): 
1096         self
.CloseTestWindow() 
1098     def OnSizeTestWin(self
, evt
): 
1099         # Update highlight after size change 
1100         hl 
= g
.testWin
.highLight
 
1102             hl
.Replace(self
.FindNodePos(hl
.item
), hl
.obj
.GetSize()) 
1104             #self.HighLight(g.testWin.highLight.item) 
1107     # Return index in parent, for real window children 
1108     def WindowIndex(self
, item
): 
1109         n 
= 0                           # index of sibling 
1110         prev 
= self
.GetPrevSibling(item
) 
1112             # MenuBar and sizers are not real children (who else?) 
1113             if not isinstance(self
.GetPyData(prev
), xxxMenuBar
) and not \
 
1114                     isinstance(self
.GetPyData(prev
), xxxSizer
): 
1116             prev 
= self
.GetPrevSibling(prev
) 
1119     # Return item index in parent 
1120     def ItemIndex(self
, item
): 
1121         n 
= 0                           # index of sibling 
1122         prev 
= self
.GetPrevSibling(item
) 
1124             prev 
= self
.GetPrevSibling(prev
) 
1128     # Full tree index of an item - list of positions 
1129     def ItemFullIndex(self
, item
): 
1130         if not item
.IsOk(): return None 
1132         while item 
!= self
.root
: 
1133             l
.insert(0, self
.ItemIndex(item
)) 
1134             item 
= self
.GetItemParent(item
) 
1136     # Get item position from full index 
1137     def ItemAtFullIndex(self
, index
): 
1138         if index 
is None: return wx
.TreeItemId() 
1141             item 
= self
.GetFirstChild(item
)[0] 
1142             for k 
in range(i
): item 
= self
.GetNextSibling(item
) 
1145     # True if next item should be inserted after current (vs. appended to it) 
1146     def NeedInsert(self
, item
): 
1147         xxx 
= self
.GetPyData(item
) 
1148         if item 
== self
.root
: return False        # root item 
1149         if xxx
.hasChildren 
and not self
.GetChildrenCount(item
, False): 
1151         return not (self
.IsExpanded(item
) and self
.GetChildrenCount(item
, False)) 
1154     def OnRightDown(self
, evt
): 
1155         pullDownMenu 
= g
.pullDownMenu
 
1157         pt 
= evt
.GetPosition(); 
1158         item
, flags 
= self
.HitTest(pt
) 
1159         if item
.Ok() and flags 
& wx
.TREE_HITTEST_ONITEM
: 
1160             self
.SelectItem(item
) 
1165         item 
= self
.selection
 
1167             menu
.Append(g
.pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand tree') 
1168             menu
.Append(g
.pullDownMenu
.ID_COLLAPSE
, 'Collapse', 'Collapse tree') 
1170 #            self.ctrl = evt.ControlDown() # save Ctrl state 
1171 #            self.shift = evt.ShiftDown()  # and Shift too 
1172             m 
= wx
.Menu()                  # create menu 
1176                 needInsert 
= self
.NeedInsert(item
) 
1177             if item 
== self
.root 
or needInsert 
and self
.GetItemParent(item
) == self
.root
: 
1178                 SetMenu(m
, pullDownMenu
.topLevel
) 
1180                 m
.Append(ID_NEW
.REF
, 'reference...', 'Create object_ref node') 
1181                 m
.Append(ID_NEW
.COMMENT
, 'comment', 'Create comment node') 
1183                 xxx 
= self
.GetPyData(item
).treeObject() 
1184                 # Check parent for possible child nodes if inserting sibling 
1185                 if needInsert
: xxx 
= xxx
.parent
 
1186                 if xxx
.__class
__ == xxxMenuBar
: 
1187                     m
.Append(ID_NEW
.MENU
, 'Menu', 'Create menu') 
1188                 elif xxx
.__class
__ in [xxxToolBar
, xxxTool
] or \
 
1189                      xxx
.__class
__ == xxxSeparator 
and xxx
.parent
.__class
__ == xxxToolBar
: 
1190                     SetMenu(m
, pullDownMenu
.toolBarControls
) 
1191                 elif xxx
.__class
__ in [xxxMenu
, xxxMenuItem
]: 
1192                     SetMenu(m
, pullDownMenu
.menuControls
) 
1193                 elif xxx
.__class
__ == xxxStdDialogButtonSizer
: 
1194                     SetMenu(m
, pullDownMenu
.stdButtons
) 
1196                     SetMenu(m
, pullDownMenu
.controls
) 
1197                     if xxx
.__class
__ in [xxxNotebook
, xxxChoicebook
, xxxListbook
]: 
1198                         m
.Enable(m
.FindItem('sizer'), False) 
1199                     elif not (xxx
.isSizer 
or xxx
.parent 
and xxx
.parent
.isSizer
): 
1200                         m
.Enable(ID_NEW
.SPACER
, False) 
1201                     if xxx
.__class
__ is not xxxFrame
: 
1202                         m
.Enable(ID_NEW
.MENU_BAR
, False) 
1203                 # Add custom controls menu 
1204                 if len(pullDownMenu
.custom
) > 2: 
1205                     SetMenu(m
, [pullDownMenu
.custom
]) 
1207                 m
.Append(ID_NEW
.REF
, 'reference...', 'Create object_ref node') 
1208                 m
.Append(ID_NEW
.COMMENT
, 'comment', 'Create comment node') 
1209             # Select correct label for create menu 
1212                     menu
.AppendMenu(wx
.NewId(), 'Insert Child', m
, 
1213                                     'Create child object as the first child') 
1215                     menu
.AppendMenu(wx
.NewId(), 'Append Child', m
, 
1216                                     'Create child object as the last child') 
1219                     menu
.AppendMenu(wx
.NewId(), 'Create Sibling', m
, 
1220                                     'Create sibling before selected object') 
1222                     menu
.AppendMenu(wx
.NewId(), 'Create Sibling', m
, 
1223                                     'Create sibling after selected object') 
1224             # Build replace menu 
1225             if item 
!= self
.root
: 
1226                 xxx 
= self
.GetPyData(item
).treeObject() 
1227                 m 
= wx
.Menu()                  # create replace menu 
1228                 if xxx
.__class
__ == xxxMenuBar
: 
1229                     m
.Append(1000 + ID_NEW
.MENU
, 'Menu', 'Create menu') 
1230                 elif xxx
.__class
__ in [xxxMenu
, xxxMenuItem
]: 
1231                     SetMenu(m
, pullDownMenu
.menuControls
, shift
=True) 
1232                 elif xxx
.__class
__ == xxxToolBar 
and \
 
1233                          self
.GetItemParent(item
) == self
.root
: 
1234                     SetMenu(m
, [], shift
=True) 
1235                 elif xxx
.__class
__ in [xxxFrame
, xxxDialog
, xxxPanel
]: 
1237                         (ID_NEW
.PANEL
, 'Panel', 'Create panel'), 
1238                         (ID_NEW
.DIALOG
, 'Dialog', 'Create dialog'), 
1239                         (ID_NEW
.FRAME
, 'Frame', 'Create frame')], shift
=True) 
1240                 elif xxx
.isSizer 
and self
.ItemHasChildren(item
): 
1241                     SetMenu(m
, pullDownMenu
.sizers
, shift
=True) 
1243                     SetMenu(m
, pullDownMenu
.controls
, shift
=True) 
1246                     menu
.AppendMenu(id, 'Replace With', m
) 
1247                     if not m
.GetMenuItemCount(): menu
.Enable(id, False) 
1248                     menu
.Append(pullDownMenu
.ID_SUBCLASS
, 'Subclass...', 
1249                                 'Set "subclass" property') 
1250             menu
.AppendSeparator() 
1251             # Not using standart IDs because we don't want to show shortcuts 
1252             menu
.Append(wx
.ID_CUT
, 'Cut', 'Cut to the clipboard') 
1253             menu
.Append(wx
.ID_COPY
, 'Copy', 'Copy to the clipboard') 
1254             if self
.ctrl 
and item 
!= self
.root
: 
1255                 menu
.Append(pullDownMenu
.ID_PASTE_SIBLING
, 'Paste Sibling', 
1256                             'Paste from the clipboard as a sibling') 
1258                 menu
.Append(wx
.ID_PASTE
, 'Paste', 'Paste from the clipboard') 
1259             menu
.Append(pullDownMenu
.ID_DELETE
, 
1260                                 'Delete', 'Delete object') 
1261             if self
.ItemHasChildren(item
): 
1262                 menu
.AppendSeparator() 
1263                 menu
.Append(pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand subtree') 
1264                 menu
.Append(pullDownMenu
.ID_COLLAPSE
, 'Collapse', 'Collapse subtree') 
1265         self
.PopupMenu(menu
, evt
.GetPosition()) 
1269     def Apply(self
, xxx
, item
): 
1272         xxx 
= xxx
.treeObject() 
1273         if xxx
.hasName 
and self
.GetItemText(item
) != xxx
.name
: 
1274             self
.SetItemText(item
, xxx
.treeName()) 
1275             # Item width may have changed 
1276             # !!! Tric to update tree width (wxGTK, ??) 
1277             self
.SetIndent(self
.GetIndent()) 
1278         elif xxx
.className 
== 'comment': 
1279             self
.SetItemText(item
, xxx
.treeName()) 
1280         # Change tree icon for sizers 
1281         if isinstance(xxx
, xxxBoxSizer
): 
1282             self
.SetItemImage(item
, xxx
.treeImage()) 
1283         # Set global modified state 
1284         g
.frame
.SetModified() 
1286     def OnBeginLabelEdit(self
, evt
): 
1287         xxx 
= self
.GetPyData(evt
.GetItem()) 
1293     def OnEndLabelEdit(self
, evt
): 
1294         xxx 
= self
.GetPyData(evt
.GetItem()) 
1296         if not xxx
.isElement
: 
1297             node
.data 
= evt
.GetLabel() 
1298             g
.panel
.SetData(xxx
) 
1301 ################################################################################ 
1305 class DropTarget(wx
.PyDropTarget
): 
1307         self
.do 
= MyDataObject() 
1308         wx
.DropTarget
.__init
__(self
, self
.do
) 
1310     # Find best object for dropping 
1311     def WhereToDrop(self
, x
, y
, d
): 
1312         # Find object by position 
1313         obj 
= wx
.FindWindowAtPoint(g
.testWin
.ClientToScreen((x
,y
))) 
1315             return wx
.DragNone
, () 
1316         item 
= g
.frame
.FindObject(g
.testWin
.item
, obj
) 
1318             return wx
.DragNone
, () 
1319         xxx 
= g
.tree
.GetPyData(item
).treeObject() 
1321         # Check if window has a XRC sizer, then use it as parent 
1323             sizer 
= obj
.GetSizer() 
1324             sizerItem 
= g
.frame
.FindObject(g
.testWin
.item
, sizer
) 
1326                 parentItem 
= sizerItem
 
1328                 item 
= wx
.TreeItemId() 
1329         # if not sizer but can have children, it is parent with free placement 
1330         elif xxx
.hasChildren
: 
1332             item 
= wx
.TreeItemId() 
1333         # Otherwise, try to add to item's parent 
1335             parentItem 
= g
.tree
.GetItemParent(item
) 
1336             obj 
= g
.tree
.FindNodeObject(parentItem
) 
1337         parent 
= g
.tree
.GetPyData(parentItem
).treeObject() 
1338         return d
,(obj
,parent
,parentItem
,item
) 
1341     def OnData(self
, x
, y
, d
): 
1343         id = int(self
.do
.GetDataHere()) 
1344         d
,other 
= self
.WhereToDrop(x
, y
, d
) 
1345         if d 
!= wx
.DragNone
: 
1346             obj
,parent
,parentItem
,item 
= other
 
1347             g
.tree
.selection 
= parentItem
 
1348             xxx 
= g
.frame
.CreateXXX(parent
, parentItem
, item
,  id) 
1349             # Set coordinates if parent is not sizer 
1350             if not parent
.isSizer
: 
1351                 xxx
.set('pos', '%d,%d' % (x
, y
)) 
1352                 g
.panel
.SetData(xxx
) 
1353             g
.frame
.SetStatusText('Object created') 
1357     def OnDragOver(self
, x
, y
, d
): 
1358         d
,other 
= self
.WhereToDrop(x
, y
, d
) 
1359         if d 
!= wx
.DragNone
: 
1360             obj
,parent
,parentItem
,item 
= other
 
1361             pos
, size 
= g
.tree
.FindNodePos(parentItem
, obj
), obj
.GetSize() 
1362             hl 
= g
.testWin
.highLightDT
 
1363             # Set color of highlighted item back to normal 
1365                 if hl
.item 
!= parentItem
: 
1366                     g
.tree
.SetItemTextColour(hl
.item
, g
.tree
.itemColour
) 
1367                     # Highlight future parent 
1368                     g
.tree
.itemColour 
= g
.tree
.GetItemTextColour(parentItem
) # save current 
1369             if not hl 
or hl
.item 
!= parentItem
: 
1370                 g
.testWin
.highLightDT 
= updateHL(hl
, HighLightDTBox
, pos
, size
) 
1371                 g
.testWin
.highLightDT
.item 
= parentItem
 
1372             g
.tree
.SetItemTextColour(parentItem
, g
.tree
.COLOUR_DT
) 
1373             g
.tree
.EnsureVisible(parentItem
) 
1374             g
.frame
.SetStatusText('Drop target: %s' % parent
.treeName()) 
1376             g
.frame
.SetStatusText('Inappropriate drop target') 
1384         hl 
= g
.testWin
.highLightDT
 
1387                 g
.tree
.SetItemTextColour(hl
.item
, g
.tree
.itemColour
)