diff --git a/wxPython/wx/tools/XRCed/CHANGES.txt b/wxPython/wx/tools/XRCed/CHANGES.txt index c4bdbc07a5..9936ba3cb6 100644 --- a/wxPython/wx/tools/XRCed/CHANGES.txt +++ b/wxPython/wx/tools/XRCed/CHANGES.txt @@ -1,3 +1,9 @@ +0.1.8-5 +------- + +Implemented comment object for simple one-line comments. No +validation is performed. + 0.1.8-4 ------- diff --git a/wxPython/wx/tools/XRCed/globals.py b/wxPython/wx/tools/XRCed/globals.py index dbf9769279..3da271cea2 100644 --- a/wxPython/wx/tools/XRCed/globals.py +++ b/wxPython/wx/tools/XRCed/globals.py @@ -15,7 +15,7 @@ import sys # Global constants progname = 'XRCed' -version = '0.1.8-4' +version = '0.1.8-5' # Minimal wxWidgets version MinWxVersion = (2,6,0) if wx.VERSION[:3] < MinWxVersion: diff --git a/wxPython/wx/tools/XRCed/panel.py b/wxPython/wx/tools/XRCed/panel.py index 17b09802fa..08600bc384 100644 --- a/wxPython/wx/tools/XRCed/panel.py +++ b/wxPython/wx/tools/XRCed/panel.py @@ -22,7 +22,7 @@ class Panel(wx.Notebook): # Set common button size for parameter buttons bTmp = wx.Button(self, -1, '') import params - params.buttonSize = (self.DLG_SZE(buttonSize)[0], bTmp.GetSize()[1]) + params.buttonSize = (self.DLG_SZE(buttonSizeD)[0], bTmp.GetSize()[1]) bTmp.Destroy() del bTmp @@ -184,7 +184,7 @@ class ParamPage(wx.Panel): param = evt.GetEventObject().GetName() w = self.controls[param] w.Enable(True) - objElem = xxx.element + objElem = xxx.node if evt.IsChecked(): # Ad new text node in order of allParams w.SetValue('') # set empty (default) value @@ -192,7 +192,7 @@ class ParamPage(wx.Panel): elem = g.tree.dom.createElement(param) # Some classes are special if param == 'font': - xxx.params[param] = xxxParamFont(xxx.element, elem) + xxx.params[param] = xxxParamFont(xxx.node, elem) elif param in xxxObject.bitmapTags: xxx.params[param] = xxxParamBitmap(elem) else: @@ -228,7 +228,7 @@ class ParamPage(wx.Panel): name = self.controlName.GetValue() if xxx.name != name: xxx.name = name - xxx.element.setAttribute('name', name) + xxx.node.setAttribute('name', name) for param, w in self.controls.items(): if w.modified: paramObj = xxx.params[param] @@ -284,8 +284,11 @@ class PropPage(ParamPage): for param in xxx.allParams: present = xxx.params.has_key(param) if param in xxx.required: - label = wx.StaticText(self, paramIDs[param], param + ':', - size = (LABEL_WIDTH,-1), name = param) + if isinstance(xxx, xxxComment): + label = None + else: + label = wx.StaticText(self, paramIDs[param], param + ':', + size = (LABEL_WIDTH,-1), name = param) else: # Notebook has one very loooooong parameter if param == 'usenotebooksizer': sParam = 'usesizer:' @@ -304,11 +307,14 @@ class PropPage(ParamPage): typeClass = ParamText control = typeClass(self, param) control.Enable(present) - sizer.AddMany([ (label, 0, wx.ALIGN_CENTER_VERTICAL), - (control, 0, wx.ALIGN_CENTER_VERTICAL | wx.GROW) ]) + # Comment has only one parameter + if isinstance(xxx, xxxComment): + sizer.Add(control, 0, wx.ALIGN_CENTER_VERTICAL | wx.GROW) + else: + sizer.AddMany([ (label, 0, wx.ALIGN_CENTER_VERTICAL), + (control, 0, wx.ALIGN_CENTER_VERTICAL | wx.GROW) ]) self.controls[param] = control topSizer.Add(sizer, 1, wx.ALL | wx.EXPAND, 3) - self.SetAutoLayout(True) self.SetSizer(topSizer) topSizer.Fit(self) def SetValues(self, xxx): diff --git a/wxPython/wx/tools/XRCed/params.py b/wxPython/wx/tools/XRCed/params.py index a246adab9a..3a05721ca0 100644 --- a/wxPython/wx/tools/XRCed/params.py +++ b/wxPython/wx/tools/XRCed/params.py @@ -25,7 +25,10 @@ genericExStyles = [ 'wxWS_EX_PROCESS_UI_UPDATES' ] -buttonSize = (35,-1) # in dialog units, transformed to pixels in panel ctor +# Global var initialized in Panel.__init__ for button size in screen pixels +buttonSize = None +# Button size in dialog units +buttonSizeD = (35,-1) # Class that can properly disable children class PPanel(wx.Panel): @@ -56,8 +59,7 @@ class ParamBinaryOr(PPanel): sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) self.button = wx.Button(self, self.ID_BUTTON_CHOICES, 'Edit...', size=buttonSize) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL) - self.SetAutoLayout(True) - self.SetSizerAndFit(sizer) + self.SetSizer(sizer) wx.EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) def GetValue(self): @@ -190,8 +192,7 @@ class ParamColour(PPanel): sizer.Add(self.text, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2) self.button = wx.Panel(self, self.ID_BUTTON, wx.DefaultPosition, wx.Size(20, 20)) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5) - self.SetAutoLayout(True) - self.SetSizerAndFit(sizer) + self.SetSizer(sizer) self.textModified = False wx.EVT_PAINT(self.button, self.OnPaintButton) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) @@ -251,8 +252,7 @@ class ParamFont(PPanel): sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) self.button = wx.Button(self, self.ID_BUTTON_SELECT, 'Select...', size=buttonSize) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL) - self.SetAutoLayout(True) - self.SetSizerAndFit(sizer) + self.SetSizer(sizer) self.textModified = False wx.EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) @@ -344,8 +344,7 @@ class ParamInt(PPanel): self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1)) self.spin.SetRange(-2147483648, 2147483647) # min/max integers sizer.Add(self.spin) - self.SetAutoLayout(True) - self.SetSizerAndFit(sizer) + self.SetSizer(sizer) wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange) def GetValue(self): return str(self.spin.GetValue()) @@ -364,8 +363,7 @@ class ParamIntNN(PPanel): self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1)) self.spin.SetRange(0, 10000) # min/max integers sizer.Add(self.spin) - self.SetAutoLayout(True) - self.SetSizerAndFit(sizer) + self.SetSizer(sizer) wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange) def GetValue(self): return str(self.spin.GetValue()) @@ -388,8 +386,7 @@ class ParamUnit(PPanel): self.spin.SetRange(-10000, 10000) sizer.Add(self.text, 0, wx.EXPAND) sizer.Add(self.spin, 0, wx.EXPAND) - self.SetAutoLayout(True) - self.SetSizerAndFit(sizer) + self.SetSizer(sizer) self.spin.Bind(wx.EVT_SPIN_UP, self.OnSpinUp) self.spin.Bind(wx.EVT_SPIN_DOWN, self.OnSpinDown) def GetValue(self): @@ -434,7 +431,6 @@ class ParamMultilineText(PPanel): sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL) - self.SetAutoLayout(True) self.SetSizerAndFit(sizer) wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) @@ -463,8 +459,7 @@ class ParamText(PPanel): if textWidth == -1: option = 1 else: option = 0 sizer.Add(self.text, option, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2) - self.SetAutoLayout(True) - self.SetSizerAndFit(sizer) + self.SetSizer(sizer) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) def GetValue(self): return self.text.GetValue() @@ -489,6 +484,10 @@ class ParamEncoding(ParamText): def __init__(self, parent, name): ParamText.__init__(self, parent, name, 100) +class ParamComment(ParamText): + def __init__(self, parent, name): + ParamText.__init__(self, parent, name, 330 + buttonSize[0]) + class ContentDialog(wx.Dialog): def __init__(self, parent, value): # Load from resource @@ -607,8 +606,7 @@ class ParamContent(PPanel): sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL) - self.SetAutoLayout(True) - self.SetSizerAndFit(sizer) + self.SetSizer(sizer) self.textModified = False wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) @@ -747,8 +745,7 @@ class RadioBox(PPanel): button = wx.RadioButton(self, -1, i, size=(-1,buttonSize[1]), name=i) topSizer.Add(button, 0, wx.RIGHT, 5) wx.EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice) - self.SetAutoLayout(True) - self.SetSizerAndFit(topSizer) + self.SetSizer(topSizer) def SetStringSelection(self, value): self.freeze = True for i in self.choices: @@ -806,8 +803,7 @@ class ParamFile(PPanel): sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) self.button = wx.Button(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize) sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL) - self.SetAutoLayout(True) - self.SetSizerAndFit(sizer) + self.SetSizer(sizer) self.textModified = False wx.EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse) wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) @@ -934,5 +930,6 @@ paramDict = { 'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont, 'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool, 'tooltip': ParamText, 'bitmap': ParamBitmap, 'icon': ParamBitmap, - 'encoding': ParamEncoding, 'borders': ParamUnit + 'encoding': ParamEncoding, 'borders': ParamUnit, + 'comment': ParamComment } diff --git a/wxPython/wx/tools/XRCed/tree.py b/wxPython/wx/tools/XRCed/tree.py index 9ea2fb3924..abc0a8e452 100644 --- a/wxPython/wx/tools/XRCed/tree.py +++ b/wxPython/wx/tools/XRCed/tree.py @@ -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,7 @@ class ID_NEW: CONTEXT_HELP_BUTTON = wx.NewId() REF = wx.NewId() + COMMENT = wx.NewId() LAST = wx.NewId() @@ -193,10 +196,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 +273,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'), ], @@ -430,6 +437,8 @@ class XML_Tree(wx.TreeCtrl): def __init__(self, parent, id): wx.TreeCtrl.__init__(self, parent, id, style = wx.TR_HAS_BUTTONS | wx.TR_MULTIPLE) self.SetBackgroundColour(wx.Colour(224, 248, 224)) + self.fontComment = wx.Font(g.sysFont().GetPointSize(), wx.DEFAULT, + wx.FONTSTYLE_ITALIC, wx.NORMAL) # Register events wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged) # One works on Linux, another on Windows @@ -450,6 +459,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,19 +570,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 @@ -581,23 +594,29 @@ 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') + 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 @@ -605,7 +624,7 @@ 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) @@ -849,7 +868,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: @@ -1076,6 +1095,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 @@ -1099,6 +1119,7 @@ class XML_Tree(wx.TreeCtrl): m.Enable(ID_NEW.MENU_BAR, False) 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: @@ -1134,11 +1155,12 @@ class XML_Tree(wx.TreeCtrl): 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') @@ -1173,6 +1195,8 @@ 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()) diff --git a/wxPython/wx/tools/XRCed/undo.py b/wxPython/wx/tools/XRCed/undo.py index a064264b94..4b28a76c38 100644 --- a/wxPython/wx/tools/XRCed/undo.py +++ b/wxPython/wx/tools/XRCed/undo.py @@ -134,11 +134,11 @@ class UndoReplace: item = g.tree.ItemAtFullIndex(self.itemIndex) xxx = g.tree.GetPyData(item) # Replace with old element - parent = xxx.parent.element + parent = xxx.parent.node if xxx is self.xxx: # sizeritem or notebookpage - replace child - parent.replaceChild(self.xxx.child.element, xxx.child.element) + parent.replaceChild(self.xxx.child.node, xxx.child.node) else: - parent.replaceChild(self.xxx.element, xxx.element) + parent.replaceChild(self.xxx.node, xxx.node) self.xxx.parent = xxx.parent xxx = self.xxx g.tree.SetPyData(item, xxx) @@ -191,9 +191,9 @@ class UndoMove: ((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.removeChild(xxx.child.node) # detach child elem.unlink() # delete child container - elem = xxx.child.element # replace + elem = xxx.child.node # replace # This may help garbage collection xxx.child.parent = None isChildContainer = False @@ -227,9 +227,9 @@ class UndoMove: ((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.removeChild(xxx.child.node) # detach child elem.unlink() # delete child container - elem = xxx.child.element # replace + elem = xxx.child.node # replace # This may help garbage collection xxx.child.parent = None isChildContainer = False diff --git a/wxPython/wx/tools/XRCed/xrced.py b/wxPython/wx/tools/XRCed/xrced.py index fbfd96ca4e..11d29e8763 100644 --- a/wxPython/wx/tools/XRCed/xrced.py +++ b/wxPython/wx/tools/XRCed/xrced.py @@ -489,10 +489,14 @@ class Frame(wx.Frame): if not selected: return # key pressed event xxx = tree.GetPyData(selected) if wx.TheClipboard.Open(): - data = wx.CustomDataObject('XRCED') - # Set encoding in header - # (False,True) - s = xxx.element.toxml(encoding=expat.native_encoding) + if xxx.isElement: + data = wx.CustomDataObject('XRCED') + # Set encoding in header + # (False,True) + s = xxx.node.toxml(encoding=expat.native_encoding) + else: + data = wx.CustomDataObject('XRCED_node') + s = xxx.node.data data.SetData(cPickle.dumps(s)) wx.TheClipboard.SetData(data) wx.TheClipboard.Close() @@ -527,21 +531,28 @@ class Frame(wx.Frame): parent = tree.GetPyData(parentLeaf).treeObject() # Create a copy of clipboard pickled element - success = False + success = success_node = False if wx.TheClipboard.Open(): data = wx.CustomDataObject('XRCED') if wx.TheClipboard.IsSupported(data.GetFormat()): success = wx.TheClipboard.GetData(data) + if not success: # try other format + data = wx.CustomDataObject('XRCED_node') + if wx.TheClipboard.IsSupported(data.GetFormat()): + success_node = wx.TheClipboard.GetData(data) wx.TheClipboard.Close() - if not success: + if not success and not success_node: wx.MessageBox( "There is no data in the clipboard in the required format", "Error") return xml = cPickle.loads(data.GetData()) # xml representation of element - elem = minidom.parseString(xml).childNodes[0] + if success: + elem = minidom.parseString(xml).childNodes[0] + else: + elem = g.tree.dom.createComment(xml) # Tempopary xxx object to test things xxx = MakeXXXFromDOM(parent, elem) @@ -558,9 +569,9 @@ class Frame(wx.Frame): ((parent.isSizer and not isinstance(xxx, xxxSizerItem)) or \ (parentIsBook and not isinstance(xxx, xxxPage)) or \ not (parent.isSizer or parentIsBook)): - elem.removeChild(xxx.child.element) # detach child + elem.removeChild(xxx.child.node) # detach child elem.unlink() # delete child container - elem = xxx.child.element # replace + elem = xxx.child.node # replace # This may help garbage collection xxx.child.parent = None isChildContainer = False @@ -605,6 +616,9 @@ class Frame(wx.Frame): def ItemsAreCompatible(self, parent, child): # Check compatibility error = False + # Comments are always compatible + if child.__class__ == xxxComment: + return True # Top-level if child.__class__ in [xxxDialog, xxxFrame, xxxWizard]: # Top-level classes @@ -732,9 +746,9 @@ class Frame(wx.Frame): ((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.removeChild(xxx.child.node) # detach child elem.unlink() # delete child container - elem = xxx.child.element # replace + elem = xxx.child.node # replace # This may help garbage collection xxx.child.parent = None isChildContainer = False @@ -789,9 +803,9 @@ class Frame(wx.Frame): ((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.removeChild(xxx.child.node) # detach child elem.unlink() # delete child container - elem = xxx.child.element # replace + elem = xxx.child.node # replace # This may help garbage collection xxx.child.parent = None isChildContainer = False @@ -841,14 +855,19 @@ class Frame(wx.Frame): # Prepare undo data panel.Apply() index = tree.ItemFullIndex(selected) + xxx = tree.GetPyData(selected) parent = tree.GetPyData(tree.GetItemParent(selected)).treeObject() elem = tree.RemoveLeaf(selected) undoMan.RegisterUndo(UndoCutDelete(index, parent, elem)) if evt.GetId() == wx.ID_CUT: if wx.TheClipboard.Open(): - data = wx.CustomDataObject('XRCED') - # (False, True) - s = elem.toxml(encoding=expat.native_encoding) + if xxx.isElement: + data = wx.CustomDataObject('XRCED') + # (False, True) + s = elem.toxml(encoding=expat.native_encoding) + else: + data = wx.CustomDataObject('XRCED_node') + s = xxx.node.data data.SetData(cPickle.dumps(s)) wx.TheClipboard.SetData(data) wx.TheClipboard.Close() @@ -866,7 +885,7 @@ class Frame(wx.Frame): def OnSubclass(self, evt): selected = tree.selection xxx = tree.GetPyData(selected).treeObject() - elem = xxx.element + elem = xxx.node subclass = xxx.subclass dlg = wx.TextEntryDialog(self, 'Subclass:', defaultValue=subclass) if dlg.ShowModal() == wx.ID_OK: @@ -1063,29 +1082,33 @@ Homepage: http://xrced.sourceforge.net\ ref = wx.GetTextFromUser('Create reference to:', 'Create reference') if not ref: return xxx = MakeEmptyRefXXX(parent, ref) + elif evt.GetId() == ID_NEW.COMMENT: + xxx = MakeEmptyCommentXXX(parent) else: # Create empty element className = pullDownMenu.createMap[evt.GetId()] xxx = MakeEmptyXXX(parent, className) - # Set default name for top-level windows - if parent.__class__ == xxxMainNode: - cl = xxx.treeObject().__class__ - frame.maxIDs[cl] += 1 - xxx.setTreeName('%s%d' % (defaultIDs[cl], frame.maxIDs[cl])) - # And for some other standard controls - elif parent.__class__ == xxxStdDialogButtonSizer: - xxx.setTreeName(pullDownMenu.stdButtonIDs[evt.GetId()][0]) - # We can even set label - obj = xxx.treeObject() - elem = g.tree.dom.createElement('label') - elem.appendChild(g.tree.dom.createTextNode(pullDownMenu.stdButtonIDs[evt.GetId()][1])) - obj.params['label'] = xxxParam(elem) - xxx.treeObject().element.appendChild(elem) - # Insert new node, register undo - elem = xxx.element - newItem = tree.InsertNode(parentLeaf, parent, elem, nextItem) + if xxx.isElement: # true object + # Set default name for top-level windows + if parent.__class__ == xxxMainNode: + cl = xxx.treeObject().__class__ + frame.maxIDs[cl] += 1 + xxx.setTreeName('%s%d' % (defaultIDs[cl], frame.maxIDs[cl])) + # And for some other standard controls + elif parent.__class__ == xxxStdDialogButtonSizer: + xxx.setTreeName(pullDownMenu.stdButtonIDs[evt.GetId()][0]) + # We can even set label + obj = xxx.treeObject() + elem = g.tree.dom.createElement('label') + elem.appendChild(g.tree.dom.createTextNode(pullDownMenu.stdButtonIDs[evt.GetId()][1])) + obj.params['label'] = xxxParam(elem) + xxx.treeObject().node.appendChild(elem) + + newItem = tree.InsertNode(parentLeaf, parent, xxx.node, nextItem) + else: # comment node + newItem = tree.InsertNode(parentLeaf, parent, xxx.node, nextItem) undoMan.RegisterUndo(UndoPasteCreate(parentLeaf, parent, newItem, selected)) tree.EnsureVisible(newItem) tree.SelectItem(newItem) @@ -1093,7 +1116,7 @@ Homepage: http://xrced.sourceforge.net\ tree.ScrollTo(newItem) tree.Refresh() # Update view? - if g.testWin and tree.IsHighlatable(newItem): + if xxx.isElement and g.testWin and tree.IsHighlatable(newItem): if conf.autoRefresh: tree.needUpdate = True tree.pendingHighLight = newItem @@ -1106,7 +1129,7 @@ Homepage: http://xrced.sourceforge.net\ def OnReplace(self, evt): selected = tree.selection xxx = tree.GetPyData(selected).treeObject() - elem = xxx.element + elem = xxx.node parent = elem.parentNode undoMan.RegisterUndo(UndoReplace(selected)) # New class @@ -1383,6 +1406,10 @@ Homepage: http://xrced.sourceforge.net\ return True def Indent(self, node, indent = 0): + if node.nodeType == minidom.Node.COMMENT_NODE: + text = self.domCopy.createTextNode('\n' + ' ' * indent) + node.parentNode.insertBefore(text, node) + return # no children # Copy child list because it will change soon children = node.childNodes[:] # Main node doesn't need to be indented @@ -1396,7 +1423,8 @@ Homepage: http://xrced.sourceforge.net\ node.appendChild(text) # Indent children which are elements for n in children: - if n.nodeType == minidom.Node.ELEMENT_NODE: + if n.nodeType == minidom.Node.ELEMENT_NODE or \ + n.nodeType == minidom.Node.COMMENT_NODE: self.Indent(n, indent + 2) def Save(self, path): diff --git a/wxPython/wx/tools/XRCed/xrced.xrc b/wxPython/wx/tools/XRCed/xrced.xrc index 16ba037d94..59c625a1c2 100644 --- a/wxPython/wx/tools/XRCed/xrced.xrc +++ b/wxPython/wx/tools/XRCed/xrced.xrc @@ -1,5 +1,6 @@ + Text Dialog 1 @@ -619,4 +620,4 @@ - \ No newline at end of file + diff --git a/wxPython/wx/tools/XRCed/xxx.py b/wxPython/wx/tools/XRCed/xxx.py index 7226d26d91..659ddebfcc 100644 --- a/wxPython/wx/tools/XRCed/xxx.py +++ b/wxPython/wx/tools/XRCed/xxx.py @@ -189,6 +189,7 @@ class xxxObject: hasStyle = True # almost everyone hasName = True # has name attribute? isSizer = hasChild = False + isElement = True allParams = None # Some nodes have no parameters # Style parameters (all optional) styles = ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'tooltip'] @@ -210,7 +211,7 @@ class xxxObject: # parent is parent xxx object (or None if none), element is DOM element object def __init__(self, parent, element, refElem=None): self.parent = parent - self.element = element + self.node = element self.refElem = refElem self.undo = None # Reference are dereferenced @@ -230,33 +231,32 @@ class xxxObject: if self.hasName: self.name = element.getAttribute('name') # Set parameters (text element children) self.params = {} - nodes = element.childNodes[:] - for node in nodes: - if node.nodeType == minidom.Node.ELEMENT_NODE: - tag = node.tagName + for n in element.childNodes[:]: + if n.nodeType == minidom.Node.ELEMENT_NODE: + tag = n.tagName if tag in ['object', 'object_ref']: continue # do nothing for object children here 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: - self.special(tag, node) + self.special(tag, n) elif tag == 'content': if self.className == 'wxCheckListBox': - self.params[tag] = xxxParamContentCheckList(node) + self.params[tag] = xxxParamContentCheckList(n) else: - self.params[tag] = xxxParamContent(node) + self.params[tag] = xxxParamContent(n) elif tag == 'font': # has children - self.params[tag] = xxxParamFont(element, node) + self.params[tag] = xxxParamFont(element, n) elif tag in self.bitmapTags: # Can have attributes - self.params[tag] = xxxParamBitmap(node) + self.params[tag] = xxxParamBitmap(n) else: # simple parameter - self.params[tag] = xxxParam(node) - elif node.nodeType == minidom.Node.TEXT_NODE and node.data.isspace(): + self.params[tag] = xxxParam(n) + elif n.nodeType == minidom.Node.TEXT_NODE and n.data.isspace(): # Remove empty text nodes - element.removeChild(node) - node.unlink() + element.removeChild(n) + n.unlink() # Check that all required params are set for param in self.required: @@ -281,9 +281,9 @@ class xxxObject: break if found: nextTextElem = self.params[p].node - self.element.insertBefore(elem, nextTextElem) + self.node.insertBefore(elem, nextTextElem) else: - self.element.appendChild(elem) + self.node.appendChild(elem) else: wx.LogWarning('Required parameter %s of %s missing' % (param, self.className)) @@ -313,7 +313,7 @@ class xxxObject: if self.hasChild: obj = self.child else: obj = self obj.name = name - obj.element.setAttribute('name', name) + obj.node.setAttribute('name', name) # Special processing for growablecols-like parameters # represented by several nodes def special(self, tag, node): @@ -329,7 +329,7 @@ class xxxObject: node = g.tree.dom.createElement(param) text = g.tree.dom.createTextNode(str(i)) node.appendChild(text) - self.element.appendChild(node) + self.node.appendChild(node) self.special(param, node) # Imitation of FindResource/DoFindResource from xmlres.cpp @@ -377,7 +377,7 @@ class xxxParamFont(xxxObject, xxxNode): self.data = v def update(self, value): # `value' is a list of strings corresponding to all parameters - elem = self.element + elem = self.node # Remove old elements first childNodes = elem.childNodes[:] for node in childNodes: elem.removeChild(node) @@ -655,6 +655,16 @@ class xxxDateCtrl(xxxObject): winStyles = ['wxDP_DEFAULT', 'wxDP_SPIN', 'wxDP_DROPDOWN', 'wxDP_ALLOWNONE', 'wxDP_SHOWCENTURY'] +class xxxGrid(xxxObject): + allParams = ['pos', 'size', 'style'] + +class xxxFilePickerCtrl(xxxObject): + allParams = ['value', 'message', 'wildcard', 'pos', 'size', 'style'] + winStyles = ['wxFLP_OPEN', 'wxFLP_SAVE', 'wxFLP_OVERWRITE_PROMPT', + 'wxFLP_FILE_MUST_EXIST', 'wxFLP_CHANGE_DIR', + 'wxFLP_DEFAULT_STYLE'] + + ################################################################################ # Buttons @@ -905,6 +915,31 @@ class xxxUnknown(xxxObject): allParams = ['pos', 'size', 'style'] winStyles = ['wxNO_FULL_REPAINT_ON_RESIZE'] +################################################################################ +# Comment + +class xxxParamComment(xxxParam): + def __init__(self, node): + xxxNode.__init__(self, node) + self.textNode = node + +class xxxComment(xxxObject): + hasStyle = hasName = False + allParams = required = ['comment'] + + def __init__(self, parent, node): + self.parent = parent + self.node = node + self.isElement = False + self.undo = None + self.className = 'comment' + self.ref = self.subclass = None + self.params = {'comment': xxxParamComment(node)} + + def treeName(self): + # Replace newlines by \n to avoid tree item resizing + return self.params['comment'].value().replace('\n', r'\n') + ################################################################################ xxxDict = { @@ -956,6 +991,8 @@ xxxDict = { 'wxGenericDirCtrl': xxxGenericDirCtrl, 'wxSpinCtrl': xxxSpinCtrl, 'wxScrolledWindow': xxxScrolledWindow, + 'wxGrid': xxxGrid, + 'wxFilePickerCtrl': xxxFilePickerCtrl, 'wxDatePickerCtrl': xxxDateCtrl, 'wxBoxSizer': xxxBoxSizer, @@ -973,13 +1010,15 @@ xxxDict = { 'separator': xxxSeparator, 'unknown': xxxUnknown, + 'comment': xxxComment, } # Create IDs for all parameters of all classes paramIDs = {'fg': wx.NewId(), 'bg': wx.NewId(), 'exstyle': wx.NewId(), 'font': wx.NewId(), 'enabled': wx.NewId(), 'focused': wx.NewId(), 'hidden': wx.NewId(), 'tooltip': wx.NewId(), 'encoding': wx.NewId(), - 'cellpos': wx.NewId(), 'cellspan': wx.NewId() + 'cellpos': wx.NewId(), 'cellspan': wx.NewId(), + 'text': wx.NewId() } for cl in xxxDict.values(): if cl.allParams: @@ -992,25 +1031,29 @@ for cl in xxxDict.values(): # Test for object elements def IsObject(node): - return node.nodeType == minidom.Node.ELEMENT_NODE and node.tagName in ['object', 'object_ref'] + return node.nodeType == minidom.Node.ELEMENT_NODE and \ + node.tagName in ['object', 'object_ref'] or \ + node.nodeType == minidom.Node.COMMENT_NODE # Make XXX object from some DOM object, selecting correct class -def MakeXXXFromDOM(parent, element): - if element.tagName == 'object_ref': - ref = element.getAttribute('ref') +def MakeXXXFromDOM(parent, node): + if node.nodeType == minidom.Node.COMMENT_NODE: + return xxxComment(parent, node) + if node.tagName == 'object_ref': + ref = node.getAttribute('ref') refElem = FindResource(ref) if refElem: cls = refElem.getAttribute('class') - else: return xxxUnknown(parent, element) + else: return xxxUnknown(parent, node) else: refElem = None - cls = element.getAttribute('class') + cls = node.getAttribute('class') try: klass = xxxDict[cls] except KeyError: # If we encounter a weird class, use unknown template - print 'WARNING: unsupported class:', element.getAttribute('class') + print 'WARNING: unsupported class:', node.getAttribute('class') klass = xxxUnknown - return klass(parent, element, refElem) + return klass(parent, node, refElem) # Make empty DOM element def MakeEmptyDOM(className): @@ -1090,3 +1133,15 @@ def MakeEmptyRefXXX(parent, ref): #xxx.allParams.remove('label') return xxx +# Make empty comment node +def MakeEmptyCommentDOM(): + node = g.tree.dom.createComment('') + return node + +# Make empty xxxComment +def MakeEmptyCommentXXX(parent): + node = MakeEmptyCommentDOM() + # Now just make object + xxx = MakeXXXFromDOM(parent, node) + return xxx +