X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/75aa19469b8b31ae58d6e8956b0e4c7200e30578..bdba6fdc0db2329dbe2d4fe45262631b1b506caa:/wxPython/wx/tools/XRCed/xxx.py diff --git a/wxPython/wx/tools/XRCed/xxx.py b/wxPython/wx/tools/XRCed/xxx.py index 4144307da0..de19e8910b 100644 --- a/wxPython/wx/tools/XRCed/xxx.py +++ b/wxPython/wx/tools/XRCed/xxx.py @@ -7,6 +7,7 @@ from xml.dom import minidom from globals import * from params import * +import traceback, types # Base class for interface parameter classes class xxxNode: @@ -189,6 +190,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 +212,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 +232,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 +282,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 +314,32 @@ class xxxObject: if self.hasChild: obj = self.child else: obj = self obj.name = name - obj.element.setAttribute('name', name) + obj.node.setAttribute('name', name) + # Set normal (text) params + def set(self, param, value): + try: + self.params[param].update(value) + except KeyError: + p = xxxParam(g.tree.dom.createElement(param)) + p.update(value) + self.params[param] = p + # Special processing for growablecols-like parameters + # represented by several nodes + def special(self, tag, node): + if not self.params.has_key(tag): + # Create new multi-group + self.params[tag] = xxxParamMulti(node) + self.params[tag].append(xxxParamInt(node)) + def setSpecial(self, param, value): + # Straightforward implementation: remove, add again + self.params[param].remove() + del self.params[param] + for i in value: + node = g.tree.dom.createElement(param) + text = g.tree.dom.createTextNode(str(i)) + node.appendChild(text) + self.node.appendChild(node) + self.special(param, node) # Imitation of FindResource/DoFindResource from xmlres.cpp def DoFindResource(parent, name, classname, recursive): @@ -360,7 +386,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) @@ -638,6 +664,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 @@ -771,45 +807,11 @@ class xxxFlexGridSizer(xxxGridSizer): specials = ['growablecols', 'growablerows'] allParams = ['cols', 'rows', 'vgap', 'hgap'] + specials paramDict = {'growablecols': ParamIntList, 'growablerows': ParamIntList} - # Special processing for growable* parameters - # (they are represented by several nodes) - def special(self, tag, node): - if not self.params.has_key(tag): - # Create new multi-group - self.params[tag] = xxxParamMulti(node) - self.params[tag].append(xxxParamInt(node)) - def setSpecial(self, param, value): - # Straightforward implementation: remove, add again - self.params[param].remove() - del self.params[param] - for i in value: - node = g.tree.dom.createElement(param) - text = g.tree.dom.createTextNode(str(i)) - node.appendChild(text) - self.element.appendChild(node) - self.special(param, node) class xxxGridBagSizer(xxxSizer): specials = ['growablecols', 'growablerows'] allParams = ['vgap', 'hgap'] + specials - paramDict = {'growablecols':ParamIntList, 'growablerows':ParamIntList} - # Special processing for growable* parameters - # (they are represented by several nodes) - def special(self, tag, node): - if not self.params.has_key(tag): - # Create new multi-group - self.params[tag] = xxxParamMulti(node) - self.params[tag].append(xxxParamInt(node)) - def setSpecial(self, param, value): - # Straightforward implementation: remove, add again - self.params[param].remove() - del self.params[param] - for i in value: - node = g.tree.dom.createElement(param) - text = g.tree.dom.createTextNode(str(i)) - node.appendChild(text) - self.element.appendChild(node) - self.special(param, node) + paramDict = {'growablecols': ParamIntList, 'growablerows': ParamIntList} # Container with only one child. # Not shown in tree. @@ -843,7 +845,8 @@ class xxxChildContainer(xxxObject): class xxxSizerItem(xxxChildContainer): allParams = ['option', 'flag', 'border', 'minsize', 'ratio'] paramDict = {'option': ParamInt, 'minsize': ParamPosSize, 'ratio': ParamPosSize} - #default = {'cellspan': '1,1'} + defaults_panel = {} + defaults_control = {} def __init__(self, parent, element, refElem=None): # For GridBag sizer items, extra parameters added if isinstance(parent, xxxGridBagSizer): @@ -853,6 +856,13 @@ class xxxSizerItem(xxxChildContainer): if 'pos' in self.child.allParams: self.child.allParams = self.child.allParams[:] self.child.allParams.remove('pos') + # Set defaults for some children types + if isinstance(self.child, xxxContainer) and not self.child.isSizer: + for param,v in self.defaults_panel.items(): + self.set(param, v) + elif isinstance(self.child, xxxObject): + for param,v in self.defaults_control.items(): + self.set(param, v) def resetChild(self, xxx): xxxChildContainer.resetChild(self, xxx) # Remove pos parameter - not needed for sizeritems @@ -922,8 +932,129 @@ class xxxUnknown(xxxObject): allParams = ['pos', 'size', 'style'] winStyles = ['wxNO_FULL_REPAINT_ON_RESIZE'] +################################################################################ +# Comment + +_handlers = [] # custom handler classes/funcs +def getHandlers(): + return _handlers +def setHandlers(handlers): + global _handlers + _handlers = handlers +_CFuncPtr = None # ctypes function type + +def register(hndlr): + """Register hndlr function or XmlResourceHandler class.""" + if _CFuncPtr and isinstance(hndlr, _CFuncPtr): + _handlers.append(hndlr) + return + if not isinstance(hndlr, type): + wx.LogError('handler is not a type: %s' % hndlr) + elif not issubclass(hndlr, wx.xrc.XmlResourceHandler): + wx.LogError('handler is not a XmlResourceHandler: %s' % hndlr) + else: + _handlers.append(hndlr) + +def load_dl(path, localname=''): + """Load shared/dynamic library into xxx namespace. + + If path is not absolute or relative, try to find in the module's directory. + """ + if not localname: + localname = os.path.basename(os.path.splitext(path)[0]) + try: + import ctypes + global _CFuncPtr + _CFuncPtr = ctypes._CFuncPtr # use as a flag of loaded ctypes + #if not os.path.dirname(path) and os.path.isfile(path): + + except ImportError: + wx.LogError('ctypes module not found') + globals()[localname] = None + return + try: + dl = ctypes.CDLL(path) + globals()[localname] = dl + # Register AddXmlHandlers() if exists + try: + register(dl.AddXmlHandlers) + except: + pass + except: + wx.LogError('error loading dynamic library: %s' % path) + print traceback.print_exc() + +# Called when creating test window +def addHandlers(): + for h in _handlers: + if _CFuncPtr and isinstance(h, _CFuncPtr): + try: + apply(h, ()) + except: + wx.LogError('error calling DL func: "%s"' % h) + print traceback.print_exc() + else: + try: + xrc.XmlResource.Get().AddHandler(apply(h, ())) + except: + wx.LogError('error adding XmlHandler: "%s"' % h) + print traceback.print_exc() + +def custom(klassName, klass='unknown'): + """Define custom control based on xrcClass. + + klass: new object name + xrcClass: name of an existing XRC object class or + a class object defining class parameters. + """ + if type(klass) is str: + # Copy correct xxx class under new name + kl = xxxDict[klass] + xxxClass = types.ClassType('xxx' + klassName, kl.__bases__, kl.__dict__) + else: + xxxClass = klass + # Register param IDs + for param in klass.allParams + klass.paramDict.keys(): + if not paramIDs.has_key(param): + paramIDs[param] = wx.NewId() + # Insert in dictionaty + xxxDict[klassName] = xxxClass + # Add to menu + g.pullDownMenu.addCustom(klassName) + +class xxxParamComment(xxxParam): + def __init__(self, node): + xxxNode.__init__(self, node) + self.textNode = node + # Parse "pragma" comments + if node.data and node.data[0] == '%': + try: + code = node.data[1:] + exec code in globals() + except: + wx.LogError('exec error: "%s"' % code) + print traceback.print_exc() + +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') + ################################################################################ +# Mapping of XRC names to xxx classes xxxDict = { 'wxPanel': xxxPanel, 'wxDialog': xxxDialog, @@ -973,6 +1104,8 @@ xxxDict = { 'wxGenericDirCtrl': xxxGenericDirCtrl, 'wxSpinCtrl': xxxSpinCtrl, 'wxScrolledWindow': xxxScrolledWindow, + 'wxGrid': xxxGrid, + 'wxFilePickerCtrl': xxxFilePickerCtrl, 'wxDatePickerCtrl': xxxDateCtrl, 'wxBoxSizer': xxxBoxSizer, @@ -990,13 +1123,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: @@ -1009,25 +1144,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): @@ -1107,3 +1246,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 +