]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/wx/tools/XRCed/tree.py
searching for plugins in XRCEDPATH
[wxWidgets.git] / wxPython / wx / tools / XRCed / tree.py
index 3fb095bcec2d2ca3ac9e1b2881a12deec6a6b71f..f384b15da5cfb281ff27d8f942b1d0283cd85812 100644 (file)
@@ -86,10 +86,12 @@ class ID_NEW:
     CHOICEBOOK = wx.NewId()
     LISTBOOK = wx.NewId()
     SPLITTER_WINDOW = wx.NewId()
+    GRID = wx.NewId()
     SCROLLED_WINDOW = wx.NewId()
     HTML_WINDOW = wx.NewId()
     CALENDAR_CTRL = wx.NewId()
     DATE_CTRL = wx.NewId()
+    FILE_PICKER_CTRL = wx.NewId()
     GENERIC_DIR_CTRL = wx.NewId()
     SPIN_CTRL = wx.NewId()
     UNKNOWN = wx.NewId()
@@ -124,6 +126,10 @@ class ID_NEW:
     CONTEXT_HELP_BUTTON = wx.NewId()
 
     REF = wx.NewId()
+    COMMENT = wx.NewId()
+
+    CUSTOM = wx.NewId()
+    for i in range(99): wx.NewId()   # reserve IDs for custom controls
 
     LAST = wx.NewId()
 
@@ -193,10 +199,12 @@ class PullDownMenu:
             ID_NEW.CHOICEBOOK: 'wxChoicebook',
             ID_NEW.LISTBOOK: 'wxListbook',
             ID_NEW.SPLITTER_WINDOW: 'wxSplitterWindow',
+            ID_NEW.GRID: 'wxGrid',
             ID_NEW.SCROLLED_WINDOW: 'wxScrolledWindow',
             ID_NEW.HTML_WINDOW: 'wxHtmlWindow',
             ID_NEW.CALENDAR_CTRL: 'wxCalendarCtrl',
             ID_NEW.DATE_CTRL: 'wxDatePickerCtrl',
+            ID_NEW.FILE_PICKER_CTRL: 'wxFilePickerCtrl',
             ID_NEW.GENERIC_DIR_CTRL: 'wxGenericDirCtrl',
             ID_NEW.SPIN_CTRL: 'wxSpinCtrl',
 
@@ -268,10 +276,12 @@ class PullDownMenu:
              (ID_NEW.SCROLL_BAR, 'ScrollBar', 'Create scroll bar'),
              (ID_NEW.TREE_CTRL, 'TreeCtrl', 'Create tree'),
              (ID_NEW.LIST_CTRL, 'ListCtrl', 'Create list'),
+#             (ID_NEW.GRID, 'Grid', 'Create grid'),
              (ID_NEW.SCROLLED_WINDOW, 'ScrolledWindow', 'Create scrolled window'),
              (ID_NEW.HTML_WINDOW, 'HtmlWindow', 'Create HTML window'),
              (ID_NEW.CALENDAR_CTRL, 'CalendarCtrl', 'Create calendar control'),
              (ID_NEW.DATE_CTRL, 'DatePickerCtrl', 'Create date picker control'),
+#             (ID_NEW.FILE_PICKER_CTRL, 'FilePickerCtrl', 'Create file picker control'),
              (ID_NEW.GENERIC_DIR_CTRL, 'GenericDirCtrl', 'Create generic dir control'),
              (ID_NEW.UNKNOWN, 'Unknown', 'Create custom control placeholder'),
              ],
@@ -370,7 +380,13 @@ class PullDownMenu:
             ID_NEW.HELP_BUTTON: ('wxID_HELP', '&Help'),
             ID_NEW.CONTEXT_HELP_BUTTON: ('wxID_CONTEXT_HELP', '&Help'),
             }
-            
+        self.custom = ['custom', 'User-defined controls']
+        self.customMap = {}        
+        
+    def addCustom(self, klass):
+        n = len(self.custom)-2
+        self.custom.append((ID_NEW.CUSTOM + n, klass))
+        self.customMap[ID_NEW.CUSTOM + n] = klass
 
 
 ################################################################################
@@ -409,6 +425,7 @@ class HighLightBox:
         l4 = wx.Window(w, -1, wx.Point(pos.x, pos.y + size.height - 2), wx.Size(size.width, 2))
         l4.SetBackgroundColour(wx.RED)
         self.lines = [l1, l2, l3, l4]
+        self.size = size
     # Move highlight to a new position
     def Replace(self, pos, size):
         if size.width == -1: size.width = 0
@@ -417,6 +434,7 @@ class HighLightBox:
         self.lines[1].SetDimensions(pos.x, pos.y, 2, size.height)
         self.lines[2].SetDimensions(pos.x + size.width - 2, pos.y, 2, size.height)
         self.lines[3].SetDimensions(pos.x, pos.y + size.height - 2, size.width, 2)
+        self.size = size
     # Remove it
     def Remove(self):
         map(wx.Window.Destroy, self.lines)
@@ -428,8 +446,12 @@ class HighLightBox:
 
 class XML_Tree(wx.TreeCtrl):
     def __init__(self, parent, id):
-        wx.TreeCtrl.__init__(self, parent, id, style = wx.TR_HAS_BUTTONS | wx.TR_MULTIPLE)
+        wx.TreeCtrl.__init__(self, parent, id,
+                             style = wx.TR_HAS_BUTTONS | wx.TR_MULTIPLE | wx.TR_EDIT_LABELS)
         self.SetBackgroundColour(wx.Colour(224, 248, 224))
+        self.fontComment = wx.FFont(self.GetFont().GetPointSize(),
+                                    self.GetFont().GetFamily(),
+                                    wx.FONTFLAG_ITALIC)
         # Register events
         wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
         # One works on Linux, another on Windows
@@ -440,6 +462,8 @@ class XML_Tree(wx.TreeCtrl):
         wx.EVT_RIGHT_DOWN(self, self.OnRightDown)
         wx.EVT_TREE_ITEM_EXPANDED(self, self.GetId(), self.OnItemExpandedCollapsed)
         wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemExpandedCollapsed)
+        self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnBeginLabelEdit)
+        self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEndLabelEdit)
 
         self.selection = None
         self.selectionChanging = False
@@ -450,6 +474,7 @@ class XML_Tree(wx.TreeCtrl):
         # Create image list
         il = wx.ImageList(16, 16, True)
         self.rootImage = il.Add(images.getTreeRootImage().Scale(16,16).ConvertToBitmap())
+        xxxComment.image = il.Add(images.getTreeCommentImage().Scale(16,16).ConvertToBitmap())
         xxxObject.image = il.Add(images.getTreeDefaultImage().Scale(16,16).ConvertToBitmap())
         xxxPanel.image = il.Add(images.getTreePanelImage().Scale(16,16).ConvertToBitmap())
         xxxDialog.image = il.Add(images.getTreeDialogImage().Scale(16,16).ConvertToBitmap())
@@ -560,17 +585,22 @@ class XML_Tree(wx.TreeCtrl):
         item = self.AppendItem(itemParent, treeObj.treeName(),
                                image=treeObj.treeImage(),
                                data=wx.TreeItemData(xxx))
-        # Different color for references
-        if treeObj.ref:
+        # Different color for comments and references
+        if xxx.className == 'comment':
+            self.SetItemTextColour(item, 'Blue')
+            self.SetItemFont(item, self.fontComment)
+        elif treeObj.ref:
             self.SetItemTextColour(item, 'DarkGreen')
+        elif treeObj.hasStyle and treeObj.params.get('hidden', False):
+            self.SetItemTextColour(item, 'Grey')
         # Try to find children objects
         if treeObj.hasChildren:
-            nodes = treeObj.element.childNodes[:]
+            nodes = treeObj.node.childNodes[:]
             for n in nodes:
                 if IsObject(n):
                     self.AddNode(item, treeObj, n)
                 elif n.nodeType != minidom.Node.ELEMENT_NODE:
-                    treeObj.element.removeChild(n)
+                    treeObj.node.removeChild(n)
                     n.unlink()
 
     # Insert new item at specific position
@@ -579,23 +609,30 @@ class XML_Tree(wx.TreeCtrl):
         xxx = MakeXXXFromDOM(parent, elem)
         # If nextItem is None, we append to parent, otherwise insert before it
         if nextItem.IsOk():
-            node = self.GetPyData(nextItem).element
-            parent.element.insertBefore(elem, node)
+            node = self.GetPyData(nextItem).node
+            parent.node.insertBefore(elem, node)
             # Inserting before is difficult, se we insert after or first child
             index = self.ItemIndex(nextItem)
             newItem = self.InsertItemBefore(itemParent, index,
                         xxx.treeName(), image=xxx.treeImage())
             self.SetPyData(newItem, xxx)
         else:
-            parent.element.appendChild(elem)
+            parent.node.appendChild(elem)
             newItem = self.AppendItem(itemParent, xxx.treeName(), image=xxx.treeImage(),
                                       data=wx.TreeItemData(xxx))
-        # Different color for references
-        if xxx.treeObject().ref:  self.SetItemTextColour(newItem, 'DarkGreen')
+        treeObj = xxx.treeObject()
+        # Different color for references and comments
+        if xxx.className == 'comment':
+            self.SetItemTextColour(newItem, 'Blue')
+            self.SetItemFont(newItem, self.fontComment)
+        elif treeObj.ref:
+            self.SetItemTextColour(newItem, 'DarkGreen')
+        elif treeObj.hasStyle and treeObj.params.get('hidden', False):
+            self.SetItemTextColour(newItem, 'Grey')
         # Add children items
         if xxx.hasChildren:
             treeObj = xxx.treeObject()
-            for n in treeObj.element.childNodes:
+            for n in treeObj.node.childNodes:
                 if IsObject(n):
                     self.AddNode(newItem, treeObj, n)
         return newItem
@@ -603,13 +640,14 @@ class XML_Tree(wx.TreeCtrl):
     # Remove leaf of tree, return it's data object
     def RemoveLeaf(self, leaf):
         xxx = self.GetPyData(leaf)
-        node = xxx.element
+        node = xxx.node
         parent = node.parentNode
         parent.removeChild(node)
         self.Delete(leaf)
         # Reset selection object
         self.selection = None
         return node
+    
     # Find position relative to the top-level window
     def FindNodePos(self, item, obj=None):
         # Root at (0,0)
@@ -629,17 +667,18 @@ class XML_Tree(wx.TreeCtrl):
                         if g.testWin.highLight:
                             g.testWin.highLight.Remove()
                     break
-        # Find first ancestor which is a wxWindow (not a sizer)
+        # For sizers and notebooks we must select the first window-like parent
         winParent = itemParent
         while self.GetPyData(winParent).isSizer:
             winParent = self.GetItemParent(winParent)
         # Notebook children are layed out in a little strange way
-        if self.GetPyData(itemParent).treeObject().__class__ == xxxNotebook:
-            parentPos = wx.Point(0,0)
-        else:
-            parentPos = self.FindNodePos(winParent)
-        # Position (-1,-1) is really (0,0)
+        # wxGTK places NB panels relative to the NB parent
+        if wx.Platform == '__WXGTK__':
+            if self.GetPyData(itemParent).treeObject().__class__ == xxxNotebook:
+                winParent = self.GetItemParent(winParent)
+        parentPos = self.FindNodePos(winParent)
         pos = obj.GetPosition()
+        # Position (-1,-1) is really (0,0)
         if pos == (-1,-1): pos = (0,0)
         return parentPos + pos
 
@@ -692,12 +731,12 @@ class XML_Tree(wx.TreeCtrl):
         #oldItem = evt.GetOldItem()
         status = ''
         oldItem = self.selection
-        if oldItem:
+        # use GetItemParent as a way to determine if the itemId is still valid
+        if oldItem and self.GetItemParent(oldItem):
             xxx = self.GetPyData(oldItem)
             # If some data was modified, apply changes
             if g.panel.IsModified():
                 self.Apply(xxx, oldItem)
-                #if conf.autoRefresh:
                 if g.testWin:
                     if g.testWin.highLight:
                         g.testWin.highLight.Remove()
@@ -722,7 +761,8 @@ class XML_Tree(wx.TreeCtrl):
         if item == g.testWin.item: return False
         while item != self.root:
             item = self.GetItemParent(item)
-            if item == g.testWin.item: return True
+            if item == g.testWin.item:
+                return True
         return False
 
     # Highlight selected item
@@ -738,19 +778,27 @@ class XML_Tree(wx.TreeCtrl):
             return
         # Get window/sizer object
         obj = self.FindNodeObject(item)
-        if not obj:
+        xxx = self.GetPyData(item).treeObject()
+        # Remove existing HL if item not found or is hidden
+        if not obj or xxx.hasStyle and xxx.params.get('hidden', False):
             if g.testWin.highLight: g.testWin.highLight.Remove()
             return
-        pos = self.FindNodePos(item, obj)
+        pos = self.FindNodePos(item, obj)         
         size = obj.GetSize()
         # Highlight
         # Negative positions are not working quite well
-        if g.testWin.highLight:
-            g.testWin.highLight.Replace(pos, size)
+        hl = g.testWin.highLight
+        # If highlight object has the same size SetDimension does not repaint it
+        # so we must remove the old HL window
+        if hl and hl.size == size:
+            hl.Remove()
+            hl = None
+        if hl:
+            hl.Replace(pos, size)
         else:
-            g.testWin.highLight = HighLightBox(pos, size)
-        g.testWin.highLight.Refresh()
-        g.testWin.highLight.item = item
+            g.testWin.highLight = hl = HighLightBox(pos, size)
+        hl.Refresh()
+        hl.item = item
 
     def ShowTestWindow(self, item):
         xxx = self.GetPyData(item)
@@ -768,6 +816,7 @@ class XML_Tree(wx.TreeCtrl):
             return
         # Show item in bold
         if g.testWin:     # Reset old
+            self.UnselectAll()
             self.SetItemBold(g.testWin.item, False)
         try:
             wx.BeginBusyCursor()
@@ -803,19 +852,6 @@ class XML_Tree(wx.TreeCtrl):
         testWin = g.testWin
         # Create a window with this resource
         xxx = self.GetPyData(item).treeObject()
-
-        # If frame
-#        if xxx.__class__ == xxxFrame:
-            # Frame can't have many children,
-            # but it's first child possibly can...
-#            child = self.GetFirstChild(item)[0]
-#            if child.IsOk() and self.GetPyData(child).__class__ == xxxPanel:
-#                # Clean-up before recursive call or error
-#                wx.MemoryFSHandler.RemoveFile('xxx.xrc')
-#                wx.EndBusyCursor()
-#                self.CreateTestWin(child)
-#                return
-
         # Close old window, remember where it was
         highLight = None
         if testWin:
@@ -841,7 +877,7 @@ class XML_Tree(wx.TreeCtrl):
         # Save in memory FS
         memFile = MemoryFile('xxx.xrc')
         # Create memory XML file
-        elem = xxx.element.cloneNode(True)
+        elem = xxx.node.cloneNode(True)
         if not xxx.name:
             name = 'noname'
         else:
@@ -870,6 +906,10 @@ class XML_Tree(wx.TreeCtrl):
         if not g.currentEncoding:
             xmlFlags != xrc.XRC_USE_LOCALE
         res = xrc.XmlResource('', xmlFlags)
+        xrc.XmlResource.Set(res)        # set as global
+        # Register handlers
+        addHandlers()
+        # Same module list
         res.Load('memory:xxx.xrc')
         try:
             if xxx.__class__ == xxxFrame:
@@ -900,7 +940,7 @@ class XML_Tree(wx.TreeCtrl):
                 testWin.SetClientSize(testWin.GetBestSize())
                 testWin.Show(True)
             elif xxx.__class__ == xxxDialog:
-                testWin = g.testWin = res.LoadDialog(None, STD_NAME)
+                testWin = g.testWin = res.LoadDialog(g.frame, STD_NAME)
                 testWin.panel = testWin
                 testWin.Layout()
                 testWin.SetPosition(pos)
@@ -910,7 +950,7 @@ class XML_Tree(wx.TreeCtrl):
                 wx.EVT_BUTTON(testWin, wx.ID_CANCEL, self.OnCloseTestWin)
             elif xxx.__class__ == xxxWizard:
                 wiz = wx.wizard.PreWizard()
-                res.LoadOnObject(wiz, None, STD_NAME, 'wxWizard')
+                res.LoadOnObject(wiz, g.frame, STD_NAME, 'wxWizard')
                 # Find first page (don't know better way)
                 firstPage = None
                 for w in wiz.GetChildren():
@@ -952,9 +992,11 @@ class XML_Tree(wx.TreeCtrl):
                 testWin.toolBar = res.LoadToolBar(testWin, STD_NAME)
                 testWin.SetToolBar(testWin.toolBar)
                 testWin.Show(True)
+            # Catch some events, set highlight
             if testWin:
                 testWin.item = item
                 wx.EVT_CLOSE(testWin, self.OnCloseTestWin)
+                wx.EVT_SIZE(testWin, self.OnSizeTestWin)
                 testWin.highLight = None
                 if highLight and not self.pendingHighLight:
                     self.HighLight(highLight)
@@ -967,6 +1009,9 @@ class XML_Tree(wx.TreeCtrl):
             inf = sys.exc_info()
             wx.LogError(traceback.format_exception(inf[0], inf[1], None)[-1])
             wx.LogError('Error loading resource')
+        # Cleanup
+        res.Unload('xxx.xrc')
+        xrc.XmlResource.Set(None)
         wx.MemoryFSHandler.RemoveFile('xxx.xrc')
 
     def CloseTestWindow(self):
@@ -980,6 +1025,11 @@ class XML_Tree(wx.TreeCtrl):
     def OnCloseTestWin(self, evt):
         self.CloseTestWindow()
 
+    def OnSizeTestWin(self, evt):
+        if g.testWin.highLight:
+            self.HighLight(g.testWin.highLight.item)
+        evt.Skip()
+
     # Return index in parent, for real window children
     def WindowIndex(self, item):
         n = 0                           # index of sibling
@@ -1061,6 +1111,7 @@ class XML_Tree(wx.TreeCtrl):
                 SetMenu(m, pullDownMenu.topLevel)
                 m.AppendSeparator()
                 m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node')
+                m.Append(ID_NEW.COMMENT, 'comment', 'Create comment node')
             else:
                 xxx = self.GetPyData(item).treeObject()
                 # Check parent for possible child nodes if inserting sibling
@@ -1082,8 +1133,12 @@ class XML_Tree(wx.TreeCtrl):
                         m.Enable(ID_NEW.SPACER, False)
                     if xxx.__class__ is not xxxFrame:
                         m.Enable(ID_NEW.MENU_BAR, False)
+                # Add custom controls menu
+                if len(pullDownMenu.custom) > 2:
+                    SetMenu(m, [pullDownMenu.custom])
                 m.AppendSeparator()
                 m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node')
+                m.Append(ID_NEW.COMMENT, 'comment', 'Create comment node')
             # Select correct label for create menu
             if not needInsert:
                 if self.shift:
@@ -1115,15 +1170,16 @@ class XML_Tree(wx.TreeCtrl):
                         (ID_NEW.PANEL, 'Panel', 'Create panel'),
                         (ID_NEW.DIALOG, 'Dialog', 'Create dialog'),
                         (ID_NEW.FRAME, 'Frame', 'Create frame')], shift=True)
-                elif xxx.isSizer:
+                elif xxx.isSizer and self.ItemHasChildren(item):
                     SetMenu(m, pullDownMenu.sizers, shift=True)
                 else:
                     SetMenu(m, pullDownMenu.controls, shift=True)
-                id = wx.NewId()
-                menu.AppendMenu(id, 'Replace With', m)
-                if not m.GetMenuItemCount(): menu.Enable(id, False)
-                menu.Append(pullDownMenu.ID_SUBCLASS, 'Subclass...',
-                            'Set "subclass" property')
+                if xxx.isElement:
+                    id = wx.NewId()
+                    menu.AppendMenu(id, 'Replace With', m)
+                    if not m.GetMenuItemCount(): menu.Enable(id, False)
+                    menu.Append(pullDownMenu.ID_SUBCLASS, 'Subclass...',
+                                'Set "subclass" property')
             menu.AppendSeparator()
             # Not using standart IDs because we don't want to show shortcuts
             menu.Append(wx.ID_CUT, 'Cut', 'Cut to the clipboard')
@@ -1142,6 +1198,12 @@ class XML_Tree(wx.TreeCtrl):
         self.PopupMenu(menu, evt.GetPosition())
         menu.Destroy()
 
+    # Redefine to force the update of font dimentions on wxGTK
+    if wx.Platform == '__WXGTK__':
+        def SetItemBold(self, item, state=True):
+            wx.TreeCtrl.SetItemBold(self, item, state)
+            self.SetIndent(self.GetIndent())
+
     # Apply changes
     def Apply(self, xxx, item):
         g.panel.Apply()
@@ -1152,9 +1214,25 @@ class XML_Tree(wx.TreeCtrl):
             # Item width may have changed
             # !!! Tric to update tree width (wxGTK, ??)
             self.SetIndent(self.GetIndent())
+        elif xxx.className == 'comment':
+            self.SetItemText(item, xxx.treeName())
         # Change tree icon for sizers
         if isinstance(xxx, xxxBoxSizer):
             self.SetItemImage(item, xxx.treeImage())
         # Set global modified state
         g.frame.SetModified()
 
+    def OnBeginLabelEdit(self, evt):
+        xxx = self.GetPyData(evt.GetItem())
+        if xxx.isElement:
+            evt.Veto()
+        else:
+            evt.Skip()
+
+    def OnEndLabelEdit(self, evt):
+        xxx = self.GetPyData(evt.GetItem())
+        node = xxx.node
+        if not xxx.isElement:
+            node.data = evt.GetLabel()
+            g.panel.SetData(xxx)
+        evt.Skip()