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
): 
  22         self
.buffer += data
.encode() 
  24         wxMemoryFSHandler_AddFile(self
.name
, self
.buffer) 
  26 ################################################################################ 
  28 # Redefine writing to include encoding 
  29 class MyDocument(minidom
.Document
): 
  31         minidom
.Document
.__init
__(self
) 
  33     def writexml(self
, writer
, indent
="", addindent
="", newl
="", encoding
=""): 
  34         if encoding
: encdstr 
= 'encoding="%s"' % encoding
 
  36         writer
.write('<?xml version="1.0" %s?>\n' % encdstr
) 
  37         for node 
in self
.childNodes
: 
  38             node
.writexml(writer
, indent
, addindent
, newl
) 
  40 ################################################################################ 
  42 # Ids for menu commands 
  52     STATIC_TEXT 
= wxNewId() 
  56     BITMAP_BUTTON 
= wxNewId() 
  57     RADIO_BUTTON 
= wxNewId() 
  58     SPIN_BUTTON 
= wxNewId() 
  59     TOGGLE_BUTTON 
= wxNewId() 
  61     STATIC_BOX 
= wxNewId() 
  67     STATIC_LINE 
= wxNewId() 
  68     STATIC_BITMAP 
= wxNewId() 
  72     SCROLL_BAR 
= wxNewId() 
  75     CHECK_LIST 
= wxNewId() 
  77     SPLITTER_WINDOW 
= wxNewId() 
  78     SCROLLED_WINDOW 
= wxNewId() 
  79     HTML_WINDOW 
= wxNewId() 
  80     CALENDAR_CTRL 
= wxNewId() 
  81     GENERIC_DIR_CTRL 
= wxNewId() 
  86     STATIC_BOX_SIZER 
= wxNewId() 
  87     GRID_SIZER 
= wxNewId() 
  88     FLEX_GRID_SIZER 
= wxNewId() 
  89     GRID_BAG_SIZER 
= wxNewId() 
 100     ID_COLLAPSE 
= wxNewId() 
 101     ID_PASTE_SIBLING 
= wxNewId() 
 102     ID_SUBCLASS 
= wxNewId() 
 104     def __init__(self
, parent
): 
 105         self
.ID_DELETE 
= parent
.ID_DELETE
 
 106         EVT_MENU_RANGE(parent
, ID_NEW
.PANEL
, ID_NEW
.LAST
, parent
.OnCreate
) 
 107         EVT_MENU_RANGE(parent
, 1000 + ID_NEW
.PANEL
, 1000 + ID_NEW
.LAST
, parent
.OnReplace
) 
 108         EVT_MENU(parent
, self
.ID_COLLAPSE
, parent
.OnCollapse
) 
 109         EVT_MENU(parent
, self
.ID_EXPAND
, parent
.OnExpand
) 
 110         EVT_MENU(parent
, self
.ID_PASTE_SIBLING
, parent
.OnPaste
) 
 111         EVT_MENU(parent
, self
.ID_SUBCLASS
, parent
.OnSubclass
) 
 112         # We connect to tree, but process in frame 
 113         EVT_MENU_HIGHLIGHT_ALL(g
.tree
, parent
.OnPullDownHighlight
) 
 115         # Mapping from IDs to element names 
 117             ID_NEW
.PANEL
: 'wxPanel', 
 118             ID_NEW
.DIALOG
: 'wxDialog', 
 119             ID_NEW
.FRAME
: 'wxFrame', 
 120             ID_NEW
.TOOL_BAR
: 'wxToolBar', 
 122             ID_NEW
.MENU_BAR
: 'wxMenuBar', 
 123             ID_NEW
.MENU
: 'wxMenu', 
 124             ID_NEW
.MENU_ITEM
: 'wxMenuItem', 
 125             ID_NEW
.SEPARATOR
: 'separator', 
 127             ID_NEW
.STATIC_TEXT
: 'wxStaticText', 
 128             ID_NEW
.TEXT_CTRL
: 'wxTextCtrl', 
 130             ID_NEW
.BUTTON
: 'wxButton', 
 131             ID_NEW
.BITMAP_BUTTON
: 'wxBitmapButton', 
 132             ID_NEW
.RADIO_BUTTON
: 'wxRadioButton', 
 133             ID_NEW
.SPIN_BUTTON
: 'wxSpinButton', 
 134             ID_NEW
.TOGGLE_BUTTON
: 'wxToggleButton', 
 136             ID_NEW
.STATIC_BOX
: 'wxStaticBox', 
 137             ID_NEW
.CHECK_BOX
: 'wxCheckBox', 
 138             ID_NEW
.RADIO_BOX
: 'wxRadioBox', 
 139             ID_NEW
.COMBO_BOX
: 'wxComboBox', 
 140             ID_NEW
.LIST_BOX
: 'wxListBox', 
 142             ID_NEW
.STATIC_LINE
: 'wxStaticLine', 
 143             ID_NEW
.STATIC_BITMAP
: 'wxStaticBitmap', 
 144             ID_NEW
.CHOICE
: 'wxChoice', 
 145             ID_NEW
.SLIDER
: 'wxSlider', 
 146             ID_NEW
.GAUGE
: 'wxGauge', 
 147             ID_NEW
.SCROLL_BAR
: 'wxScrollBar', 
 148             ID_NEW
.TREE_CTRL
: 'wxTreeCtrl', 
 149             ID_NEW
.LIST_CTRL
: 'wxListCtrl', 
 150             ID_NEW
.CHECK_LIST
: 'wxCheckListBox', 
 151             ID_NEW
.NOTEBOOK
: 'wxNotebook', 
 152             ID_NEW
.SPLITTER_WINDOW
: 'wxSplitterWindow', 
 153             ID_NEW
.SCROLLED_WINDOW
: 'wxScrolledWindow', 
 154             ID_NEW
.HTML_WINDOW
: 'wxHtmlWindow', 
 155             ID_NEW
.CALENDAR_CTRL
: 'wxCalendarCtrl', 
 156             ID_NEW
.GENERIC_DIR_CTRL
: 'wxGenericDirCtrl', 
 157             ID_NEW
.SPIN_CTRL
: 'wxSpinCtrl', 
 159             ID_NEW
.BOX_SIZER
: 'wxBoxSizer', 
 160             ID_NEW
.STATIC_BOX_SIZER
: 'wxStaticBoxSizer', 
 161             ID_NEW
.GRID_SIZER
: 'wxGridSizer', 
 162             ID_NEW
.FLEX_GRID_SIZER
: 'wxFlexGridSizer', 
 163             ID_NEW
.GRID_BAG_SIZER
: 'wxGridBagSizer', 
 164             ID_NEW
.SPACER
: 'spacer', 
 165             ID_NEW
.UNKNOWN
: 'unknown', 
 168             (ID_NEW
.PANEL
, 'Panel', 'Create panel'), 
 169             (ID_NEW
.DIALOG
, 'Dialog', 'Create dialog'), 
 170             (ID_NEW
.FRAME
, 'Frame', 'Create frame'), 
 172             (ID_NEW
.TOOL_BAR
, 'ToolBar', 'Create toolbar'), 
 173             (ID_NEW
.MENU_BAR
, 'MenuBar', 'Create menubar'), 
 174             (ID_NEW
.MENU
, 'Menu', 'Create menu') 
 177              (ID_NEW
.PANEL
, 'Panel', 'Create panel'), 
 178              (ID_NEW
.NOTEBOOK
, 'Notebook', 'Create notebook control'), 
 179              (ID_NEW
.SPLITTER_WINDOW
, 'SplitterWindow', 'Create splitter window'), 
 180              (ID_NEW
.TOOL_BAR
, 'ToolBar', 'Create toolbar'), 
 183              (ID_NEW
.BOX_SIZER
, 'BoxSizer', 'Create box sizer'), 
 184              (ID_NEW
.STATIC_BOX_SIZER
, 'StaticBoxSizer', 
 185               'Create static box sizer'), 
 186              (ID_NEW
.GRID_SIZER
, 'GridSizer', 'Create grid sizer'), 
 187              (ID_NEW
.FLEX_GRID_SIZER
, 'FlexGridSizer', 
 188               'Create flexgrid sizer'), 
 189              (ID_NEW
.GRID_BAG_SIZER
, 'GridBagSizer', 
 190               'Create gridbag sizer'), 
 191              (ID_NEW
.SPACER
, 'Spacer', 'Create spacer'), 
 194             ['control', 'Various controls', 
 195              (ID_NEW
.STATIC_TEXT
, 'Label', 'Create label'), 
 196              (ID_NEW
.STATIC_BITMAP
, 'Bitmap', 'Create bitmap'), 
 197              (ID_NEW
.STATIC_LINE
, 'Line', 'Create line'), 
 198              (ID_NEW
.TEXT_CTRL
, 'TextBox', 'Create text box'), 
 199              (ID_NEW
.CHOICE
, 'Choice', 'Create choice'), 
 200              (ID_NEW
.SLIDER
, 'Slider', 'Create slider'), 
 201              (ID_NEW
.GAUGE
, 'Gauge', 'Create gauge'), 
 202              (ID_NEW
.SPIN_CTRL
, 'SpinCtrl', 'Create spin'), 
 203              (ID_NEW
.SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'), 
 204              (ID_NEW
.TREE_CTRL
, 'TreeCtrl', 'Create tree'), 
 205              (ID_NEW
.LIST_CTRL
, 'ListCtrl', 'Create list'), 
 206              (ID_NEW
.CHECK_LIST
, 'CheckList', 'Create check list'), 
 207              (ID_NEW
.SCROLLED_WINDOW
, 'ScrolledWindow', 'Create scrolled window'), 
 208              (ID_NEW
.HTML_WINDOW
, 'HtmlWindow', 'Create HTML window'), 
 209              (ID_NEW
.CALENDAR_CTRL
, 'CalendarCtrl', 'Create calendar control'), 
 210              (ID_NEW
.GENERIC_DIR_CTRL
, 'GenericDirCtrl', 'Create generic dir control'), 
 211              (ID_NEW
.UNKNOWN
, 'Unknown', 'Create custom control placeholder'), 
 213             ['button', 'Buttons', 
 214              (ID_NEW
.BUTTON
, 'Button', 'Create button'), 
 215              (ID_NEW
.BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'), 
 216              (ID_NEW
.RADIO_BUTTON
, 'RadioButton', 'Create radio button'), 
 217              (ID_NEW
.SPIN_BUTTON
, 'SpinButton', 'Create spin button'), 
 218              (ID_NEW
.TOGGLE_BUTTON
, 'ToggleButton', 'Create toggle button'), 
 221              (ID_NEW
.STATIC_BOX
, 'StaticBox', 'Create static box'), 
 222              (ID_NEW
.CHECK_BOX
, 'CheckBox', 'Create check box'), 
 223              (ID_NEW
.RADIO_BOX
, 'RadioBox', 'Create radio box'), 
 224              (ID_NEW
.COMBO_BOX
, 'ComboBox', 'Create combo box'), 
 225              (ID_NEW
.LIST_BOX
, 'ListBox', 'Create list box'), 
 227             ['container', 'Containers', 
 228              (ID_NEW
.PANEL
, 'Panel', 'Create panel'), 
 229              (ID_NEW
.NOTEBOOK
, 'Notebook', 'Create notebook control'), 
 230              (ID_NEW
.SPLITTER_WINDOW
, 'SplitterWindow', 'Create splitter window'), 
 231              (ID_NEW
.TOOL_BAR
, 'ToolBar', 'Create toolbar'), 
 234              (ID_NEW
.BOX_SIZER
, 'BoxSizer', 'Create box sizer'), 
 235              (ID_NEW
.STATIC_BOX_SIZER
, 'StaticBoxSizer', 
 236               'Create static box sizer'), 
 237              (ID_NEW
.GRID_SIZER
, 'GridSizer', 'Create grid sizer'), 
 238              (ID_NEW
.FLEX_GRID_SIZER
, 'FlexGridSizer', 
 239               'Create flexgrid sizer'), 
 240              (ID_NEW
.GRID_BAG_SIZER
, 'GridBagSizer', 
 241               'Create gridbag sizer'), 
 242              (ID_NEW
.SPACER
, 'Spacer', 'Create spacer'), 
 245         self
.menuControls 
= [ 
 246             (ID_NEW
.MENU
, 'Menu', 'Create menu'), 
 247             (ID_NEW
.MENU_ITEM
, 'MenuItem', 'Create menu item'), 
 248             (ID_NEW
.SEPARATOR
, 'Separator', 'Create separator'), 
 250         self
.toolBarControls 
= [ 
 251             (ID_NEW
.TOOL
, 'Tool', 'Create tool'), 
 252             (ID_NEW
.SEPARATOR
, 'Separator', 'Create separator'), 
 253             ['control', 'Various controls', 
 254              (ID_NEW
.STATIC_TEXT
, 'Label', 'Create label'), 
 255              (ID_NEW
.STATIC_BITMAP
, 'Bitmap', 'Create bitmap'), 
 256              (ID_NEW
.STATIC_LINE
, 'Line', 'Create line'), 
 257              (ID_NEW
.TEXT_CTRL
, 'TextBox', 'Create text box'), 
 258              (ID_NEW
.CHOICE
, 'Choice', 'Create choice'), 
 259              (ID_NEW
.SLIDER
, 'Slider', 'Create slider'), 
 260              (ID_NEW
.GAUGE
, 'Gauge', 'Create gauge'), 
 261              (ID_NEW
.SCROLL_BAR
, 'ScrollBar', 'Create scroll bar'), 
 262              (ID_NEW
.LIST_CTRL
, 'ListCtrl', 'Create list control'), 
 263              (ID_NEW
.CHECK_LIST
, 'CheckList', 'Create check list'), 
 265             ['button', 'Buttons', 
 266              (ID_NEW
.BUTTON
, 'Button', 'Create button'), 
 267              (ID_NEW
.BITMAP_BUTTON
, 'BitmapButton', 'Create bitmap button'), 
 268              (ID_NEW
.RADIO_BUTTON
, 'RadioButton', 'Create radio button'), 
 269              (ID_NEW
.SPIN_BUTTON
, 'SpinButton', 'Create spin button'), 
 272              (ID_NEW
.STATIC_BOX
, 'StaticBox', 'Create static box'), 
 273              (ID_NEW
.CHECK_BOX
, 'CheckBox', 'Create check box'), 
 274              (ID_NEW
.RADIO_BOX
, 'RadioBox', 'Create radio box'), 
 275              (ID_NEW
.COMBO_BOX
, 'ComboBox', 'Create combo box'), 
 276              (ID_NEW
.LIST_BOX
, 'ListBox', 'Create list box'), 
 280 ################################################################################ 
 282 # Set menu to list items. 
 283 # Each menu command is a tuple (id, label, help) 
 284 # submenus are lists [id, label, help, submenu] 
 285 # and separators are any other type 
 286 def SetMenu(m
, list): 
 288         if type(l
) == types
.TupleType
: 
 290         elif type(l
) == types
.ListType
: 
 292             SetMenu(subMenu
, l
[2:]) 
 293             m
.AppendMenu(wxNewId(), l
[0], subMenu
, l
[1]) 
 296 # Same, but adds 1000 to all IDs 
 297 def SetMenu2(m
, list): 
 299         if type(l
) == types
.TupleType
: 
 301             l 
= (1000 + l
[0],) + l
[1:] 
 303         elif type(l
) == types
.ListType
: 
 305             SetMenu2(subMenu
, l
[2:]) 
 306             m
.AppendMenu(wxNewId(), l
[0], subMenu
, l
[1]) 
 310 ################################################################################ 
 313     def __init__(self
, pos
, size
): 
 314         if size
.width 
== -1: size
.width 
= 0 
 315         if size
.height 
== -1: size
.height 
= 0 
 317         l1 
= wxWindow(w
, -1, pos
, wxSize(size
.width
, 2)) 
 318         l1
.SetBackgroundColour(wxRED
) 
 319         l2 
= wxWindow(w
, -1, pos
, wxSize(2, size
.height
)) 
 320         l2
.SetBackgroundColour(wxRED
) 
 321         l3 
= wxWindow(w
, -1, wxPoint(pos
.x 
+ size
.width 
- 2, pos
.y
), wxSize(2, size
.height
)) 
 322         l3
.SetBackgroundColour(wxRED
) 
 323         l4 
= wxWindow(w
, -1, wxPoint(pos
.x
, pos
.y 
+ size
.height 
- 2), wxSize(size
.width
, 2)) 
 324         l4
.SetBackgroundColour(wxRED
) 
 325         self
.lines 
= [l1
, l2
, l3
, l4
] 
 326     # Move highlight to a new position 
 327     def Replace(self
, pos
, size
): 
 328         if size
.width 
== -1: size
.width 
= 0 
 329         if size
.height 
== -1: size
.height 
= 0 
 330         self
.lines
[0].SetDimensions(pos
.x
, pos
.y
, size
.width
, 2) 
 331         self
.lines
[1].SetDimensions(pos
.x
, pos
.y
, 2, size
.height
) 
 332         self
.lines
[2].SetDimensions(pos
.x 
+ size
.width 
- 2, pos
.y
, 2, size
.height
) 
 333         self
.lines
[3].SetDimensions(pos
.x
, pos
.y 
+ size
.height 
- 2, size
.width
, 2) 
 336         map(wxWindow
.Destroy
, self
.lines
) 
 337         g
.testWin
.highLight 
= None 
 339 ################################################################################ 
 341 class XML_Tree(wxTreeCtrl
): 
 342     def __init__(self
, parent
, id): 
 343         wxTreeCtrl
.__init
__(self
, parent
, id, style 
= wxTR_HAS_BUTTONS
) 
 344         self
.SetBackgroundColour(wxColour(224, 248, 224)) 
 346         EVT_TREE_SEL_CHANGED(self
, self
.GetId(), self
.OnSelChanged
) 
 347         # One works on Linux, another on Windows 
 348         if wxPlatform 
== '__WXGTK__': 
 349             EVT_TREE_ITEM_ACTIVATED(self
, self
.GetId(), self
.OnItemActivated
) 
 351             EVT_LEFT_DCLICK(self
, self
.OnDClick
) 
 352         EVT_RIGHT_DOWN(self
, self
.OnRightDown
) 
 353         EVT_TREE_ITEM_EXPANDED(self
, self
.GetId(), self
.OnItemExpandedCollapsed
) 
 354         EVT_TREE_ITEM_COLLAPSED(self
, self
.GetId(), self
.OnItemExpandedCollapsed
) 
 356         self
.selection 
= None 
 357         self
.needUpdate 
= False 
 358         self
.pendingHighLight 
= None 
 359         self
.ctrl 
= self
.shift 
= False 
 362         il 
= wxImageList(16, 16, True) 
 363         self
.rootImage 
= il
.Add(images
.getTreeRootImage().Scale(16,16).ConvertToBitmap()) 
 364         xxxObject
.image 
= il
.Add(images
.getTreeDefaultImage().Scale(16,16).ConvertToBitmap()) 
 365         xxxPanel
.image 
= il
.Add(images
.getTreePanelImage().Scale(16,16).ConvertToBitmap()) 
 366         xxxDialog
.image 
= il
.Add(images
.getTreeDialogImage().Scale(16,16).ConvertToBitmap()) 
 367         xxxFrame
.image 
= il
.Add(images
.getTreeFrameImage().Scale(16,16).ConvertToBitmap()) 
 368         xxxMenuBar
.image 
= il
.Add(images
.getTreeMenuBarImage().Scale(16,16).ConvertToBitmap()) 
 369         xxxMenu
.image 
= il
.Add(images
.getTreeMenuImage().Scale(16,16).ConvertToBitmap()) 
 370         xxxMenuItem
.image 
= il
.Add(images
.getTreeMenuItemImage().Scale(16,16).ConvertToBitmap()) 
 371         xxxToolBar
.image 
= il
.Add(images
.getTreeToolBarImage().Scale(16,16).ConvertToBitmap()) 
 372         xxxTool
.image 
= il
.Add(images
.getTreeToolImage().Scale(16,16).ConvertToBitmap()) 
 373         xxxSeparator
.image 
= il
.Add(images
.getTreeSeparatorImage().Scale(16,16).ConvertToBitmap()) 
 374         xxxSizer
.imageH 
= il
.Add(images
.getTreeSizerHImage().Scale(16,16).ConvertToBitmap()) 
 375         xxxSizer
.imageV 
= il
.Add(images
.getTreeSizerVImage().Scale(16,16).ConvertToBitmap()) 
 376         xxxStaticBoxSizer
.imageH 
= il
.Add(images
.getTreeStaticBoxSizerHImage().Scale(16,16).ConvertToBitmap()) 
 377         xxxStaticBoxSizer
.imageV 
= il
.Add(images
.getTreeStaticBoxSizerVImage().Scale(16,16).ConvertToBitmap()) 
 378         xxxGridSizer
.image 
= il
.Add(images
.getTreeSizerGridImage().Scale(16,16).ConvertToBitmap()) 
 379         xxxFlexGridSizer
.image 
= il
.Add(images
.getTreeSizerFlexGridImage().Scale(16,16).ConvertToBitmap()) 
 381         self
.SetImageList(il
) 
 383     def RegisterKeyEvents(self
): 
 384         EVT_KEY_DOWN(self
, g
.tools
.OnKeyDown
) 
 385         EVT_KEY_UP(self
, g
.tools
.OnKeyUp
) 
 386         EVT_ENTER_WINDOW(self
, g
.tools
.OnMouse
) 
 387         EVT_LEAVE_WINDOW(self
, g
.tools
.OnMouse
) 
 390         self
.selection 
= None 
 391         wxTreeCtrl
.Unselect(self
) 
 394     def ExpandAll(self
, item
): 
 395         if self
.ItemHasChildren(item
): 
 397             i
, cookie 
= self
.GetFirstChild(item
) 
 401                 i
, cookie 
= self
.GetNextChild(item
, cookie
) 
 404     def CollapseAll(self
, item
): 
 405         if self
.ItemHasChildren(item
): 
 406             i
, cookie 
= self
.GetFirstChild(item
) 
 410                 i
, cookie 
= self
.GetNextChild(item
, cookie
) 
 417         self
.DeleteAllItems() 
 418         # Add minimal structure 
 419         if self
.dom
: self
.dom
.unlink() 
 420         self
.dom 
= MyDocument() 
 421         self
.dummyNode 
= self
.dom
.createComment('dummy node') 
 423         self
.mainNode 
= self
.dom
.createElement('resource') 
 424         self
.dom
.appendChild(self
.mainNode
) 
 425         self
.rootObj 
= xxxMainNode(self
.dom
) 
 426         self
.root 
= self
.AddRoot('XML tree', self
.rootImage
, 
 427                                  data
=wxTreeItemData(self
.rootObj
)) 
 428         self
.SetItemHasChildren(self
.root
) 
 430         self
.Expand(self
.root
) 
 432     # Clear old data and set new 
 433     def SetData(self
, dom
): 
 434         self
.DeleteAllItems() 
 435         # Add minimal structure 
 436         if self
.dom
: self
.dom
.unlink() 
 438         self
.dummyNode 
= self
.dom
.createComment('dummy node') 
 439         # Find 'resource' child, add it's children 
 440         self
.mainNode 
= dom
.documentElement
 
 441         self
.rootObj 
= xxxMainNode(self
.dom
) 
 442         self
.root 
= self
.AddRoot('XML tree', self
.rootImage
, 
 443                                  data
=wxTreeItemData(self
.rootObj
)) 
 444         self
.SetItemHasChildren(self
.root
) 
 445         nodes 
= self
.mainNode
.childNodes
[:] 
 448                 self
.AddNode(self
.root
, None, node
) 
 450                 self
.mainNode
.removeChild(node
) 
 452         self
.Expand(self
.root
) 
 455     # Add tree item for given parent item if node is DOM element node with 
 456     # 'object' tag. xxxParent is parent xxx object 
 457     def AddNode(self
, itemParent
, xxxParent
, node
): 
 458         # Set item data to current node 
 460             xxx 
= MakeXXXFromDOM(xxxParent
, node
) 
 462             print 'ERROR: MakeXXXFromDom(%s, %s)' % (xxxParent
, node
) 
 464         treeObj 
= xxx
.treeObject() 
 466         item 
= self
.AppendItem(itemParent
, treeObj
.treeName(), 
 467                                image
=treeObj
.treeImage(), 
 468                                data
=wxTreeItemData(xxx
)) 
 469         # Try to find children objects 
 470         if treeObj
.hasChildren
: 
 471             nodes 
= treeObj
.element
.childNodes
[:] 
 474                     self
.AddNode(item
, treeObj
, n
) 
 475                 elif n
.nodeType 
!= minidom
.Node
.ELEMENT_NODE
: 
 476                     treeObj
.element
.removeChild(n
) 
 479     # Insert new item at specific position 
 480     def InsertNode(self
, itemParent
, parent
, elem
, nextItem
): 
 481         # Insert in XML tree and wxWin 
 482         xxx 
= MakeXXXFromDOM(parent
, elem
) 
 483         # If nextItem is None, we append to parent, otherwise insert before it 
 485             node 
= self
.GetPyData(nextItem
).element
 
 486             parent
.element
.insertBefore(elem
, node
) 
 487             # Inserting before is difficult, se we insert after or first child 
 488             index 
= self
.ItemIndex(nextItem
) 
 489             newItem 
= self
.InsertItemBefore(itemParent
, index
, 
 490                         xxx
.treeName(), image
=xxx
.treeImage()) 
 491             self
.SetPyData(newItem
, xxx
) 
 493             parent
.element
.appendChild(elem
) 
 494             newItem 
= self
.AppendItem(itemParent
, xxx
.treeName(), image
=xxx
.treeImage(), 
 495                                       data
=wxTreeItemData(xxx
)) 
 498             treeObj 
= xxx
.treeObject() 
 499             for n 
in treeObj
.element
.childNodes
: 
 501                     self
.AddNode(newItem
, treeObj
, n
) 
 504     # Remove leaf of tree, return it's data object 
 505     def RemoveLeaf(self
, leaf
): 
 506         xxx 
= self
.GetPyData(leaf
) 
 508         parent 
= node
.parentNode
 
 509         parent
.removeChild(node
) 
 511         # Reset selection object 
 512         self
.selection 
= None 
 514     # Find position relative to the top-level window 
 515     def FindNodePos(self
, item
): 
 517         if item 
== g
.testWin
.item
: return wxPoint(0, 0) 
 518         itemParent 
= self
.GetItemParent(item
) 
 520         obj 
= self
.FindNodeObject(item
) 
 521         if self
.GetPyData(itemParent
).treeObject().__class
__ == xxxNotebook
: 
 522             notebook 
= self
.FindNodeObject(itemParent
) 
 524             for i 
in range(notebook
.GetPageCount()): 
 525                 if notebook
.GetPage(i
) == obj
: 
 526                     if notebook
.GetSelection() != i
: notebook
.SetSelection(i
) 
 528         # Find first ancestor which is a wxWindow (not a sizer) 
 529         winParent 
= itemParent
 
 530         while self
.GetPyData(winParent
).isSizer
: 
 531             winParent 
= self
.GetItemParent(winParent
) 
 532         parentPos 
= self
.FindNodePos(winParent
) 
 533         # Position (-1,-1) is really (0,0) 
 534         pos 
= obj
.GetPosition() 
 535         if pos 
== (-1,-1): pos 
= (0,0) 
 536         return parentPos 
+ pos
 
 538     # Find window (or sizer) corresponding to a tree item. 
 539     def FindNodeObject(self
, item
): 
 541         # If top-level, return testWin (or panel its panel) 
 542         if item 
== testWin
.item
: return testWin
.panel
 
 543         itemParent 
= self
.GetItemParent(item
) 
 544         xxx 
= self
.GetPyData(item
).treeObject() 
 545         parentWin 
= self
.FindNodeObject(itemParent
) 
 546         # Top-level sizer? return window's sizer 
 547         if xxx
.isSizer 
and isinstance(parentWin
, wxWindow
): 
 548             return parentWin
.GetSizer() 
 549         # Otherwise get parent's object and it's child 
 550         child 
= parentWin
.GetChildren()[self
.ItemIndex(item
)] 
 551         # Return window or sizer for sizer items 
 552         if child
.GetClassName() == 'wxSizerItem': 
 553             if child
.IsWindow(): child 
= child
.GetWindow() 
 554             elif child
.IsSizer(): 
 555                 child 
= child
.GetSizer() 
 556                 # Test for notebook sizers 
 557                 if isinstance(child
, wxNotebookSizer
): 
 558                     child 
= child
.GetNotebook() 
 561     def OnSelChanged(self
, evt
): 
 563         # !!! problem with wxGTK - GetOldItem is Ok if nothing selected 
 564         #oldItem = evt.GetOldItem() 
 566         oldItem 
= self
.selection
 
 568             xxx 
= self
.GetPyData(oldItem
) 
 569             # If some data was modified, apply changes 
 570             if g
.panel
.IsModified(): 
 571                 self
.Apply(xxx
, oldItem
) 
 572                 #if conf.autoRefresh: 
 574                     if g
.testWin
.highLight
: 
 575                         g
.testWin
.highLight
.Remove() 
 576                     self
.needUpdate 
= True 
 577                 status 
= 'Changes were applied' 
 578         g
.frame
.SetStatusText(status
) 
 580         self
.selection 
= evt
.GetItem() 
 581         if not self
.selection
.IsOk(): 
 582             self
.selection 
= None 
 584         xxx 
= self
.GetPyData(self
.selection
) 
 589         # Hightlighting is done in OnIdle 
 590         self
.pendingHighLight 
= self
.selection
 
 592     # Check if item is in testWin subtree 
 593     def IsHighlatable(self
, item
): 
 594         if item 
== g
.testWin
.item
: return False 
 595         while item 
!= self
.root
: 
 596             item 
= self
.GetItemParent(item
) 
 597             if item 
== g
.testWin
.item
: return True 
 600     # Highlight selected item 
 601     def HighLight(self
, item
): 
 602         self
.pendingHighLight 
= None 
 603         # Can highlight only with some top-level windows 
 604         if not g
.testWin 
or self
.GetPyData(g
.testWin
.item
).treeObject().__class
__ \
 
 605             not in [xxxDialog
, xxxPanel
, xxxFrame
]: 
 607         # If a control from another window is selected, remove highlight 
 608         if not self
.IsHighlatable(item
): 
 609             if g
.testWin
.highLight
: g
.testWin
.highLight
.Remove() 
 611         # Get window/sizer object 
 612         obj
, pos 
= self
.FindNodeObject(item
), self
.FindNodePos(item
) 
 615         # Nagative positions are not working wuite well 
 616         if g
.testWin
.highLight
: 
 617             g
.testWin
.highLight
.Replace(pos
, size
) 
 619             g
.testWin
.highLight 
= HighLightBox(pos
, size
) 
 620         g
.testWin
.highLight
.item 
= item
 
 622     def ShowTestWindow(self
, item
): 
 623         xxx 
= self
.GetPyData(item
) 
 624         if g
.panel
.IsModified(): 
 625             self
.Apply(xxx
, item
)       # apply changes 
 626         treeObj 
= xxx
.treeObject() 
 627         if treeObj
.className 
not in ['wxFrame', 'wxPanel', 'wxDialog', 
 628                                      'wxMenuBar', 'wxToolBar']: 
 629             wxLogMessage('No view for this element (yet)') 
 632         if g
.testWin
:     # Reset old 
 633             self
.SetItemBold(g
.testWin
.item
, False) 
 634         self
.CreateTestWin(item
) 
 635         # Maybe an error occured, so we need to test 
 636         if g
.testWin
: self
.SetItemBold(g
.testWin
.item
) 
 638     # Double-click on Linux 
 639     def OnItemActivated(self
, evt
): 
 640         if evt
.GetItem() != self
.root
: 
 641             self
.ShowTestWindow(evt
.GetItem()) 
 643     # Double-click on Windows 
 644     def OnDClick(self
, evt
): 
 645         item
, flags 
= self
.HitTest(evt
.GetPosition()) 
 646         if flags 
in [wxTREE_HITTEST_ONITEMBUTTON
, wxTREE_HITTEST_ONITEMLABEL
]: 
 647             if item 
!= self
.root
: self
.ShowTestWindow(item
) 
 651     def OnItemExpandedCollapsed(self
, evt
): 
 652         # Update tool palette 
 656     # (re)create test window 
 657     def CreateTestWin(self
, item
): 
 659         # Create a window with this resource 
 660         xxx 
= self
.GetPyData(item
).treeObject() 
 663 #        if xxx.__class__ == xxxFrame: 
 664             # Frame can't have many children, 
 665             # but it's first child possibly can... 
 666 #            child = self.GetFirstChild(item)[0] 
 667 #            if child.IsOk() and self.GetPyData(child).__class__ == xxxPanel: 
 668 #                # Clean-up before recursive call or error 
 669 #                wxMemoryFSHandler_RemoveFile('xxx.xrc') 
 671 #                self.CreateTestWin(child) 
 676         # Close old window, remember where it was 
 679             pos 
= testWin
.GetPosition() 
 680             if item 
== testWin
.item
: 
 681                 # Remember highlight if same top-level window 
 682                 if testWin
.highLight
: 
 683                     highLight 
= testWin
.highLight
.item
 
 684                 if xxx
.className 
== 'wxPanel': 
 685                     if testWin
.highLight
: 
 686                         testWin
.pendingHighLight 
= highLight
 
 687                         testWin
.highLight
.Remove() 
 688                     testWin
.panel
.Destroy() 
 692                     testWin 
= g
.testWin 
= None 
 695                 testWin 
= g
.testWin 
= None 
 699         memFile 
= MemoryFile('xxx.xrc') 
 700         # Create partial XML file - faster for big files 
 703         mainNode 
= dom
.createElement('resource') 
 704         dom
.appendChild(mainNode
) 
 706         # Remove temporarily from old parent 
 708         # Change window id to _XRCED_T_W. This gives some name for 
 709         # unnamed windows, and for named gives the possibility to 
 710         # write sawfish scripts. 
 715         elem
.setAttribute('name', STD_NAME
) 
 716         parent 
= elem
.parentNode
 
 717         next 
= elem
.nextSibling
 
 718         parent
.replaceChild(self
.dummyNode
, elem
) 
 719         # Append to new DOM, write it 
 720         mainNode
.appendChild(elem
) 
 721         dom
.writexml(memFile
, encoding
=self
.rootObj
.params
['encoding'].value()) 
 723         mainNode
.removeChild(elem
) 
 725         parent
.replaceChild(elem
, self
.dummyNode
) 
 726         # Remove temporary name or restore changed 
 728             elem
.removeAttribute('name') 
 730             elem
.setAttribute('name', xxx
.name
) 
 731         memFile
.close()                 # write to wxMemoryFS 
 732         xmlFlags 
= wxXRC_NO_SUBCLASSING
 
 733         # Use translations if encoding is not specified 
 734         if g
.currentEncoding 
== 'ascii': 
 735             xmlFlags 
!= wxXRC_USE_LOCALE
 
 736         res 
= wxXmlResource('', xmlFlags
) 
 737         res
.Load('memory:xxx.xrc') 
 739             if xxx
.__class
__ == xxxFrame
: 
 740                 # Frame can't have many children, 
 741                 # but it's first child possibly can... 
 742     #            child = self.GetFirstChild(item)[0] 
 743     #            if child.IsOk() and self.GetPyData(child).__class__ == xxxPanel: 
 744     #                # Clean-up before recursive call or error 
 745     #                wxMemoryFSHandler_RemoveFile('xxx.xrc') 
 747     #                self.CreateTestWin(child) 
 749                 # This currently works under GTK, but not under MSW 
 750                 testWin 
= g
.testWin 
= wxPreFrame() 
 751                 res
.LoadOnFrame(testWin
, g
.frame
, STD_NAME
) 
 753                 testWin
.panel 
= testWin
 
 754                 testWin
.CreateStatusBar() 
 755                 testWin
.SetClientSize(testWin
.GetBestSize()) 
 756                 testWin
.panel 
= testWin
 
 757                 testWin
.SetPosition(pos
) 
 759             elif xxx
.__class
__ == xxxPanel
: 
 762                     testWin 
= g
.testWin 
= wxFrame(g
.frame
, -1, 'Panel: ' + name
, 
 763                                                   pos
=pos
, name
=STD_NAME
) 
 764                 testWin
.panel 
= res
.LoadPanel(testWin
, STD_NAME
) 
 765                 testWin
.SetClientSize(testWin
.GetBestSize()) 
 767             elif xxx
.__class
__ == xxxDialog
: 
 768                 testWin 
= g
.testWin 
= res
.LoadDialog(None, STD_NAME
) 
 769                 testWin
.panel 
= testWin
 
 771                 testWin
.SetPosition(pos
) 
 773                 # Dialog's default code does not produce EVT_CLOSE 
 774                 EVT_BUTTON(testWin
, wxID_OK
, self
.OnCloseTestWin
) 
 775                 EVT_BUTTON(testWin
, wxID_CANCEL
, self
.OnCloseTestWin
) 
 776             elif xxx
.__class
__ == xxxMenuBar
: 
 777                 testWin 
= g
.testWin 
= wxFrame(g
.frame
, -1, 'MenuBar: ' + name
, 
 778                                               pos
=pos
, name
=STD_NAME
) 
 780                 # Set status bar to display help 
 781                 testWin
.CreateStatusBar() 
 782                 testWin
.menuBar 
= res
.LoadMenuBar(STD_NAME
) 
 783                 testWin
.SetMenuBar(testWin
.menuBar
) 
 785             elif xxx
.__class
__ == xxxToolBar
: 
 786                 testWin 
= g
.testWin 
= wxFrame(g
.frame
, -1, 'ToolBar: ' + name
, 
 787                                               pos
=pos
, name
=STD_NAME
) 
 789                 # Set status bar to display help 
 790                 testWin
.CreateStatusBar() 
 791                 testWin
.toolBar 
= res
.LoadToolBar(testWin
, STD_NAME
) 
 792                 testWin
.SetToolBar(testWin
.toolBar
) 
 795             EVT_CLOSE(testWin
, self
.OnCloseTestWin
) 
 796             testWin
.highLight 
= None 
 797             if highLight 
and not self
.pendingHighLight
: 
 798                 self
.HighLight(highLight
) 
 801                 self
.SetItemBold(item
, False) 
 802                 g
.testWinPos 
= g
.testWin
.GetPosition() 
 806             wxLogError(traceback
.format_exception(inf
[0], inf
[1], None)[-1]) 
 807             wxLogError('Error loading resource') 
 808         wxMemoryFSHandler_RemoveFile('xxx.xrc') 
 811     def OnCloseTestWin(self
, evt
): 
 812         self
.SetItemBold(g
.testWin
.item
, False) 
 813         g
.testWinPos 
= g
.testWin
.GetPosition() 
 817     # Return item index in parent 
 818     def ItemIndex(self
, item
): 
 819         n 
= 0                           # index of sibling 
 820         prev 
= self
.GetPrevSibling(item
) 
 822             prev 
= self
.GetPrevSibling(prev
) 
 826     # Full tree index of an item - list of positions 
 827     def ItemFullIndex(self
, item
): 
 828         if not item
.IsOk(): return None 
 830         while item 
!= self
.root
: 
 831             l
.insert(0, self
.ItemIndex(item
)) 
 832             item 
= self
.GetItemParent(item
) 
 834     # Get item position from full index 
 835     def ItemAtFullIndex(self
, index
): 
 836         if index 
is None: return wxTreeItemId() 
 839             item 
= self
.GetFirstChild(item
)[0] 
 840             for k 
in range(i
): item 
= self
.GetNextSibling(item
) 
 843     # True if next item should be inserted after current (vs. appended to it) 
 844     def NeedInsert(self
, item
): 
 845         xxx 
= self
.GetPyData(item
) 
 846         if item 
== self
.root
: return False        # root item 
 847         if xxx
.hasChildren 
and not self
.GetChildrenCount(item
, False): 
 849         return not (self
.IsExpanded(item
) and self
.GetChildrenCount(item
, False)) 
 852     def OnRightDown(self
, evt
): 
 853         pullDownMenu 
= g
.pullDownMenu
 
 855         pt 
= evt
.GetPosition(); 
 856         item
, flags 
= self
.HitTest(pt
) 
 857         if item
.Ok() and flags 
& wxTREE_HITTEST_ONITEM
: 
 858             self
.SelectItem(item
) 
 863         item 
= self
.selection
 
 865             menu
.Append(g
.pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand tree') 
 866             menu
.Append(g
.pullDownMenu
.ID_COLLAPSE
, 'Collapse', 'Collapse tree') 
 868 #            self.ctrl = evt.ControlDown() # save Ctrl state 
 869 #            self.shift = evt.ShiftDown()  # and Shift too 
 870             m 
= wxMenu()                  # create menu 
 874                 needInsert 
= self
.NeedInsert(item
) 
 875             if item 
== self
.root 
or needInsert 
and self
.GetItemParent(item
) == self
.root
: 
 876                 SetMenu(m
, pullDownMenu
.topLevel
) 
 878                 xxx 
= self
.GetPyData(item
).treeObject() 
 879                 # Check parent for possible child nodes if inserting sibling 
 880                 if needInsert
: xxx 
= xxx
.parent
 
 881                 if xxx
.__class
__ == xxxMenuBar
: 
 882                     m
.Append(ID_NEW
.MENU
, 'Menu', 'Create menu') 
 883                 elif xxx
.__class
__ in [xxxToolBar
, xxxTool
] or \
 
 884                      xxx
.__class
__ == xxxSeparator 
and xxx
.parent
.__class
__ == xxxToolBar
: 
 885                     SetMenu(m
, pullDownMenu
.toolBarControls
) 
 886                 elif xxx
.__class
__ in [xxxMenu
, xxxMenuItem
]: 
 887                     SetMenu(m
, pullDownMenu
.menuControls
) 
 889                     SetMenu(m
, pullDownMenu
.controls
) 
 890                     if xxx
.__class
__ == xxxNotebook
: 
 891                         m
.Enable(m
.FindItem('sizer'), False) 
 892                     elif not (xxx
.isSizer 
or xxx
.parent 
and xxx
.parent
.isSizer
): 
 893                         m
.Enable(ID_NEW
.SPACER
, False) 
 894             # Select correct label for create menu 
 897                     menu
.AppendMenu(wxNewId(), 'Insert Child', m
, 
 898                                     'Create child object as the first child') 
 900                     menu
.AppendMenu(wxNewId(), 'Append Child', m
, 
 901                                     'Create child object as the last child') 
 904                     menu
.AppendMenu(wxNewId(), 'Create Sibling', m
, 
 905                                     'Create sibling before selected object') 
 907                     menu
.AppendMenu(wxNewId(), 'Create Sibling', m
, 
 908                                     'Create sibling after selected object') 
 910             if item 
!= self
.root
: 
 911                 xxx 
= self
.GetPyData(item
).treeObject() 
 912                 m 
= wxMenu()                  # create replace menu 
 913                 if xxx
.__class
__ == xxxMenuBar
: 
 914                     m
.Append(1000 + ID_NEW
.MENU
, 'Menu', 'Create menu') 
 915                 elif xxx
.__class
__ in [xxxMenu
, xxxMenuItem
]: 
 916                     SetMenu2(m
, pullDownMenu
.menuControls
) 
 917                 elif xxx
.__class
__ == xxxToolBar 
and \
 
 918                          self
.GetItemParent(item
) == self
.root
: 
 920                 elif xxx
.__class
__ in [xxxFrame
, xxxDialog
, xxxPanel
]: 
 922                         (ID_NEW
.PANEL
, 'Panel', 'Create panel'), 
 923                         (ID_NEW
.DIALOG
, 'Dialog', 'Create dialog'), 
 924                         (ID_NEW
.FRAME
, 'Frame', 'Create frame')]) 
 926                     SetMenu2(m
, pullDownMenu
.sizers
) 
 928                     SetMenu2(m
, pullDownMenu
.controls
) 
 930                 menu
.AppendMenu(id, 'Replace With', m
) 
 931                 if not m
.GetMenuItemCount(): menu
.Enable(id, False) 
 932                 menu
.Append(pullDownMenu
.ID_SUBCLASS
, 'Subclass...', 
 933                             'Set subclass property') 
 934             menu
.AppendSeparator() 
 935             # Not using standart IDs because we don't want to show shortcuts 
 936             menu
.Append(wxID_CUT
, 'Cut', 'Cut to the clipboard') 
 937             menu
.Append(wxID_COPY
, 'Copy', 'Copy to the clipboard') 
 938             if self
.ctrl 
and item 
!= self
.root
: 
 939                 menu
.Append(pullDownMenu
.ID_PASTE_SIBLING
, 'Paste Sibling', 
 940                             'Paste from the clipboard as a sibling') 
 942                 menu
.Append(wxID_PASTE
, 'Paste', 'Paste from the clipboard') 
 943             menu
.Append(pullDownMenu
.ID_DELETE
, 
 944                                 'Delete', 'Delete object') 
 945             if self
.ItemHasChildren(item
): 
 946                 menu
.AppendSeparator() 
 947                 menu
.Append(pullDownMenu
.ID_EXPAND
, 'Expand', 'Expand subtree') 
 948                 menu
.Append(pullDownMenu
.ID_COLLAPSE
, 'Collapse', 'Collapse subtree') 
 949         self
.PopupMenu(menu
, evt
.GetPosition()) 
 953     def Apply(self
, xxx
, item
): 
 956         xxx 
= xxx
.treeObject() 
 957         if xxx
.hasName 
and self
.GetItemText(item
) != xxx
.name
: 
 958             self
.SetItemText(item
, xxx
.treeName()) 
 959             # Item width may have changed 
 960             # !!! Tric to update tree width (wxGTK, ??) 
 961             self
.SetIndent(self
.GetIndent()) 
 962         # Change tree icon for sizers 
 963         if isinstance(xxx
, xxxBoxSizer
): 
 964             self
.SetItemImage(item
, xxx
.treeImage()) 
 965         # Set global modified state 
 966         g
.frame
.modified 
= True