1 # Name:         xxx.py ('xxx' is easy to distinguish from 'wx' :) ) 
   2 # Purpose:      XML interface classes 
   3 # Author:       Roman Rolinsky <rolinsky@mema.ucl.ac.be> 
   7 from xml
.dom 
import minidom
 
  11 # Base class for interface parameter classes 
  13     def __init__(self
, node
): 
  16         self
.node
.parentNode
.removeChild(self
.node
) 
  19 # Generic (text) parameter class 
  20 class xxxParam(xxxNode
): 
  21     # Standard use: for text nodes 
  22     def __init__(self
, node
): 
  23         xxxNode
.__init
__(self
, node
) 
  24         if not node
.hasChildNodes(): 
  25             # If does not have child nodes, create empty text node 
  26             text 
= g
.tree
.dom
.createTextNode('') 
  27             node
.appendChild(text
) 
  29             text 
= node
.childNodes
[0] # first child must be text node 
  30             assert text
.nodeType 
== minidom
.Node
.TEXT_NODE
 
  31             # Append other text nodes if present and delete them 
  33             for n 
in node
.childNodes
[1:]: 
  34                 if n
.nodeType 
== minidom
.Node
.TEXT_NODE
: 
  39             if extraText
: text
.data 
= text
.data 
+ extraText
 
  40         # Use convertion from unicode to current encoding 
  42     # Value returns string 
  43     if wxUSE_UNICODE
:   # no conversion is needed 
  45             return self
.textNode
.data
 
  46         def update(self
, value
): 
  47             self
.textNode
.data 
= value
 
  51                 return self
.textNode
.data
.encode(g
.currentEncoding
) 
  53                 return self
.textNode
.data
.encode() 
  54         def update(self
, value
): 
  55             try: # handle exception if encoding is wrong 
  56                 self
.textNode
.data 
= unicode(value
, g
.currentEncoding
) 
  57             except UnicodeDecodeError: 
  58                 self
.textNode
.data 
= unicode(value
) 
  59                 #wxLogMessage("Unicode error: set encoding in file\nglobals.py to something appropriate") 
  62 class xxxParamInt(xxxParam
): 
  63     # Standard use: for text nodes 
  64     def __init__(self
, node
): 
  65         xxxParam
.__init
__(self
, node
) 
  66     # Value returns string 
  69             return int(self
.textNode
.data
) 
  71             return -1                   # invalid value 
  72     def update(self
, value
): 
  73         self
.textNode
.data 
= str(value
) 
  76 class xxxParamContent(xxxNode
): 
  77     def __init__(self
, node
): 
  78         xxxNode
.__init
__(self
, node
) 
  79         data
, l 
= [], []                # data is needed to quicker value retrieval 
  80         nodes 
= node
.childNodes
[:]      # make a copy of the child list 
  82             if n
.nodeType 
== minidom
.Node
.ELEMENT_NODE
: 
  83                 assert n
.tagName 
== 'item', 'bad content content' 
  84                 if not n
.hasChildNodes(): 
  85                     # If does not have child nodes, create empty text node 
  86                     text 
= g
.tree
.dom
.createTextNode('') 
  87                     node
.appendChild(text
) 
  90                     text 
= n
.childNodes
[0] # first child must be text node 
  91                     assert text
.nodeType 
== minidom
.Node
.TEXT_NODE
 
  93                 data
.append(str(text
.data
)) 
  97         self
.l
, self
.data 
= l
, data
 
 100     def update(self
, value
): 
 101         # If number if items is not the same, recreate children 
 102         if len(value
) != len(self
.l
):   # remove first if number of items has changed 
 103             childNodes 
= self
.node
.childNodes
[:] 
 105                 self
.node
.removeChild(n
) 
 108                 itemElem 
= g
.tree
.dom
.createElement('item') 
 109                 itemText 
= g
.tree
.dom
.createTextNode(str) 
 110                 itemElem
.appendChild(itemText
) 
 111                 self
.node
.appendChild(itemElem
) 
 115             for i 
in range(len(value
)): 
 116                 self
.l
[i
].data 
= value
[i
] 
 119 # Content parameter for checklist 
 120 class xxxParamContentCheckList(xxxNode
): 
 121     def __init__(self
, node
): 
 122         xxxNode
.__init
__(self
, node
) 
 123         data
, l 
= [], []                # data is needed to quicker value retrieval 
 124         nodes 
= node
.childNodes
[:]      # make a copy of the child list 
 126             if n
.nodeType 
== minidom
.Node
.ELEMENT_NODE
: 
 127                 assert n
.tagName 
== 'item', 'bad content content' 
 128                 checked 
= n
.getAttribute('checked') 
 129                 if not checked
: checked 
= 0 
 130                 if not n
.hasChildNodes(): 
 131                     # If does not have child nodes, create empty text node 
 132                     text 
= g
.tree
.dom
.createTextNode('') 
 133                     node
.appendChild(text
) 
 136                     text 
= n
.childNodes
[0] # first child must be text node 
 137                     assert text
.nodeType 
== minidom
.Node
.TEXT_NODE
 
 139                 data
.append((str(text
.data
), int(checked
))) 
 143         self
.l
, self
.data 
= l
, data
 
 146     def update(self
, value
): 
 147         # If number if items is not the same, recreate children 
 148         if len(value
) != len(self
.l
):   # remove first if number of items has changed 
 149             childNodes 
= self
.node
.childNodes
[:] 
 151                 self
.node
.removeChild(n
) 
 154                 itemElem 
= g
.tree
.dom
.createElement('item') 
 155                 # Add checked only if True 
 156                 if ch
: itemElem
.setAttribute('checked', '1') 
 157                 itemText 
= g
.tree
.dom
.createTextNode(s
) 
 158                 itemElem
.appendChild(itemText
) 
 159                 self
.node
.appendChild(itemElem
) 
 160                 l
.append((itemText
, itemElem
)) 
 163             for i 
in range(len(value
)): 
 164                 self
.l
[i
][0].data 
= value
[i
][0] 
 165                 self
.l
[i
][1].setAttribute('checked', str(value
[i
][1])) 
 169 class xxxParamBitmap(xxxParam
): 
 170     def __init__(self
, node
): 
 171         xxxParam
.__init
__(self
, node
) 
 172         self
.stock_id 
= node
.getAttribute('stock_id') 
 174         return [self
.stock_id
, xxxParam
.value(self
)] 
 175     def update(self
, value
): 
 176         self
.stock_id 
= value
[0] 
 178             self
.node
.setAttribute('stock_id', self
.stock_id
) 
 179         elif self
.node
.hasAttribute('stock_id'): 
 180             self
.node
.removeAttribute('stock_id') 
 181         xxxParam
.update(self
, value
[1]) 
 183 ################################################################################ 
 185 # Classes to interface DOM objects 
 188     hasChildren 
= False                 # has children elements? 
 189     hasStyle 
= True                     # almost everyone 
 190     hasName 
= True                      # has name attribute? 
 191     isSizer 
= hasChild 
= False 
 192     allParams 
= None                    # Some nodes have no parameters 
 193     # Style parameters (all optional) 
 194     styles 
= ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'tooltip'] 
 198     bitmapTags 
= ['bitmap', 'bitmap2', 'icon'] 
 199     # Required paremeters: none by default 
 201     # Default parameters with default values 
 205     # Window styles and extended styles 
 209     # Construct a new xxx object from DOM element 
 210     # parent is parent xxx object (or None if none), element is DOM element object 
 211     def __init__(self
, parent
, element
, refElem
=None): 
 213         self
.element 
= element
 
 214         self
.refElem 
= refElem
 
 216         # Reference are dereferenced 
 217         if element
.tagName 
== 'object_ref': 
 218             # Find original object 
 219             self
.ref 
= element
.getAttribute('ref') 
 221                 self
.className 
= self
.refElem
.getAttribute('class') 
 223                 self
.className 
= 'xxxUnknown' 
 228             self
.className 
= element
.getAttribute('class') 
 229         self
.subclass 
= element
.getAttribute('subclass') 
 230         if self
.hasName
: self
.name 
= element
.getAttribute('name') 
 231         # Set parameters (text element children) 
 233         nodes 
= element
.childNodes
[:] 
 235             if node
.nodeType 
== minidom
.Node
.ELEMENT_NODE
: 
 237                 if tag 
in ['object', 'object_ref']: 
 238                     continue            # do nothing for object children here 
 239                 elif tag 
not in self
.allParams 
and tag 
not in self
.styles
: 
 240                     print 'WARNING: unknown parameter for %s: %s' % \
 
 241                           (self
.className
, tag
) 
 242                 elif tag 
in self
.specials
: 
 243                     self
.special(tag
, node
) 
 244                 elif tag 
== 'content': 
 245                     if self
.className 
== 'wxCheckListBox': 
 246                         self
.params
[tag
] = xxxParamContentCheckList(node
) 
 248                         self
.params
[tag
] = xxxParamContent(node
) 
 249                 elif tag 
== 'font': # has children 
 250                     self
.params
[tag
] = xxxParamFont(element
, node
) 
 251                 elif tag 
in self
.bitmapTags
: 
 252                     # Can have attributes 
 253                     self
.params
[tag
] = xxxParamBitmap(node
) 
 254                 else:                   # simple parameter 
 255                     self
.params
[tag
] = xxxParam(node
) 
 256             elif node
.nodeType 
== minidom
.Node
.TEXT_NODE 
and node
.data
.isspace(): 
 257                 # Remove empty text nodes 
 258                 element
.removeChild(node
) 
 261         # Check that all required params are set 
 262         for param 
in self
.required
: 
 263             if not self
.params
.has_key(param
): 
 264                 # If default is specified, set it 
 265                 if self
.default
.has_key(param
): 
 266                     elem 
= g
.tree
.dom
.createElement(param
) 
 267                     if param 
== 'content': 
 268                         if self
.className 
== 'wxCheckListBox': 
 269                             self
.params
[param
] = xxxParamContentCheckList(elem
) 
 271                             self
.params
[param
] = xxxParamContent(elem
) 
 273                         self
.params
[param
] = xxxParam(elem
) 
 274                     # Find place to put new element: first present element after param 
 276                     paramStyles 
= self
.allParams 
+ self
.styles
 
 277                     for p 
in paramStyles
[paramStyles
.index(param
) + 1:]: 
 278                         # Content params don't have same type 
 279                         if self
.params
.has_key(p
) and p 
!= 'content': 
 283                         nextTextElem 
= self
.params
[p
].node
 
 284                         self
.element
.insertBefore(elem
, nextTextElem
) 
 286                         self
.element
.appendChild(elem
) 
 288                     wxLogWarning('Required parameter %s of %s missing' % 
 289                                  (param
, self
.className
)) 
 290     # Returns real tree object 
 291     def treeObject(self
): 
 292         if self
.hasChild
: return self
.child
 
 294     # Returns tree image index 
 296         if self
.hasChild
: return self
.child
.treeImage() 
 298     # Class name plus wx name 
 300         if self
.hasChild
: return self
.child
.treeName() 
 301         if self
.subclass
: className 
= self
.subclass
 
 302         else: className 
= self
.className
 
 303         if self
.hasName 
and self
.name
: return className 
+ ' "' + self
.name 
+ '"' 
 305     # Class name or subclass 
 307         if self
.subclass
: name 
= self
.subclass 
+ '(' + self
.className 
+ ')' 
 308         name 
= self
.className
 
 309         if self
.ref
: name 
= 'ref: ' + self
.ref 
+ ', ' + name
 
 311     # Sets name of tree object 
 312     def setTreeName(self
, name
): 
 313         if self
.hasChild
: obj 
= self
.child
 
 316         obj
.element
.setAttribute('name', name
) 
 318 # Imitation of FindResource/DoFindResource from xmlres.cpp 
 319 def DoFindResource(parent
, name
, classname
, recursive
): 
 320     for n 
in parent
.childNodes
: 
 321         if n
.nodeType 
== minidom
.Node
.ELEMENT_NODE 
and \
 
 322                n
.tagName 
in ['object', 'object_ref'] and \
 
 323                n
.getAttribute('name') == name
: 
 324             cls 
= n
.getAttribute('class') 
 325             if not classname 
or cls 
== classname
:  return n
 
 326             if not cls 
or n
.tagName 
== 'object_ref': 
 327                 refName 
= n
.getAttribute('ref') 
 328                 if not refName
:  continue 
 329                 refNode 
= FindResource(refName
) 
 330                 if refName 
and refNode
.getAttribute('class') == classname
: 
 333         for n 
in parent
.childNodes
: 
 334             if n
.nodeType 
== minidom
.Node
.ELEMENT_NODE 
and \
 
 335                    n
.tagName 
in ['object', 'object_ref']: 
 336                 found 
= DoFindResource(n
, name
, classname
, True) 
 337                 if found
:  return found
 
 338 def FindResource(name
, classname
='', recursive
=True): 
 339     found 
= DoFindResource(g
.tree
.mainNode
, name
, classname
, recursive
) 
 340     if found
:  return found
 
 341     wxLogError('XRC resource "%s" not found!' % name
) 
 344 ################################################################################ 
 346 # This is a little special: it is both xxxObject and xxxNode 
 347 class xxxParamFont(xxxObject
, xxxNode
): 
 348     allParams 
= ['size', 'family', 'style', 'weight', 'underlined', 
 350     def __init__(self
, parent
, element
): 
 351         xxxObject
.__init
__(self
, parent
, element
) 
 352         xxxNode
.__init
__(self
, element
) 
 353         self
.parentNode 
= parent       
# required to behave similar to DOM node 
 355         for p 
in self
.allParams
: 
 357                 v
.append(str(self
.params
[p
].value())) 
 361     def update(self
, value
): 
 362         # `value' is a list of strings corresponding to all parameters 
 364         # Remove old elements first 
 365         childNodes 
= elem
.childNodes
[:] 
 366         for node 
in childNodes
: elem
.removeChild(node
) 
 370         for param 
in self
.allParams
: 
 372                 fontElem 
= g
.tree
.dom
.createElement(param
) 
 373                 textNode 
= g
.tree
.dom
.createTextNode(value
[i
]) 
 374                 self
.params
[param
] = textNode
 
 375                 fontElem
.appendChild(textNode
) 
 376                 elem
.appendChild(fontElem
) 
 383 ################################################################################ 
 385 class xxxContainer(xxxObject
): 
 389 # Simulate normal parameter for encoding 
 392         return g
.currentEncoding
 
 393     def update(self
, val
): 
 394         g
.currentEncoding 
= val
 
 396 # Special class for root node 
 397 class xxxMainNode(xxxContainer
): 
 398     allParams 
= ['encoding'] 
 399     hasStyle 
= hasName 
= False 
 400     def __init__(self
, dom
): 
 401         xxxContainer
.__init
__(self
, None, dom
.documentElement
) 
 402         self
.className 
= 'XML tree' 
 403         # Reset required parameters after processing XML, because encoding is 
 405         self
.required 
= ['encoding'] 
 406         self
.params
['encoding'] = xxxEncoding() 
 408 ################################################################################ 
 411 class xxxPanel(xxxContainer
): 
 412     allParams 
= ['pos', 'size', 'style'] 
 413     winStyles 
= ['wxNO_3D', 'wxTAB_TRAVERSAL'] 
 414     styles 
= ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle', 
 417 class xxxDialog(xxxContainer
): 
 418     allParams 
= ['title', 'centered', 'pos', 'size', 'style'] 
 419     paramDict 
= {'centered': ParamBool}
 
 421     default 
= {'title': ''}
 
 422     winStyles 
= ['wxDEFAULT_DIALOG_STYLE', 'wxCAPTION',  
 423                  'wxSTAY_ON_TOP', 'wxSYSTEM_MENU', 'wxTHICK_FRAME', 
 424                  'wxRESIZE_BORDER', 'wxRESIZE_BOX', 'wxCLOSE_BOX', 
 425                  'wxMAXIMIZE_BOX', 'wxMINIMIZE_BOX', 
 426                  'wxDIALOG_MODAL', 'wxDIALOG_MODELESS', 'wxDIALOG_NO_PARENT' 
 427                  'wxNO_3D', 'wxTAB_TRAVERSAL']                  
 428     exStyles 
= ['wxWS_EX_VALIDATE_RECURSIVELY', 'wxDIALOG_EX_METAL'] 
 429     styles 
= ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle', 
 432 class xxxFrame(xxxContainer
): 
 433     allParams 
= ['title', 'centered', 'pos', 'size', 'style'] 
 434     paramDict 
= {'centered': ParamBool}
 
 436     default 
= {'title': ''}
 
 437     winStyles 
= ['wxDEFAULT_FRAME_STYLE', 'wxDEFAULT_DIALOG_STYLE', 'wxCAPTION',  
 438                  'wxSTAY_ON_TOP', 'wxSYSTEM_MENU', 'wxTHICK_FRAME', 
 439                  'wxRESIZE_BORDER', 'wxRESIZE_BOX', 'wxCLOSE_BOX', 
 440                  'wxMAXIMIZE_BOX', 'wxMINIMIZE_BOX', 
 441                  'wxFRAME_NO_TASKBAR', 'wxFRAME_SHAPED', 'wxFRAME_TOOL_WINDOW', 
 442                  'wxFRAME_FLOAT_ON_PARENT', 
 443                  'wxNO_3D', 'wxTAB_TRAVERSAL']                  
 444     exStyles 
= ['wxWS_EX_VALIDATE_RECURSIVELY', 'wxFRAME_EX_METAL'] 
 445     styles 
= ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle', 
 448 class xxxTool(xxxObject
): 
 449     allParams 
= ['bitmap', 'bitmap2', 'radio', 'toggle', 'tooltip', 'longhelp', 'label'] 
 450     required 
= ['bitmap'] 
 451     paramDict 
= {'bitmap2': ParamBitmap, 'radio': ParamBool, 'toggle': ParamBool}
 
 454 class xxxToolBar(xxxContainer
): 
 455     allParams 
= ['bitmapsize', 'margins', 'packing', 'separation', 'dontattachtoframe', 
 456                  'pos', 'size', 'style'] 
 458     paramDict 
= {'bitmapsize': ParamPosSize
, 'margins': ParamPosSize
, 
 459                  'packing': ParamUnit
, 'separation': ParamUnit
, 
 460                  'dontattachtoframe': ParamBool
, 'style': ParamNonGenericStyle
} 
 461     winStyles 
= ['wxTB_FLAT', 'wxTB_DOCKABLE', 'wxTB_VERTICAL', 'wxTB_HORIZONTAL', 
 462                  'wxTB_3DBUTTONS','wxTB_TEXT', 'wxTB_NOICONS', 'wxTB_NODIVIDER', 
 463                  'wxTB_NOALIGN', 'wxTB_HORZ_LAYOUT', 'wxTB_HORZ_TEXT'] 
 465 class xxxStatusBar(xxxObject
): 
 467     allParams 
= ['fields', 'widths', 'styles', 'style'] 
 468     paramDict 
= {'fields': ParamIntNN
, 'widths': ParamText
, 'styles': ParamText
, 
 469                  'style': ParamNonGenericStyle
} 
 470     winStyles 
= ['wxST_SIZEGRIP'] 
 472 class xxxWizard(xxxContainer
): 
 473     allParams 
= ['title', 'bitmap', 'pos'] 
 475     default 
= {'title': ''}
 
 477     exStyles 
= ['wxWIZARD_EX_HELPBUTTON'] 
 479 class xxxWizardPage(xxxContainer
): 
 480     allParams 
= ['bitmap'] 
 484 class xxxWizardPageSimple(xxxContainer
): 
 485     allParams 
= ['bitmap'] 
 489 ################################################################################ 
 492 class xxxBitmap(xxxObject
): 
 493     allParams 
= ['bitmap'] 
 494     required 
= ['bitmap'] 
 497 class xxxIcon(xxxObject
): 
 500 ################################################################################ 
 503 class xxxStaticText(xxxObject
): 
 504     allParams 
= ['label', 'pos', 'size', 'style'] 
 506     default 
= {'label': ''}
 
 507     winStyles 
= ['wxALIGN_LEFT', 'wxALIGN_RIGHT', 'wxALIGN_CENTRE', 'wxST_NO_AUTORESIZE'] 
 509 class xxxStaticLine(xxxObject
): 
 510     allParams 
= ['pos', 'size', 'style'] 
 511     winStyles 
= ['wxLI_HORIZONTAL', 'wxLI_VERTICAL'] 
 513 class xxxStaticBitmap(xxxObject
): 
 514     allParams 
= ['bitmap', 'pos', 'size', 'style'] 
 515     required 
= ['bitmap'] 
 517 class xxxTextCtrl(xxxObject
): 
 518     allParams 
= ['value', 'pos', 'size', 'style'] 
 519     winStyles 
= ['wxTE_NO_VSCROLL', 
 521                  'wxTE_PROCESS_ENTER', 
 537     paramDict 
= {'value': ParamMultilineText}
 
 539 class xxxChoice(xxxObject
): 
 540     allParams 
= ['content', 'selection', 'pos', 'size', 'style'] 
 541     required 
= ['content'] 
 542     default 
= {'content': '[]'}
 
 543     winStyles 
= ['wxCB_SORT'] 
 545 class xxxSlider(xxxObject
): 
 546     allParams 
= ['value', 'min', 'max', 'pos', 'size', 'style', 
 547                  'tickfreq', 'pagesize', 'linesize', 'thumb', 'tick', 
 549     paramDict 
= {'value': ParamInt
, 'tickfreq': ParamIntNN
, 'pagesize': ParamIntNN
, 
 550                  'linesize': ParamIntNN
, 'thumb': ParamUnit
,  
 551                  'tick': ParamInt
, 'selmin': ParamInt
, 'selmax': ParamInt
} 
 552     required 
= ['value', 'min', 'max'] 
 553     winStyles 
= ['wxSL_HORIZONTAL', 'wxSL_VERTICAL', 'wxSL_AUTOTICKS', 'wxSL_LABELS', 
 554                  'wxSL_LEFT', 'wxSL_RIGHT', 'wxSL_TOP', 'wxSL_BOTTOM', 
 555                  'wxSL_BOTH', 'wxSL_SELRANGE', 'wxSL_INVERSE'] 
 557 class xxxGauge(xxxObject
): 
 558     allParams 
= ['range', 'pos', 'size', 'style', 'value', 'shadow', 'bezel'] 
 559     paramDict 
= {'range': ParamIntNN
, 'value': ParamIntNN
, 
 560                  'shadow': ParamIntNN
, 'bezel': ParamIntNN
} 
 561     winStyles 
= ['wxGA_HORIZONTAL', 'wxGA_VERTICAL', 'wxGA_PROGRESSBAR', 'wxGA_SMOOTH'] 
 563 class xxxScrollBar(xxxObject
): 
 564     allParams 
= ['pos', 'size', 'style', 'value', 'thumbsize', 'range', 'pagesize'] 
 565     paramDict 
= {'value': ParamIntNN
, 'range': ParamIntNN
, 'thumbsize': ParamIntNN
, 
 566                  'pagesize': ParamIntNN
} 
 567     winStyles 
= ['wxSB_HORIZONTAL', 'wxSB_VERTICAL'] 
 569 class xxxListCtrl(xxxObject
): 
 570     allParams 
= ['pos', 'size', 'style'] 
 571     winStyles 
= ['wxLC_LIST', 'wxLC_REPORT', 'wxLC_ICON', 'wxLC_SMALL_ICON', 
 572                  'wxLC_ALIGN_TOP', 'wxLC_ALIGN_LEFT', 'wxLC_AUTOARRANGE', 
 573                  'wxLC_USER_TEXT', 'wxLC_EDIT_LABELS', 'wxLC_NO_HEADER', 
 574                  'wxLC_SINGLE_SEL', 'wxLC_SORT_ASCENDING', 'wxLC_SORT_DESCENDING', 
 575                  'wxLC_VIRTUAL', 'wxLC_HRULES', 'wxLC_VRULES', 'wxLC_NO_SORT_HEADER'] 
 577 class xxxTreeCtrl(xxxObject
): 
 578     allParams 
= ['pos', 'size', 'style'] 
 579     winStyles 
= ['wxTR_EDIT_LABELS', 
 582                  'wxTR_TWIST_BUTTONS', 
 584                  'wxTR_FULL_ROW_HIGHLIGHT', 
 585                  'wxTR_LINES_AT_ROOT', 
 588                  'wxTR_HAS_VARIABLE_ROW_HEIGHT', 
 592                  'wxTR_DEFAULT_STYLE'] 
 594 class xxxHtmlWindow(xxxObject
): 
 595     allParams 
= ['pos', 'size', 'style', 'borders', 'url', 'htmlcode'] 
 596     paramDict 
= {'htmlcode':ParamMultilineText}
 
 597     winStyles 
= ['wxHW_SCROLLBAR_NEVER', 'wxHW_SCROLLBAR_AUTO', 'wxHW_NO_SELECTION'] 
 599 class xxxCalendarCtrl(xxxObject
): 
 600     allParams 
= ['pos', 'size', 'style'] 
 601     winStyles 
= ['wxCAL_SUNDAY_FIRST', 'wxCAL_MONDAY_FIRST', 'wxCAL_SHOW_HOLIDAYS', 
 602                  'wxCAL_NO_YEAR_CHANGE', 'wxCAL_NO_MONTH_CHANGE', 
 603                  'wxCAL_SEQUENTIAL_MONTH_SELECTION', 'wxCAL_SHOW_SURROUNDING_WEEKS'] 
 605 class xxxNotebook(xxxContainer
): 
 606     allParams 
= ['pos', 'size', 'style'] 
 607     winStyles 
= ['wxNB_DEFAULT', 'wxNB_LEFT', 'wxNB_RIGHT', 'wxNB_BOTTOM', 
 608                  'wxNB_FIXEDWIDTH', 'wxNB_MULTILINE', 'wxNB_NOPAGETHEME'] 
 610 class xxxChoicebook(xxxContainer
): 
 611     allParams 
= ['pos', 'size', 'style'] 
 612     winStyles 
= ['wxCHB_DEFAULT', 'wxCHB_LEFT', 'wxCHB_RIGHT', 'wxCHB_TOP', 'wxCHB_BOTTOM'] 
 614 class xxxListbook(xxxContainer
): 
 615     allParams 
= ['pos', 'size', 'style'] 
 616     winStyles 
= ['wxLB_DEFAULT', 'wxLB_LEFT', 'wxLB_RIGHT', 'wxLB_TOP', 'wxLB_BOTTOM'] 
 618 class xxxSplitterWindow(xxxContainer
): 
 619     allParams 
= ['orientation', 'sashpos', 'minsize', 'pos', 'size', 'style'] 
 620     paramDict 
= {'orientation': ParamOrientation, 'sashpos': ParamUnit, 'minsize': ParamUnit }
 
 621     winStyles 
= ['wxSP_3D', 'wxSP_3DSASH', 'wxSP_3DBORDER',  
 622                  'wxSP_FULLSASH', 'wxSP_NOBORDER', 'wxSP_PERMIT_UNSPLIT', 'wxSP_LIVE_UPDATE', 
 625 class xxxGenericDirCtrl(xxxObject
): 
 626     allParams 
= ['defaultfolder', 'filter', 'defaultfilter', 'pos', 'size', 'style'] 
 627     paramDict 
= {'defaultfilter': ParamIntNN}
 
 628     winStyles 
= ['wxDIRCTRL_DIR_ONLY', 'wxDIRCTRL_3D_INTERNAL', 'wxDIRCTRL_SELECT_FIRST', 
 629                  'wxDIRCTRL_SHOW_FILTERS'] 
 631 class xxxScrolledWindow(xxxContainer
): 
 632     allParams 
= ['pos', 'size', 'style'] 
 633     winStyles 
= ['wxHSCROLL', 'wxVSCROLL', 'wxNO_3D', 'wxTAB_TRAVERSAL'] 
 635 class xxxDateCtrl(xxxObject
): 
 636     allParams 
= ['pos', 'size', 'style', 'borders'] 
 637     winStyles 
= ['wxDP_DEFAULT', 'wxDP_SPIN', 'wxDP_DROPDOWN', 
 638                  'wxDP_ALLOWNONE', 'wxDP_SHOWCENTURY'] 
 640 ################################################################################ 
 643 class xxxButton(xxxObject
): 
 644     allParams 
= ['label', 'default', 'pos', 'size', 'style'] 
 645     paramDict 
= {'default': ParamBool}
 
 647     winStyles 
= ['wxBU_LEFT', 'wxBU_TOP', 'wxBU_RIGHT', 'wxBU_BOTTOM', 'wxBU_EXACTFIT'] 
 649 class xxxBitmapButton(xxxObject
): 
 650     allParams 
= ['bitmap', 'selected', 'focus', 'disabled', 'default', 
 651                  'pos', 'size', 'style'] 
 652     required 
= ['bitmap'] 
 653     winStyles 
= ['wxBU_AUTODRAW', 'wxBU_LEFT', 'wxBU_RIGHT', 
 654                  'wxBU_TOP', 'wxBU_BOTTOM', 'wxBU_EXACTFIT'] 
 656 class xxxRadioButton(xxxObject
): 
 657     allParams 
= ['label', 'value', 'pos', 'size', 'style'] 
 658     paramDict 
= {'value': ParamBool}
 
 660     winStyles 
= ['wxRB_GROUP', 'wxRB_SINGLE'] 
 662 class xxxSpinButton(xxxObject
): 
 663     allParams 
= ['value', 'min', 'max', 'pos', 'size', 'style'] 
 664     paramDict 
= {'value': ParamInt}
 
 665     winStyles 
= ['wxSP_HORIZONTAL', 'wxSP_VERTICAL', 'wxSP_ARROW_KEYS', 'wxSP_WRAP'] 
 667 class xxxSpinCtrl(xxxObject
): 
 668     allParams 
= ['value', 'min', 'max', 'pos', 'size', 'style'] 
 669     paramDict 
= {'value': ParamInt}
 
 670     winStyles 
= ['wxSP_HORIZONTAL', 'wxSP_VERTICAL', 'wxSP_ARROW_KEYS', 'wxSP_WRAP'] 
 672 class xxxToggleButton(xxxObject
): 
 673     allParams 
= ['label', 'checked', 'pos', 'size', 'style'] 
 674     paramDict 
= {'checked': ParamBool}
 
 677 ################################################################################ 
 680 class xxxStaticBox(xxxObject
): 
 681     allParams 
= ['label', 'pos', 'size', 'style'] 
 684 class xxxRadioBox(xxxObject
): 
 685     allParams 
= ['label', 'content', 'selection', 'dimension', 'pos', 'size', 'style'] 
 686     paramDict 
= {'dimension': ParamIntNN}
 
 687     required 
= ['label', 'content'] 
 688     default 
= {'content': '[]'}
 
 689     winStyles 
= ['wxRA_SPECIFY_ROWS', 'wxRA_SPECIFY_COLS', 'wxRA_HORIZONTAL', 
 692 class xxxCheckBox(xxxObject
): 
 693     allParams 
= ['label', 'checked', 'pos', 'size', 'style'] 
 694     paramDict 
= {'checked': ParamBool}
 
 695     winStyles 
= ['wxCHK_2STATE', 'wxCHK_3STATE', 'wxCHK_ALLOW_3RD_STATE_FOR_USER', 
 699 class xxxComboBox(xxxObject
): 
 700     allParams 
= ['content', 'selection', 'value', 'pos', 'size', 'style'] 
 701     required 
= ['content'] 
 702     default 
= {'content': '[]'}
 
 703     winStyles 
= ['wxCB_SIMPLE', 'wxCB_SORT', 'wxCB_READONLY', 'wxCB_DROPDOWN'] 
 705 class xxxListBox(xxxObject
): 
 706     allParams 
= ['content', 'selection', 'pos', 'size', 'style'] 
 707     required 
= ['content'] 
 708     default 
= {'content': '[]'}
 
 709     winStyles 
= ['wxLB_SINGLE', 'wxLB_MULTIPLE', 'wxLB_EXTENDED', 'wxLB_HSCROLL', 
 710                  'wxLB_ALWAYS_SB', 'wxLB_NEEDED_SB', 'wxLB_SORT'] 
 712 class xxxCheckList(xxxObject
): 
 713     allParams 
= ['content', 'pos', 'size', 'style'] 
 714     required 
= ['content'] 
 715     default 
= {'content': '[]'}
 
 716     winStyles 
= ['wxLB_SINGLE', 'wxLB_MULTIPLE', 'wxLB_EXTENDED', 'wxLB_HSCROLL', 
 717                  'wxLB_ALWAYS_SB', 'wxLB_NEEDED_SB', 'wxLB_SORT'] 
 718     paramDict 
= {'content': ParamContentCheckList}
 
 720 ################################################################################ 
 723 class xxxSizer(xxxContainer
): 
 724     hasName 
= hasStyle 
= False 
 725     paramDict 
= {'orient': ParamOrient}
 
 727     itemTag 
= 'sizeritem'               # different for some sizers 
 729 class xxxBoxSizer(xxxSizer
): 
 730     allParams 
= ['orient'] 
 731     required 
= ['orient'] 
 732     default 
= {'orient': 'wxVERTICAL'}
 
 733     # Tree icon depends on orientation 
 735         if self
.params
['orient'].value() == 'wxHORIZONTAL': return self
.imageH
 
 736         else: return self
.imageV
 
 738 class xxxStaticBoxSizer(xxxBoxSizer
): 
 739     allParams 
= ['label', 'orient'] 
 740     required 
= ['label', 'orient'] 
 742 class xxxGridSizer(xxxSizer
): 
 743     allParams 
= ['cols', 'rows', 'vgap', 'hgap'] 
 745     default 
= {'cols': '2', 'rows': '2'}
 
 747 class xxxStdDialogButtonSizer(xxxSizer
): 
 751 # For repeated parameters 
 753     def __init__(self
, node
): 
 755         self
.l
, self
.data 
= [], [] 
 756     def append(self
, param
): 
 758         self
.data
.append(param
.value()) 
 764         self
.l
, self
.data 
= [], [] 
 766 class xxxFlexGridSizer(xxxGridSizer
): 
 767     specials 
= ['growablecols', 'growablerows'] 
 768     allParams 
= ['cols', 'rows', 'vgap', 'hgap'] + specials
 
 769     paramDict 
= {'growablecols': ParamIntList, 'growablerows': ParamIntList}
 
 770     # Special processing for growable* parameters 
 771     # (they are represented by several nodes) 
 772     def special(self
, tag
, node
): 
 773         if not self
.params
.has_key(tag
): 
 774             # Create new multi-group 
 775             self
.params
[tag
] = xxxParamMulti(node
) 
 776         self
.params
[tag
].append(xxxParamInt(node
)) 
 777     def setSpecial(self
, param
, value
): 
 778         # Straightforward implementation: remove, add again 
 779         self
.params
[param
].remove() 
 780         del self
.params
[param
] 
 782             node 
= g
.tree
.dom
.createElement(param
) 
 783             text 
= g
.tree
.dom
.createTextNode(str(i
)) 
 784             node
.appendChild(text
) 
 785             self
.element
.appendChild(node
) 
 786             self
.special(param
, node
) 
 788 class xxxGridBagSizer(xxxSizer
): 
 789     specials 
= ['growablecols', 'growablerows'] 
 790     allParams 
= ['vgap', 'hgap'] + specials
 
 791     paramDict 
= {'growablecols':ParamIntList, 'growablerows':ParamIntList}
 
 792     # Special processing for growable* parameters 
 793     # (they are represented by several nodes) 
 794     def special(self
, tag
, node
): 
 795         if not self
.params
.has_key(tag
): 
 796             # Create new multi-group 
 797             self
.params
[tag
] = xxxParamMulti(node
) 
 798         self
.params
[tag
].append(xxxParamInt(node
)) 
 799     def setSpecial(self
, param
, value
): 
 800         # Straightforward implementation: remove, add again 
 801         self
.params
[param
].remove() 
 802         del self
.params
[param
] 
 804             node 
= g
.tree
.dom
.createElement(param
) 
 805             text 
= g
.tree
.dom
.createTextNode(str(i
)) 
 806             node
.appendChild(text
) 
 807             self
.element
.appendChild(node
) 
 808             self
.special(param
, node
) 
 810 # Container with only one child. 
 812 class xxxChildContainer(xxxObject
): 
 813     hasName 
= hasStyle 
= False 
 815     def __init__(self
, parent
, element
, refElem
=None): 
 816         xxxObject
.__init
__(self
, parent
, element
, refElem
) 
 817         # Must have one child with 'object' tag, but we don't check it 
 818         nodes 
= element
.childNodes
[:]   # create copy 
 820             if node
.nodeType 
== minidom
.Node
.ELEMENT_NODE
: 
 821                 if node
.tagName 
in ['object', 'object_ref']: 
 822                     # Create new xxx object for child node 
 823                     self
.child 
= MakeXXXFromDOM(self
, node
) 
 824                     self
.child
.parent 
= parent
 
 825                     # Copy hasChildren and isSizer attributes 
 826                     self
.hasChildren 
= self
.child
.hasChildren
 
 827                     self
.isSizer 
= self
.child
.isSizer
 
 830                 element
.removeChild(node
) 
 832         assert 0, 'no child found' 
 834 class xxxSizerItem(xxxChildContainer
): 
 835     allParams 
= ['option', 'flag', 'border', 'minsize', 'ratio'] 
 836     paramDict 
= {'option': ParamInt, 'minsize': ParamPosSize, 'ratio': ParamPosSize}
 
 837     #default = {'cellspan': '1,1'} 
 838     def __init__(self
, parent
, element
, refElem
=None): 
 839         # For GridBag sizer items, extra parameters added 
 840         if isinstance(parent
, xxxGridBagSizer
): 
 841             self
.allParams 
= self
.allParams 
+ ['cellpos', 'cellspan'] 
 842         xxxChildContainer
.__init
__(self
, parent
, element
, refElem
) 
 843         # Remove pos parameter - not needed for sizeritems 
 844         if 'pos' in self
.child
.allParams
: 
 845             self
.child
.allParams 
= self
.child
.allParams
[:] 
 846             self
.child
.allParams
.remove('pos') 
 848 class xxxSizerItemButton(xxxSizerItem
): 
 851     def __init__(self
, parent
, element
, refElem
=None): 
 852         xxxChildContainer
.__init
__(self
, parent
, element
, refElem
=None) 
 853         # Remove pos parameter - not needed for sizeritems 
 854         if 'pos' in self
.child
.allParams
: 
 855             self
.child
.allParams 
= self
.child
.allParams
[:] 
 856             self
.child
.allParams
.remove('pos') 
 858 class xxxPage(xxxChildContainer
): 
 859     allParams 
= ['label', 'selected'] 
 860     paramDict 
= {'selected': ParamBool}
 
 862     def __init__(self
, parent
, element
, refElem
=None): 
 863         xxxChildContainer
.__init
__(self
, parent
, element
, refElem
) 
 864         # pos and size dont matter for notebookpages 
 865         if 'pos' in self
.child
.allParams
: 
 866             self
.child
.allParams 
= self
.child
.allParams
[:] 
 867             self
.child
.allParams
.remove('pos') 
 868         if 'size' in self
.child
.allParams
: 
 869             self
.child
.allParams 
= self
.child
.allParams
[:] 
 870             self
.child
.allParams
.remove('size') 
 872 class xxxSpacer(xxxObject
): 
 873     hasName 
= hasStyle 
= False 
 874     allParams 
= ['size', 'option', 'flag', 'border'] 
 875     paramDict 
= {'option': ParamInt}
 
 876     default 
= {'size': '0,0'}
 
 878 class xxxMenuBar(xxxContainer
): 
 879     allParams 
= ['style'] 
 880     paramDict 
= {'style': ParamNonGenericStyle}    
# no generic styles 
 881     winStyles 
= ['wxMB_DOCKABLE'] 
 883 class xxxMenu(xxxContainer
): 
 884     allParams 
= ['label', 'help', 'style'] 
 885     default 
= {'label': ''}
 
 886     paramDict 
= {'style': ParamNonGenericStyle}    
# no generic styles 
 887     winStyles 
= ['wxMENU_TEAROFF'] 
 889 class xxxMenuItem(xxxObject
): 
 890     allParams 
= ['label', 'bitmap', 'accel', 'help', 
 891                  'checkable', 'radio', 'enabled', 'checked'] 
 892     default 
= {'label': ''}
 
 895 class xxxSeparator(xxxObject
): 
 896     hasName 
= hasStyle 
= False 
 898 ################################################################################ 
 901 class xxxUnknown(xxxObject
): 
 902     allParams 
= ['pos', 'size', 'style'] 
 903     winStyles 
= ['wxNO_FULL_REPAINT_ON_RESIZE'] 
 905 ################################################################################ 
 909     'wxDialog': xxxDialog
, 
 912     'wxToolBar': xxxToolBar
, 
 913     'wxStatusBar': xxxStatusBar
, 
 914     'wxWizard': xxxWizard
, 
 915     'wxWizardPage': xxxWizardPage
, 
 916     'wxWizardPageSimple': xxxWizardPageSimple
, 
 918     'wxBitmap': xxxBitmap
, 
 921     'wxButton': xxxButton
, 
 922     'wxBitmapButton': xxxBitmapButton
, 
 923     'wxRadioButton': xxxRadioButton
, 
 924     'wxSpinButton': xxxSpinButton
, 
 925     'wxToggleButton' : xxxToggleButton
, 
 927     'wxStaticBox': xxxStaticBox
, 
 928     'wxStaticBitmap': xxxStaticBitmap
, 
 929     'wxRadioBox': xxxRadioBox
, 
 930     'wxComboBox': xxxComboBox
, 
 931     'wxCheckBox': xxxCheckBox
, 
 932     'wxListBox': xxxListBox
, 
 934     'wxStaticText': xxxStaticText
, 
 935     'wxStaticLine': xxxStaticLine
, 
 936     'wxTextCtrl': xxxTextCtrl
, 
 937     'wxChoice': xxxChoice
, 
 938     'wxSlider': xxxSlider
, 
 940     'wxScrollBar': xxxScrollBar
, 
 941     'wxTreeCtrl': xxxTreeCtrl
, 
 942     'wxListCtrl': xxxListCtrl
, 
 943     'wxCheckListBox': xxxCheckList
, 
 944     'notebookpage': xxxPage
, 
 945     'choicebookpage': xxxPage
, 
 946     'listbookpage': xxxPage
, 
 947     'wxNotebook': xxxNotebook
, 
 948     'wxChoicebook': xxxChoicebook
, 
 949     'wxListbook': xxxListbook
, 
 950     'wxSplitterWindow': xxxSplitterWindow
, 
 951     'wxHtmlWindow': xxxHtmlWindow
, 
 952     'wxCalendarCtrl': xxxCalendarCtrl
, 
 953     'wxGenericDirCtrl': xxxGenericDirCtrl
, 
 954     'wxSpinCtrl': xxxSpinCtrl
, 
 955     'wxScrolledWindow': xxxScrolledWindow
, 
 956     'wxDatePickerCtrl': xxxDateCtrl
, 
 958     'wxBoxSizer': xxxBoxSizer
, 
 959     'wxStaticBoxSizer': xxxStaticBoxSizer
, 
 960     'wxGridSizer': xxxGridSizer
, 
 961     'wxFlexGridSizer': xxxFlexGridSizer
, 
 962     'wxGridBagSizer': xxxGridBagSizer
, 
 963     'wxStdDialogButtonSizer': xxxStdDialogButtonSizer
, 
 964     'sizeritem': xxxSizerItem
, 'button': xxxSizerItemButton
, 
 967     'wxMenuBar': xxxMenuBar
, 
 969     'wxMenuItem': xxxMenuItem
, 
 970     'separator': xxxSeparator
, 
 972     'unknown': xxxUnknown
, 
 975 # Create IDs for all parameters of all classes 
 976 paramIDs 
= {'fg': wxNewId(), 'bg': wxNewId(), 'exstyle': wxNewId(), 'font': wxNewId(), 
 977             'enabled': wxNewId(), 'focused': wxNewId(), 'hidden': wxNewId(), 
 978             'tooltip': wxNewId(), 'encoding': wxNewId(), 
 979             'cellpos': wxNewId(), 'cellspan': wxNewId() 
 981 for cl 
in xxxDict
.values(): 
 983         for param 
in cl
.allParams 
+ cl
.paramDict
.keys(): 
 984             if not paramIDs
.has_key(param
): 
 985                 paramIDs
[param
] = wxNewId() 
 987 ################################################################################ 
 990 # Test for object elements 
 992     return node
.nodeType 
== minidom
.Node
.ELEMENT_NODE 
and node
.tagName 
in ['object', 'object_ref'] 
 994 # Make XXX object from some DOM object, selecting correct class 
 995 def MakeXXXFromDOM(parent
, element
): 
 996     if element
.tagName 
== 'object_ref': 
 997         ref 
= element
.getAttribute('ref') 
 998         refElem 
= FindResource(ref
) 
 999         if refElem
: cls 
= refElem
.getAttribute('class') 
1000         else: return xxxUnknown(parent
, element
) 
1003         cls 
= element
.getAttribute('class') 
1005         klass 
= xxxDict
[cls
] 
1007         # If we encounter a weird class, use unknown template 
1008         print 'WARNING: unsupported class:', element
.getAttribute('class') 
1010     return klass(parent
, element
, refElem
) 
1012 # Make empty DOM element 
1013 def MakeEmptyDOM(className
): 
1014     elem 
= g
.tree
.dom
.createElement('object') 
1015     elem
.setAttribute('class', className
) 
1016     # Set required and default parameters 
1017     xxxClass 
= xxxDict
[className
] 
1018     defaultNotRequired 
= filter(lambda x
, l
=xxxClass
.required
: x 
not in l
, 
1019                                 xxxClass
.default
.keys()) 
1020     for param 
in xxxClass
.required 
+ defaultNotRequired
: 
1021         textElem 
= g
.tree
.dom
.createElement(param
) 
1023             textNode 
= g
.tree
.dom
.createTextNode(xxxClass
.default
[param
]) 
1025             textNode 
= g
.tree
.dom
.createTextNode('') 
1026         textElem
.appendChild(textNode
) 
1027         elem
.appendChild(textElem
) 
1030 # Make empty XXX object 
1031 def MakeEmptyXXX(parent
, className
): 
1032     # Make corresponding DOM object first 
1033     elem 
= MakeEmptyDOM(className
) 
1034     # If parent is a sizer, we should create sizeritem object, except for spacers 
1036         if parent
.isSizer 
and className 
!= 'spacer': 
1037             sizerItemElem 
= MakeEmptyDOM(parent
.itemTag
) 
1038             sizerItemElem
.appendChild(elem
) 
1039             elem 
= sizerItemElem
 
1040         elif isinstance(parent
, xxxNotebook
): 
1041             pageElem 
= MakeEmptyDOM('notebookpage') 
1042             pageElem
.appendChild(elem
) 
1044         elif isinstance(parent
, xxxChoicebook
): 
1045             pageElem 
= MakeEmptyDOM('choicebookpage') 
1046             pageElem
.appendChild(elem
) 
1048         elif isinstance(parent
, xxxListbook
): 
1049             pageElem 
= MakeEmptyDOM('listbookpage') 
1050             pageElem
.appendChild(elem
) 
1052     # Now just make object 
1053     return MakeXXXFromDOM(parent
, elem
) 
1055 # Make empty DOM element for reference 
1056 def MakeEmptyRefDOM(ref
): 
1057     elem 
= g
.tree
.dom
.createElement('object_ref') 
1058     elem
.setAttribute('ref', ref
) 
1061 # Make empty XXX object 
1062 def MakeEmptyRefXXX(parent
, ref
): 
1063     # Make corresponding DOM object first 
1064     elem 
= MakeEmptyRefDOM(ref
) 
1065     # If parent is a sizer, we should create sizeritem object, except for spacers 
1068             sizerItemElem 
= MakeEmptyDOM(parent
.itemTag
) 
1069             sizerItemElem
.appendChild(elem
) 
1070             elem 
= sizerItemElem
 
1071         elif isinstance(parent
, xxxNotebook
): 
1072             pageElem 
= MakeEmptyDOM('notebookpage') 
1073             pageElem
.appendChild(elem
) 
1075         elif isinstance(parent
, xxxChoicebook
): 
1076             pageElem 
= MakeEmptyDOM('choicebookpage') 
1077             pageElem
.appendChild(elem
) 
1079         elif isinstance(parent
, xxxListbook
): 
1080             pageElem 
= MakeEmptyDOM('listbookpage') 
1081             pageElem
.appendChild(elem
) 
1083     # Now just make object 
1084     return MakeXXXFromDOM(parent
, elem
)