]> git.saurik.com Git - wxWidgets.git/commitdiff
0.1.6-1
authorRoman Rolinsky <rolinsky@femagsoft.com>
Tue, 9 Aug 2005 19:27:27 +0000 (19:27 +0000)
committerRoman Rolinsky <rolinsky@femagsoft.com>
Tue, 9 Aug 2005 19:27:27 +0000 (19:27 +0000)
Support for object_ref. CreateTestWin saves all DOM in temporary
memory file now, to allow reference resolution.

Tree changed to multiple selection (not really supported yet), so
after deleting Unselect can be used (otherwise parent item is
selected automatically which results in scrolling jumps - distracting).

!!! Not tested on wxMSW yet.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@35165 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

wxPython/wx/tools/XRCed/CHANGES.txt
wxPython/wx/tools/XRCed/globals.py
wxPython/wx/tools/XRCed/tree.py
wxPython/wx/tools/XRCed/undo.py
wxPython/wx/tools/XRCed/xxx.py

index a9db3b30e555f5488103ef8f498971e6b0f2ec9b..cb43de5ba8704c4751202f3413409ada63a1f3b3 100644 (file)
@@ -1,3 +1,12 @@
+0.1.6-1
+-------
+
+New (experimental ;) ) feature: support for "object_ref" tag, for
+creating references to named objects (see tn0014.txt). "reference..." 
+menu command creates new object_ref node. Properties of the top-level
+object can be overriden, but overriding child controls is not working
+as expected (maybe a bug in wx).
+
 0.1.5-3
 -------
 
index 9d274483f3cbd074d94923280c408af7470a4631..cfcbc68dc34d4fbca8315b6254d77230b00e06c6 100644 (file)
@@ -15,7 +15,7 @@ import sys
 # Global constants
 
 progname = 'XRCed'
-version = '0.1.5-3'
+version = '0.1.6-1'
 # Can be changed to set other default encoding different
 #defaultEncoding = ''
 # you comment above and can uncomment this:
index 0a4d4d0638509fc0d790d0dfbd8d371c950c60cf..4c6817b53590f0684ecec292f2856a18855dfc6b 100644 (file)
@@ -117,6 +117,8 @@ class ID_NEW:
     HELP_BUTTON = wxNewId()
     CONTEXT_HELP_BUTTON = wxNewId()
 
+    REF = wxNewId()
+
     LAST = wxNewId()
 
     
@@ -403,7 +405,7 @@ class HighLightBox:
 
 class XML_Tree(wxTreeCtrl):
     def __init__(self, parent, id):
-        wxTreeCtrl.__init__(self, parent, id, style = wxTR_HAS_BUTTONS)
+        wxTreeCtrl.__init__(self, parent, id, style = wxTR_HAS_BUTTONS | wxTR_MULTIPLE)
         self.SetBackgroundColour(wxColour(224, 248, 224))
         # Register events
         EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
@@ -449,11 +451,6 @@ class XML_Tree(wxTreeCtrl):
         EVT_ENTER_WINDOW(self, g.tools.OnMouse)
         EVT_LEAVE_WINDOW(self, g.tools.OnMouse)
 
-    def Unselect(self):
-        self.selection = None
-        wxTreeCtrl.Unselect(self)
-        g.tools.UpdateUI()
-
     def ExpandAll(self, item):
         if self.ItemHasChildren(item):
             self.Expand(item)
@@ -516,7 +513,7 @@ class XML_Tree(wxTreeCtrl):
         self.Unselect()
 
     # Add tree item for given parent item if node is DOM element node with
-    # 'object' tag. xxxParent is parent xxx object
+    # object/object_ref tag. xxxParent is parent xxx object
     def AddNode(self, itemParent, xxxParent, node):
         # Set item data to current node
         try:
@@ -529,6 +526,9 @@ class XML_Tree(wxTreeCtrl):
         item = self.AppendItem(itemParent, treeObj.treeName(),
                                image=treeObj.treeImage(),
                                data=wxTreeItemData(xxx))
+        # Different color for references
+        if treeObj.ref:
+            self.SetItemTextColour(item, 'DarkGreen')
         # Try to find children objects
         if treeObj.hasChildren:
             nodes = treeObj.element.childNodes[:]
@@ -556,6 +556,8 @@ class XML_Tree(wxTreeCtrl):
             parent.element.appendChild(elem)
             newItem = self.AppendItem(itemParent, xxx.treeName(), image=xxx.treeImage(),
                                       data=wxTreeItemData(xxx))
+        # Different color for references
+        if xxx.treeObject().ref:  self.SetItemTextColour(newItem, 'DarkGreen')
         # Add children items
         if xxx.hasChildren:
             treeObj = xxx.treeObject()
@@ -619,7 +621,7 @@ class XML_Tree(wxTreeCtrl):
             return parentWin.GetSizer()
         elif isinstance(xxx.parent, xxxToolBar):
             # How to get tool from toolbar?
-            return parentWin.GetChildren()[0]
+            return parentWin
         elif isinstance(xxx.parent, xxxStdDialogButtonSizer):
             # This sizer returns non-existing children
             for ch in parentWin.GetChildren():
@@ -784,13 +786,7 @@ class XML_Tree(wxTreeCtrl):
             pos = g.testWinPos
         # Save in memory FS
         memFile = MemoryFile('xxx.xrc')
-        # Create partial XML file - faster for big files
-
-        dom = MyDocument()
-        mainNode = dom.createElement('resource')
-        dom.appendChild(mainNode)
-
-        # Remove temporarily from old parent
+        # Create memory XML file
         elem = xxx.element
         # Change window id to _XRCED_T_W. This gives some name for
         # unnamed windows, and for named gives the possibility to
@@ -806,14 +802,11 @@ class XML_Tree(wxTreeCtrl):
             elem.setAttribute('class', 'wxPanel')
         parent = elem.parentNode
         next = elem.nextSibling
-        parent.replaceChild(self.dummyNode, elem)
-        # Append to new DOM, write it
-        mainNode.appendChild(elem)
-        dom.writexml(memFile, encoding=self.rootObj.params['encoding'].value())
+        encd = self.rootObj.params['encoding'].value()
+        if not encd: encd = None
+        self.dom.writexml(open('ttt.xrc','w'), encoding=encd)
+        self.dom.writexml(memFile, encoding=encd)
         # Put back in place
-        mainNode.removeChild(elem)
-        dom.unlink()
-        parent.replaceChild(elem, self.dummyNode)
         # Remove temporary name or restore changed
         if not xxx.name:
             elem.removeAttribute('name')
@@ -998,6 +991,8 @@ class XML_Tree(wxTreeCtrl):
                 needInsert = self.NeedInsert(item)
             if item == self.root or needInsert and self.GetItemParent(item) == self.root:
                 SetMenu(m, pullDownMenu.topLevel)
+                m.AppendSeparator()
+                m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node')
             else:
                 xxx = self.GetPyData(item).treeObject()
                 # Check parent for possible child nodes if inserting sibling
@@ -1017,6 +1012,8 @@ class XML_Tree(wxTreeCtrl):
                         m.Enable(m.FindItem('sizer'), False)
                     elif not (xxx.isSizer or xxx.parent and xxx.parent.isSizer):
                         m.Enable(ID_NEW.SPACER, False)
+                m.AppendSeparator()
+                m.Append(ID_NEW.REF, 'reference...', 'Create object_ref node')
             # Select correct label for create menu
             if not needInsert:
                 if self.shift:
@@ -1056,7 +1053,7 @@ class XML_Tree(wxTreeCtrl):
                 menu.AppendMenu(id, 'Replace With', m)
                 if not m.GetMenuItemCount(): menu.Enable(id, False)
                 menu.Append(pullDownMenu.ID_SUBCLASS, 'Subclass...',
-                            'Set subclass property')
+                            'Set "subclass" property')
             menu.AppendSeparator()
             # Not using standart IDs because we don't want to show shortcuts
             menu.Append(wxID_CUT, 'Cut', 'Cut to the clipboard')
@@ -1089,5 +1086,5 @@ class XML_Tree(wxTreeCtrl):
         if isinstance(xxx, xxxBoxSizer):
             self.SetItemImage(item, xxx.treeImage())
         # Set global modified state
-        g.frame.modified = True
+        g.frame.SetModified()
 
index ef9083cdc73aa550a7273132025d0bd75326b31b..1f01d8d403f30370fe82770bf99cdd53b240c5d2 100644 (file)
@@ -20,13 +20,13 @@ class UndoManager:
         undoObj = self.undo.pop()
         undoObj.undo()
         self.redo.append(undoObj)
-        g.frame.modified = True
+        g.frame.SetModified()
         g.frame.SetStatusText('Undone')
     def Redo(self):
         undoObj = self.redo.pop()
         undoObj.redo()
         self.undo.append(undoObj)
-        g.frame.modified = True
+        g.frame.SetModified()
         g.frame.SetStatusText('Redone')
     def Clear(self):
         for i in self.undo: i.destroy()
index 4af295088df1f56775e1e7f631a0b7511a53a2a4..62e7aaa8b8415011c9c7cc0ba4f43fb273e6720e 100644 (file)
@@ -208,12 +208,24 @@ class xxxObject:
     #image = -1
     # Construct a new xxx object from DOM element
     # parent is parent xxx object (or None if none), element is DOM element object
-    def __init__(self, parent, element):
+    def __init__(self, parent, element, refElem=None):
         self.parent = parent
         self.element = element
+        self.refElem = refElem
         self.undo = None
-        # Get attributes
-        self.className = element.getAttribute('class')
+        # Reference are dereferenced
+        if element.tagName == 'object_ref':
+            # Find original object
+            self.ref = element.getAttribute('ref')
+            if refElem:
+                self.className = self.refElem.getAttribute('class')
+            else:
+                self.className = 'xxxUnknown'
+            self.required = []
+        else:
+            # Get attributes
+            self.ref = None
+            self.className = element.getAttribute('class')
         self.subclass = element.getAttribute('subclass')
         if self.hasName: self.name = element.getAttribute('name')
         # Set parameters (text element children)
@@ -222,9 +234,9 @@ class xxxObject:
         for node in nodes:
             if node.nodeType == minidom.Node.ELEMENT_NODE:
                 tag = node.tagName
-                if tag == 'object':
+                if tag in ['object', 'object_ref']:
                     continue            # do nothing for object children here
-                if tag not in self.allParams and tag not in self.styles:
+                elif tag not in self.allParams and tag not in self.styles:
                     print 'WARNING: unknown parameter for %s: %s' % \
                           (self.className, tag)
                 elif tag in self.specials:
@@ -292,8 +304,10 @@ class xxxObject:
         return className
     # Class name or subclass
     def panelName(self):
-        if self.subclass: return self.subclass + '(' + self.className + ')'
-        else: return self.className
+        if self.subclass: name = self.subclass + '(' + self.className + ')'
+        name = self.className
+        if self.ref: name = 'ref: ' + self.ref + ', ' + name
+        return name
     # Sets name of tree object
     def setTreeName(self, name):
         if self.hasChild: obj = self.child
@@ -301,6 +315,32 @@ class xxxObject:
         obj.name = name
         obj.element.setAttribute('name', name)
 
+# Imitation of FindResource/DoFindResource from xmlres.cpp
+def DoFindResource(parent, name, classname, recursive):
+    for n in parent.childNodes:
+        if n.nodeType == minidom.Node.ELEMENT_NODE and \
+               n.tagName in ['object', 'object_ref'] and \
+               n.getAttribute('name') == name:
+            cls = n.getAttribute('class')
+            if not classname or cls == classname:  return n
+            if not cls or n.tagName == 'object_ref':
+                refName = n.getAttribute('ref')
+                if not refName:  continue
+                refNode = FindResource(refName)
+                if refName and refNode.getAttribute('class') == classname:
+                    return n
+    if recursive:
+        for n in parent.childNodes:
+            if n.nodeType == minidom.Node.ELEMENT_NODE and \
+                   n.tagName in ['object', 'object_ref']:
+                found = DoFindResource(n, name, classname, True)
+                if found:  return found
+def FindResource(name, classname='', recursive=True):
+    found = DoFindResource(g.tree.mainNode, name, classname, recursive)
+    if found:  return found
+    wxLogError('XRC resource "%s" not found!' % name)
+                
+
 ################################################################################
 
 # This is a little special: it is both xxxObject and xxxNode
@@ -717,13 +757,13 @@ class xxxGridBagSizer(xxxSizer):
 class xxxChildContainer(xxxObject):
     hasName = hasStyle = False
     hasChild = True
-    def __init__(self, parent, element):
-        xxxObject.__init__(self, parent, element)
+    def __init__(self, parent, element, refElem=None):
+        xxxObject.__init__(self, parent, element, refElem)
         # Must have one child with 'object' tag, but we don't check it
         nodes = element.childNodes[:]   # create copy
         for node in nodes:
             if node.nodeType == minidom.Node.ELEMENT_NODE:
-                if node.tagName == 'object':
+                if node.tagName in ['object', 'object_ref']:
                     # Create new xxx object for child node
                     self.child = MakeXXXFromDOM(self, node)
                     self.child.parent = parent
@@ -740,11 +780,11 @@ class xxxSizerItem(xxxChildContainer):
     allParams = ['option', 'flag', 'border', 'minsize', 'ratio']
     paramDict = {'option': ParamInt, 'minsize': ParamPosSize, 'ratio': ParamPosSize}
     #default = {'cellspan': '1,1'}
-    def __init__(self, parent, element):
+    def __init__(self, parent, element, refElem=None):
         # For GridBag sizer items, extra parameters added
         if isinstance(parent, xxxGridBagSizer):
             self.allParams = self.allParams + ['cellpos', 'cellspan']
-        xxxChildContainer.__init__(self, parent, element)
+        xxxChildContainer.__init__(self, parent, element, refElem)
         # Remove pos parameter - not needed for sizeritems
         if 'pos' in self.child.allParams:
             self.child.allParams = self.child.allParams[:]
@@ -753,8 +793,8 @@ class xxxSizerItem(xxxChildContainer):
 class xxxSizerItemButton(xxxSizerItem):
     allParams = []
     paramDict = {}
-    def __init__(self, parent, element):
-        xxxChildContainer.__init__(self, parent, element)
+    def __init__(self, parent, element, refElem=None):
+        xxxChildContainer.__init__(self, parent, element, refElem=None)
         # Remove pos parameter - not needed for sizeritems
         if 'pos' in self.child.allParams:
             self.child.allParams = self.child.allParams[:]
@@ -764,8 +804,8 @@ class xxxNotebookPage(xxxChildContainer):
     allParams = ['label', 'selected']
     paramDict = {'selected': ParamBool}
     required = ['label']
-    def __init__(self, parent, element):
-        xxxChildContainer.__init__(self, parent, element)
+    def __init__(self, parent, element, refElem=None):
+        xxxChildContainer.__init__(self, parent, element, refElem)
         # pos and size dont matter for notebookpages
         if 'pos' in self.child.allParams:
             self.child.allParams = self.child.allParams[:]
@@ -888,17 +928,25 @@ for cl in xxxDict.values():
 
 # Test for object elements
 def IsObject(node):
-    return node.nodeType == minidom.Node.ELEMENT_NODE and node.tagName == 'object'
+    return node.nodeType == minidom.Node.ELEMENT_NODE and node.tagName in ['object', 'object_ref']
 
 # Make XXX object from some DOM object, selecting correct class
 def MakeXXXFromDOM(parent, element):
+    if element.tagName == 'object_ref':
+        ref = element.getAttribute('ref')
+        refElem = FindResource(ref)
+        if refElem: cls = refElem.getAttribute('class')
+        else: return xxxUnknown(parent, element)
+    else:
+        refElem = None
+        cls = element.getAttribute('class')
     try:
-        klass = xxxDict[element.getAttribute('class')]
+        klass = xxxDict[cls]
     except KeyError:
         # If we encounter a weird class, use unknown template
         print 'WARNING: unsupported class:', element.getAttribute('class')
         klass = xxxUnknown
-    return klass(parent, element)
+    return klass(parent, element, refElem)
 
 # Make empty DOM element
 def MakeEmptyDOM(className):
@@ -935,3 +983,26 @@ def MakeEmptyXXX(parent, className):
     # Now just make object
     return MakeXXXFromDOM(parent, elem)
 
+# Make empty DOM element for reference
+def MakeEmptyRefDOM(ref):
+    elem = g.tree.dom.createElement('object_ref')
+    elem.setAttribute('ref', ref)
+    return elem
+
+# Make empty XXX object
+def MakeEmptyRefXXX(parent, ref):
+    # Make corresponding DOM object first
+    elem = MakeEmptyRefDOM(ref)
+    # If parent is a sizer, we should create sizeritem object, except for spacers
+    if parent:
+        if parent.isSizer:
+            sizerItemElem = MakeEmptyDOM(parent.itemTag)
+            sizerItemElem.appendChild(elem)
+            elem = sizerItemElem
+        elif isinstance(parent, xxxNotebook):
+            pageElem = MakeEmptyDOM('notebookpage')
+            pageElem.appendChild(elem)
+            elem = pageElem
+    # Now just make object
+    return MakeXXXFromDOM(parent, elem)
+