+
+ def ItemsAreCompatible(self, parent, child):
+ # Check compatibility
+ error = False
+ # Top-level
+ if child.__class__ in [xxxDialog, xxxFrame, xxxWizard]:
+ # Top-level classes
+ if parent.__class__ != xxxMainNode: error = True
+ elif child.__class__ == xxxMenuBar:
+ # Menubar can be put in frame or dialog
+ if parent.__class__ not in [xxxMainNode, xxxFrame, xxxDialog]: error = True
+ elif child.__class__ == xxxToolBar:
+ # Toolbar can be top-level of child of panel or frame
+ if parent.__class__ not in [xxxMainNode, xxxPanel, xxxFrame] and \
+ not parent.isSizer: error = True
+ elif child.__class__ == xxxPanel and parent.__class__ == xxxMainNode:
+ pass
+ elif child.__class__ == xxxSpacer:
+ if not parent.isSizer: error = True
+ elif child.__class__ == xxxSeparator:
+ if not parent.__class__ in [xxxMenu, xxxToolBar]: error = True
+ elif child.__class__ == xxxTool:
+ if parent.__class__ != xxxToolBar: error = True
+ elif child.__class__ == xxxMenu:
+ if not parent.__class__ in [xxxMainNode, xxxMenuBar, xxxMenu]: error = True
+ elif child.__class__ == xxxMenuItem:
+ if not parent.__class__ in [xxxMenuBar, xxxMenu]: error = True
+ elif child.isSizer and parent.__class__ in [xxxNotebook, xxxChoicebook, xxxListbook]:
+ error = True
+ else: # normal controls can be almost anywhere
+ if parent.__class__ == xxxMainNode or \
+ parent.__class__ in [xxxMenuBar, xxxMenu]: error = True
+ if error:
+ if parent.__class__ == xxxMainNode: parentClass = 'root'
+ else: parentClass = parent.className
+ wx.LogError('Incompatible parent/child: parent is %s, child is %s!' %
+ (parentClass, child.className))
+ return False
+ return True
+
+ def OnMoveUp(self, evt):
+ selected = tree.selection
+ if not selected: return
+
+ index = tree.ItemIndex(selected)
+ if index == 0: return # No previous sibling found
+
+ # Undo info
+ self.lastOp = 'MOVEUP'
+ status = 'Moved before previous sibling'
+
+ # Prepare undo data
+ panel.Apply()
+
+ parent = tree.GetItemParent(selected)
+ elem = tree.RemoveLeaf(selected)
+ nextItem = tree.GetFirstChild(parent)[0]
+ for i in range(index - 1): nextItem = tree.GetNextSibling(nextItem)
+ selected = tree.InsertNode(parent, tree.GetPyData(parent).treeObject(), elem, nextItem)
+ newIndex = tree.ItemIndex(selected)
+ tree.SelectItem(selected)
+
+ undoMan.RegisterUndo(UndoMove(parent, index, parent, newIndex))
+
+ self.modified = True
+ self.SetStatusText(status)
+
+ return
+
+ def OnMoveDown(self, evt):
+ selected = tree.selection
+ if not selected: return
+
+ index = tree.ItemIndex(selected)
+ next = tree.GetNextSibling(selected)
+ if not next: return
+
+ # Undo info
+ self.lastOp = 'MOVEDOWN'
+ status = 'Moved after next sibling'
+
+ # Prepare undo data
+ panel.Apply()
+
+ parent = tree.GetItemParent(selected)
+ elem = tree.RemoveLeaf(selected)
+ nextItem = tree.GetFirstChild(parent)[0]
+ for i in range(index + 1): nextItem = tree.GetNextSibling(nextItem)
+ selected = tree.InsertNode(parent, tree.GetPyData(parent).treeObject(), elem, nextItem)
+ newIndex = tree.ItemIndex(selected)
+ tree.SelectItem(selected)
+
+ undoMan.RegisterUndo(UndoMove(parent, index, parent, newIndex))
+
+ self.modified = True
+ self.SetStatusText(status)
+
+ return
+
+ def OnMoveLeft(self, evt):
+ selected = tree.selection
+ if not selected: return
+
+ oldParent = tree.GetItemParent(selected)
+ if not oldParent: return
+ pparent = tree.GetItemParent(oldParent)
+ if not pparent: return
+
+ # Check compatibility
+ if not self.ItemsAreCompatible(tree.GetPyData(pparent).treeObject(), tree.GetPyData(selected).treeObject()): return
+
+ # Undo info
+ self.lastOp = 'MOVELEFT'
+ status = 'Made next sibling of parent'
+
+ oldIndex = tree.ItemIndex(selected)
+ elem = tree.RemoveLeaf(selected)
+ nextItem = tree.GetFirstChild(pparent)[0]
+ parentIndex = tree.ItemIndex(oldParent)
+ for i in range(parentIndex + 1): nextItem = tree.GetNextSibling(nextItem)
+
+ # Check parent and child relationships.
+ # If parent is sizer or notebook, child is of wrong class or
+ # parent is normal window, child is child container then detach child.
+ parent = tree.GetPyData(pparent).treeObject()
+ xxx = MakeXXXFromDOM(parent, elem)
+ isChildContainer = isinstance(xxx, xxxChildContainer)
+ if isChildContainer and \
+ ((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
+ (isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
+ not (parent.isSizer or isinstance(parent, xxxNotebook))):
+ elem.removeChild(xxx.child.element) # detach child
+ elem.unlink() # delete child container
+ elem = xxx.child.element # replace
+ # This may help garbage collection
+ xxx.child.parent = None
+ isChildContainer = False
+ # Parent is sizer or notebook, child is not child container
+ if parent.isSizer and not isChildContainer and not isinstance(xxx, xxxSpacer):
+ # Create sizer item element
+ sizerItemElem = MakeEmptyDOM('sizeritem')
+ sizerItemElem.appendChild(elem)
+ elem = sizerItemElem
+ elif isinstance(parent, xxxNotebook) and not isChildContainer:
+ pageElem = MakeEmptyDOM('notebookpage')
+ pageElem.appendChild(elem)
+ elem = pageElem
+
+ selected = tree.InsertNode(pparent, tree.GetPyData(pparent).treeObject(), elem, nextItem)
+ newIndex = tree.ItemIndex(selected)
+ tree.SelectItem(selected)
+
+ undoMan.RegisterUndo(UndoMove(oldParent, oldIndex, pparent, newIndex))
+
+ self.modified = True
+ self.SetStatusText(status)
+
+ def OnMoveRight(self, evt):
+ selected = tree.selection
+ if not selected: return
+
+ oldParent = tree.GetItemParent(selected)
+ if not oldParent: return
+
+ newParent = tree.GetPrevSibling(selected)
+ if not newParent: return
+
+ parent = tree.GetPyData(newParent).treeObject()
+
+ # Check compatibility
+ if not self.ItemsAreCompatible(parent, tree.GetPyData(selected).treeObject()): return
+
+ # Undo info
+ self.lastOp = 'MOVERIGHT'
+ status = 'Made last child of previous sibling'
+
+ oldIndex = tree.ItemIndex(selected)
+ elem = tree.RemoveLeaf(selected)
+
+ # Check parent and child relationships.
+ # If parent is sizer or notebook, child is of wrong class or
+ # parent is normal window, child is child container then detach child.
+ xxx = MakeXXXFromDOM(parent, elem)
+ isChildContainer = isinstance(xxx, xxxChildContainer)
+ if isChildContainer and \
+ ((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \
+ (isinstance(parent, xxxNotebook) and not isinstance(xxx, xxxNotebookPage)) or \
+ not (parent.isSizer or isinstance(parent, xxxNotebook))):
+ elem.removeChild(xxx.child.element) # detach child
+ elem.unlink() # delete child container
+ elem = xxx.child.element # replace
+ # This may help garbage collection
+ xxx.child.parent = None
+ isChildContainer = False
+ # Parent is sizer or notebook, child is not child container
+ if parent.isSizer and not isChildContainer and not isinstance(xxx, xxxSpacer):
+ # Create sizer item element
+ sizerItemElem = MakeEmptyDOM('sizeritem')
+ sizerItemElem.appendChild(elem)
+ elem = sizerItemElem
+ elif isinstance(parent, xxxNotebook) and not isChildContainer:
+ pageElem = MakeEmptyDOM('notebookpage')
+ pageElem.appendChild(elem)
+ elem = pageElem
+
+ selected = tree.InsertNode(newParent, tree.GetPyData(newParent).treeObject(), elem, wx.TreeItemId())
+
+ newIndex = tree.ItemIndex(selected)
+ tree.SelectItem(selected)
+
+ undoMan.RegisterUndo(UndoMove(oldParent, oldIndex, newParent, newIndex))
+
+ self.modified = True
+ self.SetStatusText(status)
+