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
 
  50             return self
.textNode
.data
.encode(g
.currentEncoding
) 
  51         def update(self
, value
): 
  52             self
.textNode
.data 
= unicode(value
, g
.currentEncoding
) 
  55 class xxxParamInt(xxxParam
): 
  56     # Standard use: for text nodes 
  57     def __init__(self
, node
): 
  58         xxxParam
.__init
__(self
, node
) 
  59     # Value returns string 
  62             return int(self
.textNode
.data
) 
  64             return -1                   # invalid value 
  65     def update(self
, value
): 
  66         self
.textNode
.data 
= str(value
) 
  69 class xxxParamContent(xxxNode
): 
  70     def __init__(self
, node
): 
  71         xxxNode
.__init
__(self
, node
) 
  72         data
, l 
= [], []                # data is needed to quicker value retrieval 
  73         nodes 
= node
.childNodes
[:]      # make a copy of the child list 
  75             if n
.nodeType 
== minidom
.Node
.ELEMENT_NODE
: 
  76                 assert n
.tagName 
== 'item', 'bad content content' 
  77                 if not n
.hasChildNodes(): 
  78                     # If does not have child nodes, create empty text node 
  79                     text 
= g
.tree
.dom
.createTextNode('') 
  80                     node
.appendChild(text
) 
  83                     text 
= n
.childNodes
[0] # first child must be text node 
  84                     assert text
.nodeType 
== minidom
.Node
.TEXT_NODE
 
  86                 data
.append(str(text
.data
)) 
  90         self
.l
, self
.data 
= l
, data
 
  93     def update(self
, value
): 
  94         # If number if items is not the same, recreate children 
  95         if len(value
) != len(self
.l
):   # remove first if number of items has changed 
  96             childNodes 
= self
.node
.childNodes
[:] 
  98                 self
.node
.removeChild(n
) 
 101                 itemElem 
= g
.tree
.dom
.createElement('item') 
 102                 itemText 
= g
.tree
.dom
.createTextNode(str) 
 103                 itemElem
.appendChild(itemText
) 
 104                 self
.node
.appendChild(itemElem
) 
 108             for i 
in range(len(value
)): 
 109                 self
.l
[i
].data 
= value
[i
] 
 112 # Content parameter for checklist 
 113 class xxxParamContentCheckList(xxxNode
): 
 114     def __init__(self
, node
): 
 115         xxxNode
.__init
__(self
, node
) 
 116         data
, l 
= [], []                # data is needed to quicker value retrieval 
 117         nodes 
= node
.childNodes
[:]      # make a copy of the child list 
 119             if n
.nodeType 
== minidom
.Node
.ELEMENT_NODE
: 
 120                 assert n
.tagName 
== 'item', 'bad content content' 
 121                 checked 
= n
.getAttribute('checked') 
 122                 if not checked
: checked 
= 0 
 123                 if not n
.hasChildNodes(): 
 124                     # If does not have child nodes, create empty text node 
 125                     text 
= g
.tree
.dom
.createTextNode('') 
 126                     node
.appendChild(text
) 
 129                     text 
= n
.childNodes
[0] # first child must be text node 
 130                     assert text
.nodeType 
== minidom
.Node
.TEXT_NODE
 
 132                 data
.append((str(text
.data
), int(checked
))) 
 136         self
.l
, self
.data 
= l
, data
 
 139     def update(self
, value
): 
 140         # If number if items is not the same, recreate children 
 141         if len(value
) != len(self
.l
):   # remove first if number of items has changed 
 142             childNodes 
= self
.node
.childNodes
[:] 
 144                 self
.node
.removeChild(n
) 
 147                 itemElem 
= g
.tree
.dom
.createElement('item') 
 148                 # Add checked only if True 
 149                 if ch
: itemElem
.setAttribute('checked', '1') 
 150                 itemText 
= g
.tree
.dom
.createTextNode(s
) 
 151                 itemElem
.appendChild(itemText
) 
 152                 self
.node
.appendChild(itemElem
) 
 153                 l
.append((itemText
, itemElem
)) 
 156             for i 
in range(len(value
)): 
 157                 self
.l
[i
][0].data 
= value
[i
][0] 
 158                 self
.l
[i
][1].setAttribute('checked', str(value
[i
][1])) 
 162 class xxxParamBitmap(xxxParam
): 
 163     def __init__(self
, node
): 
 164         xxxParam
.__init
__(self
, node
) 
 165         self
.stock_id 
= node
.getAttribute('stock_id') 
 167         return [self
.stock_id
, xxxParam
.value(self
)] 
 168     def update(self
, value
): 
 169         self
.stock_id 
= value
[0] 
 171             self
.node
.setAttribute('stock_id', self
.stock_id
) 
 172         elif self
.node
.hasAttribute('stock_id'): 
 173             self
.node
.removeAttribute('stock_id') 
 174         xxxParam
.update(self
, value
[1]) 
 176 ################################################################################ 
 178 # Classes to interface DOM objects 
 181     hasChildren 
= False                 # has children elements? 
 182     hasStyle 
= True                     # almost everyone 
 183     hasName 
= True                      # has name attribute? 
 184     isSizer 
= hasChild 
= False 
 185     allParams 
= None                    # Some nodes have no parameters 
 186     # Style parameters (all optional) 
 187     styles 
= ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'tooltip'] 
 191     bitmapTags 
= ['bitmap', 'bitmap2', 'icon'] 
 192     # Required paremeters: none by default 
 194     # Default parameters with default values 
 198     # Window styles and extended styles 
 202     # Construct a new xxx object from DOM element 
 203     # parent is parent xxx object (or None if none), element is DOM element object 
 204     def __init__(self
, parent
, element
): 
 206         self
.element 
= element
 
 209         self
.className 
= element
.getAttribute('class') 
 210         self
.subclass 
= element
.getAttribute('subclass') 
 211         if self
.hasName
: self
.name 
= element
.getAttribute('name') 
 212         # Set parameters (text element children) 
 214         nodes 
= element
.childNodes
[:] 
 216             if node
.nodeType 
== minidom
.Node
.ELEMENT_NODE
: 
 219                     continue            # do nothing for object children here 
 220                 if tag 
not in self
.allParams 
and tag 
not in self
.styles
: 
 221                     print 'WARNING: unknown parameter for %s: %s' % \
 
 222                           (self
.className
, tag
) 
 223                 elif tag 
in self
.specials
: 
 224                     self
.special(tag
, node
) 
 225                 elif tag 
== 'content': 
 226                     if self
.className 
== 'wxCheckListBox': 
 227                         self
.params
[tag
] = xxxParamContentCheckList(node
) 
 229                         self
.params
[tag
] = xxxParamContent(node
) 
 230                 elif tag 
== 'font': # has children 
 231                     self
.params
[tag
] = xxxParamFont(element
, node
) 
 232                 elif tag 
in self
.bitmapTags
: 
 233                     # Can have attributes 
 234                     self
.params
[tag
] = xxxParamBitmap(node
) 
 235                 else:                   # simple parameter 
 236                     self
.params
[tag
] = xxxParam(node
) 
 238                 # Remove all other nodes 
 239                 element
.removeChild(node
) 
 241         # Check that all required params are set 
 242         for param 
in self
.required
: 
 243             if not self
.params
.has_key(param
): 
 244                 # If default is specified, set it 
 245                 if self
.default
.has_key(param
): 
 246                     elem 
= g
.tree
.dom
.createElement(param
) 
 247                     if param 
== 'content': 
 248                         if self
.className 
== 'wxCheckListBox': 
 249                             self
.params
[param
] = xxxParamContentCheckList(elem
) 
 251                             self
.params
[param
] = xxxParamContent(elem
) 
 253                         self
.params
[param
] = xxxParam(elem
) 
 254                     # Find place to put new element: first present element after param 
 256                     paramStyles 
= self
.allParams 
+ self
.styles
 
 257                     for p 
in paramStyles
[paramStyles
.index(param
) + 1:]: 
 258                         # Content params don't have same type 
 259                         if self
.params
.has_key(p
) and p 
!= 'content': 
 263                         nextTextElem 
= self
.params
[p
].node
 
 264                         self
.element
.insertBefore(elem
, nextTextElem
) 
 266                         self
.element
.appendChild(elem
) 
 268                     wxLogWarning('Required parameter %s of %s missing' % 
 269                                  (param
, self
.className
)) 
 270     # Returns real tree object 
 271     def treeObject(self
): 
 272         if self
.hasChild
: return self
.child
 
 274     # Returns tree image index 
 276         if self
.hasChild
: return self
.child
.treeImage() 
 278     # Class name plus wx name 
 280         if self
.hasChild
: return self
.child
.treeName() 
 281         if self
.subclass
: className 
= self
.subclass
 
 282         else: className 
= self
.className
 
 283         if self
.hasName 
and self
.name
: return className 
+ ' "' + self
.name 
+ '"' 
 285     # Class name or subclass 
 287         if self
.subclass
: return self
.subclass 
+ '(' + self
.className 
+ ')' 
 288         else: return self
.className
 
 290 ################################################################################ 
 292 # This is a little special: it is both xxxObject and xxxNode 
 293 class xxxParamFont(xxxObject
, xxxNode
): 
 294     allParams 
= ['size', 'style', 'weight', 'family', 'underlined', 
 296     def __init__(self
, parent
, element
): 
 297         xxxObject
.__init
__(self
, parent
, element
) 
 298         xxxNode
.__init
__(self
, element
) 
 299         self
.parentNode 
= parent       
# required to behave similar to DOM node 
 301         for p 
in self
.allParams
: 
 303                 v
.append(str(self
.params
[p
].value())) 
 307     def update(self
, value
): 
 308         # `value' is a list of strings corresponding to all parameters 
 310         # Remove old elements first 
 311         childNodes 
= elem
.childNodes
[:] 
 312         for node 
in childNodes
: elem
.removeChild(node
) 
 316         for param 
in self
.allParams
: 
 318                 fontElem 
= g
.tree
.dom
.createElement(param
) 
 319                 textNode 
= g
.tree
.dom
.createTextNode(value
[i
]) 
 320                 self
.params
[param
] = textNode
 
 321                 fontElem
.appendChild(textNode
) 
 322                 elem
.appendChild(fontElem
) 
 329 ################################################################################ 
 331 class xxxContainer(xxxObject
): 
 334 # Simulate normal parameter for encoding 
 336     def __init__(self
, val
): 
 340     def update(self
, val
): 
 343 # Special class for root node 
 344 class xxxMainNode(xxxContainer
): 
 345     allParams 
= ['encoding'] 
 346     hasStyle 
= hasName 
= False 
 347     def __init__(self
, dom
): 
 348         xxxContainer
.__init
__(self
, None, dom
.documentElement
) 
 349         self
.className 
= 'XML tree' 
 350         # Reset required parameters after processing XML, because encoding is 
 352         self
.required 
= ['encoding'] 
 353         self
.params
['encoding'] = xxxEncoding(dom
.encoding
) 
 355 ################################################################################ 
 358 class xxxPanel(xxxContainer
): 
 359     allParams 
= ['pos', 'size', 'style'] 
 360     styles 
= ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle', 
 362     winStyles 
= ['wxNO_3D', 'wxTAB_TRAVERSAL', 'wxCLIP_CHILDREN'] 
 363     exStyles 
= ['wxWS_EX_VALIDATE_RECURSIVELY'] 
 365 class xxxDialog(xxxContainer
): 
 366     allParams 
= ['title', 'centered', 'pos', 'size', 'style'] 
 367     paramDict 
= {'centered': ParamBool}
 
 369     default 
= {'title': ''}
 
 370     winStyles 
= ['wxDEFAULT_DIALOG_STYLE', 'wxSTAY_ON_TOP', 
 371 ##                 'wxDIALOG_MODAL', 'wxDIALOG_MODELESS', 
 372                  'wxCAPTION', 'wxSYSTEM_MENU', 'wxRESIZE_BORDER', 'wxRESIZE_BOX', 
 374                  'wxNO_3D', 'wxTAB_TRAVERSAL', 'wxCLIP_CHILDREN'] 
 375     styles 
= ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle', 
 377     exStyles 
= ['wxWS_EX_VALIDATE_RECURSIVELY'] 
 379 class xxxFrame(xxxContainer
): 
 380     allParams 
= ['title', 'centered', 'pos', 'size', 'style'] 
 381     paramDict 
= {'centered': ParamBool}
 
 383     default 
= {'title': ''}
 
 384     winStyles 
= ['wxDEFAULT_FRAME_STYLE', 'wxDEFAULT_DIALOG_STYLE', 
 386                  'wxCAPTION', 'wxSYSTEM_MENU', 'wxRESIZE_BORDER', 
 387                  'wxRESIZE_BOX', 'wxMINIMIZE_BOX', 'wxMAXIMIZE_BOX', 
 388                  'wxFRAME_FLOAT_ON_PARENT', 'wxFRAME_TOOL_WINDOW', 
 389                  'wxNO_3D', 'wxTAB_TRAVERSAL', 'wxCLIP_CHILDREN'] 
 390     styles 
= ['fg', 'bg', 'font', 'enabled', 'focused', 'hidden', 'exstyle', 
 392     exStyles 
= ['wxWS_EX_VALIDATE_RECURSIVELY'] 
 394 class xxxTool(xxxObject
): 
 395     allParams 
= ['bitmap', 'bitmap2', 'toggle', 'tooltip', 'longhelp'] 
 396     required 
= ['bitmap'] 
 397     paramDict 
= {'bitmap2': ParamBitmap, 'toggle': ParamBool}
 
 400 class xxxToolBar(xxxContainer
): 
 401     allParams 
= ['bitmapsize', 'margins', 'packing', 'separation', 
 402                  'pos', 'size', 'style'] 
 404     paramDict 
= {'bitmapsize': ParamPosSize
, 'margins': ParamPosSize
, 
 405                  'packing': ParamInt
, 'separation': ParamInt
, 
 406                  'style': ParamNonGenericStyle
} 
 407     winStyles 
= ['wxTB_FLAT', 'wxTB_DOCKABLE', 'wxTB_VERTICAL', 'wxTB_HORIZONTAL'] 
 409 ################################################################################ 
 412 class xxxBitmap(xxxObject
): 
 413     allParams 
= ['bitmap'] 
 414     required 
= ['bitmap'] 
 417 class xxxIcon(xxxObject
): 
 421 ################################################################################ 
 424 class xxxStaticText(xxxObject
): 
 425     allParams 
= ['label', 'pos', 'size', 'style'] 
 427     default 
= {'label': ''}
 
 428     winStyles 
= ['wxALIGN_LEFT', 'wxALIGN_RIGHT', 'wxALIGN_CENTRE', 'wxST_NO_AUTORESIZE'] 
 430 class xxxStaticLine(xxxObject
): 
 431     allParams 
= ['pos', 'size', 'style'] 
 432     winStyles 
= ['wxLI_HORIZONTAL', 'wxLI_VERTICAL'] 
 434 class xxxStaticBitmap(xxxObject
): 
 435     allParams 
= ['bitmap', 'pos', 'size', 'style'] 
 436     required 
= ['bitmap'] 
 438 class xxxTextCtrl(xxxObject
): 
 439     allParams 
= ['value', 'pos', 'size', 'style'] 
 440     winStyles 
= ['wxTE_PROCESS_ENTER', 'wxTE_PROCESS_TAB', 'wxTE_MULTILINE', 
 441               'wxTE_PASSWORD', 'wxTE_READONLY', 'wxHSCROLL'] 
 442     paramDict 
= {'value': ParamMultilineText}
 
 444 class xxxChoice(xxxObject
): 
 445     allParams 
= ['content', 'selection', 'pos', 'size', 'style'] 
 446     required 
= ['content'] 
 447     default 
= {'content': '[]'}
 
 448     winStyles 
= ['wxCB_SORT'] 
 450 class xxxSlider(xxxObject
): 
 451     allParams 
= ['value', 'min', 'max', 'pos', 'size', 'style', 
 452                  'tickfreq', 'pagesize', 'linesize', 'thumb', 'tick', 
 454     paramDict 
= {'value': ParamInt
, 'tickfreq': ParamInt
, 'pagesize': ParamInt
, 
 455                  'linesize': ParamInt
, 'thumb': ParamInt
, 'thumb': ParamInt
, 
 456                  'tick': ParamInt
, 'selmin': ParamInt
, 'selmax': ParamInt
} 
 457     required 
= ['value', 'min', 'max'] 
 458     winStyles 
= ['wxSL_HORIZONTAL', 'wxSL_VERTICAL', 'wxSL_AUTOTICKS', 'wxSL_LABELS', 
 459                  'wxSL_LEFT', 'wxSL_RIGHT', 'wxSL_TOP', 'wxSL_BOTTOM', 
 460                  'wxSL_BOTH', 'wxSL_SELRANGE'] 
 462 class xxxGauge(xxxObject
): 
 463     allParams 
= ['range', 'pos', 'size', 'style', 'value', 'shadow', 'bezel'] 
 464     paramDict 
= {'range': ParamInt
, 'value': ParamInt
, 
 465                  'shadow': ParamInt
, 'bezel': ParamInt
} 
 466     winStyles 
= ['wxGA_HORIZONTAL', 'wxGA_VERTICAL', 'wxGA_PROGRESSBAR', 'wxGA_SMOOTH'] 
 468 class xxxScrollBar(xxxObject
): 
 469     allParams 
= ['pos', 'size', 'style', 'value', 'thumbsize', 'range', 'pagesize'] 
 470     paramDict 
= {'value': ParamInt
, 'range': ParamInt
, 'thumbsize': ParamInt
, 
 471                  'pagesize': ParamInt
} 
 472     winStyles 
= ['wxSB_HORIZONTAL', 'wxSB_VERTICAL'] 
 474 class xxxListCtrl(xxxObject
): 
 475     allParams 
= ['pos', 'size', 'style'] 
 476     winStyles 
= ['wxLC_LIST', 'wxLC_REPORT', 'wxLC_ICON', 'wxLC_SMALL_ICON', 
 477               'wxLC_ALIGN_TOP', 'wxLC_ALIGN_LEFT', 'wxLC_AUTOARRANGE', 
 478               'wxLC_USER_TEXT', 'wxLC_EDIT_LABELS', 'wxLC_NO_HEADER', 
 479               'wxLC_SINGLE_SEL', 'wxLC_SORT_ASCENDING', 'wxLC_SORT_DESCENDING'] 
 481 class xxxTreeCtrl(xxxObject
): 
 482     allParams 
= ['pos', 'size', 'style'] 
 483     winStyles 
= ['wxTR_HAS_BUTTONS', 'wxTR_NO_LINES', 'wxTR_LINES_AT_ROOT', 
 484               'wxTR_EDIT_LABELS', 'wxTR_MULTIPLE'] 
 486 class xxxHtmlWindow(xxxObject
): 
 487     allParams 
= ['pos', 'size', 'style', 'borders', 'url', 'htmlcode'] 
 488     paramDict 
= {'borders': ParamInt, 'htmlcode':ParamMultilineText}
 
 489     winStyles 
= ['wxHW_SCROLLBAR_NEVER', 'wxHW_SCROLLBAR_AUTO'] 
 491 class xxxCalendarCtrl(xxxObject
): 
 492     allParams 
= ['pos', 'size', 'style'] 
 494 class xxxNotebook(xxxContainer
): 
 495     allParams 
= ['usenotebooksizer', 'pos', 'size', 'style'] 
 496     paramDict 
= {'usenotebooksizer': ParamBool}
 
 497     winStyles 
= ['wxNB_FIXEDWIDTH', 'wxNB_LEFT', 'wxNB_RIGHT', 'wxNB_BOTTOM'] 
 499 class xxxSplitterWindow(xxxContainer
): 
 500     allParams 
= ['orientation', 'sashpos', 'minsize', 'pos', 'size', 'style'] 
 501     paramDict 
= {'orientation': ParamOrientation, 'sashpos': ParamUnit, 'minsize': ParamUnit }
 
 502     winStyles 
= ['wxSP_3D', 'wxSP_3DSASH', 'wxSP_3DBORDER', 'wxSP_BORDER', 
 503                          'wxSP_NOBORDER', 'wxSP_PERMIT_UNSPLIT', 'wxSP_LIVE_UPDATE', 
 506 class xxxGenericDirCtrl(xxxObject
): 
 507     allParams 
= ['defaultfolder', 'filter', 'defaultfilter', 'pos', 'size', 'style'] 
 508     paramDict 
= {'defaultfilter': ParamInt}
 
 509     winStyles 
= ['wxDIRCTRL_DIR_ONLY', 'wxDIRCTRL_3D_INTERNAL', 'wxDIRCTRL_SELECT_FIRST', 
 510                  'wxDIRCTRL_SHOW_FILTERS', 'wxDIRCTRL_EDIT_LABELS'] 
 512 class xxxScrolledWindow(xxxContainer
): 
 513     allParams 
= ['pos', 'size', 'style'] 
 514     winStyles 
= ['wxHSCROLL', 'wxVSCROLL'] 
 516 ################################################################################ 
 519 class xxxButton(xxxObject
): 
 520     allParams 
= ['label', 'default', 'pos', 'size', 'style'] 
 521     paramDict 
= {'default': ParamBool}
 
 523     winStyles 
= ['wxBU_LEFT', 'wxBU_TOP', 'wxBU_RIGHT', 'wxBU_BOTTOM'] 
 525 class xxxBitmapButton(xxxObject
): 
 526     allParams 
= ['bitmap', 'selected', 'focus', 'disabled', 'default', 
 527                  'pos', 'size', 'style'] 
 528     required 
= ['bitmap'] 
 529     winStyles 
= ['wxBU_AUTODRAW', 'wxBU_LEFT', 'wxBU_TOP', 
 530                  'wxBU_RIGHT', 'wxBU_BOTTOM'] 
 532 class xxxRadioButton(xxxObject
): 
 533     allParams 
= ['label', 'value', 'pos', 'size', 'style'] 
 534     paramDict 
= {'value': ParamBool}
 
 536     winStyles 
= ['wxRB_GROUP'] 
 538 class xxxSpinButton(xxxObject
): 
 539     allParams 
= ['value', 'min', 'max', 'pos', 'size', 'style'] 
 540     paramDict 
= {'value': ParamInt}
 
 541     winStyles 
= ['wxSP_HORIZONTAL', 'wxSP_VERTICAL', 'wxSP_ARROW_KEYS', 'wxSP_WRAP'] 
 543 class xxxSpinCtrl(xxxObject
): 
 544     allParams 
= ['value', 'min', 'max', 'pos', 'size', 'style'] 
 545     paramDict 
= {'value': ParamInt}
 
 546     winStyles 
= ['wxSP_HORIZONTAL', 'wxSP_VERTICAL', 'wxSP_ARROW_KEYS', 'wxSP_WRAP'] 
 548 ################################################################################ 
 551 class xxxStaticBox(xxxObject
): 
 552     allParams 
= ['label', 'pos', 'size', 'style'] 
 555 class xxxRadioBox(xxxObject
): 
 556     allParams 
= ['label', 'content', 'selection', 'dimension', 'pos', 'size', 'style'] 
 557     paramDict 
= {'dimension': ParamInt}
 
 558     required 
= ['label', 'content'] 
 559     default 
= {'content': '[]'}
 
 560     winStyles 
= ['wxRA_SPECIFY_ROWS', 'wxRA_SPECIFY_COLS'] 
 562 class xxxCheckBox(xxxObject
): 
 563     allParams 
= ['label', 'checked', 'pos', 'size', 'style'] 
 564     paramDict 
= {'checked': ParamBool}
 
 567 class xxxComboBox(xxxObject
): 
 568     allParams 
= ['content', 'selection', 'value', 'pos', 'size', 'style'] 
 569     required 
= ['content'] 
 570     default 
= {'content': '[]'}
 
 571     winStyles 
= ['wxCB_SIMPLE', 'wxCB_SORT', 'wxCB_READONLY', 'wxCB_DROPDOWN'] 
 573 class xxxListBox(xxxObject
): 
 574     allParams 
= ['content', 'selection', 'pos', 'size', 'style'] 
 575     required 
= ['content'] 
 576     default 
= {'content': '[]'}
 
 577     winStyles 
= ['wxLB_SINGLE', 'wxLB_MULTIPLE', 'wxLB_EXTENDED', 'wxLB_HSCROLL', 
 578               'wxLB_ALWAYS_SB', 'wxLB_NEEDED_SB', 'wxLB_SORT'] 
 580 class xxxCheckList(xxxObject
): 
 581     allParams 
= ['content', 'pos', 'size', 'style'] 
 582     required 
= ['content'] 
 583     default 
= {'content': '[]'}
 
 584     winStyles 
= ['wxLC_LIST', 'wxLC_REPORT', 'wxLC_ICON', 'wxLC_SMALL_ICON', 
 585               'wxLC_ALIGN_TOP', 'wxLC_ALIGN_LEFT', 'wxLC_AUTOARRANGE', 
 586               'wxLC_USER_TEXT', 'wxLC_EDIT_LABELS', 'wxLC_NO_HEADER', 
 587               'wxLC_SINGLE_SEL', 'wxLC_SORT_ASCENDING', 'wxLC_SORT_DESCENDING'] 
 588     paramDict 
= {'content': ParamContentCheckList}
 
 590 ################################################################################ 
 593 class xxxSizer(xxxContainer
): 
 594     hasName 
= hasStyle 
= False 
 595     paramDict 
= {'orient': ParamOrient}
 
 598 class xxxBoxSizer(xxxSizer
): 
 599     allParams 
= ['orient'] 
 600     required 
= ['orient'] 
 601     default 
= {'orient': 'wxVERTICAL'}
 
 602     # Tree icon depends on orientation 
 604         if self
.params
['orient'].value() == 'wxHORIZONTAL': return self
.imageH
 
 605         else: return self
.imageV
 
 607 class xxxStaticBoxSizer(xxxBoxSizer
): 
 608     allParams 
= ['label', 'orient'] 
 609     required 
= ['label', 'orient'] 
 611 class xxxGridSizer(xxxSizer
): 
 612     allParams 
= ['cols', 'rows', 'vgap', 'hgap'] 
 614     default 
= {'cols': '2', 'rows': '2'}
 
 616 # For repeated parameters 
 618     def __init__(self
, node
): 
 620         self
.l
, self
.data 
= [], [] 
 621     def append(self
, param
): 
 623         self
.data
.append(param
.value()) 
 629         self
.l
, self
.data 
= [], [] 
 631 class xxxFlexGridSizer(xxxGridSizer
): 
 632     specials 
= ['growablecols', 'growablerows'] 
 633     allParams 
= ['cols', 'rows', 'vgap', 'hgap'] + specials
 
 634     paramDict 
= {'growablecols':ParamIntList, 'growablerows':ParamIntList}
 
 635     # Special processing for growable* parameters 
 636     # (they are represented by several nodes) 
 637     def special(self
, tag
, node
): 
 638         if not self
.params
.has_key(tag
): 
 639             # Create new multi-group 
 640             self
.params
[tag
] = xxxParamMulti(node
) 
 641         self
.params
[tag
].append(xxxParamInt(node
)) 
 642     def setSpecial(self
, param
, value
): 
 643         # Straightforward implementation: remove, add again 
 644         self
.params
[param
].remove() 
 645         del self
.params
[param
] 
 647             node 
= g
.tree
.dom
.createElement(param
) 
 648             text 
= g
.tree
.dom
.createTextNode(str(i
)) 
 649             node
.appendChild(text
) 
 650             self
.element
.appendChild(node
) 
 651             self
.special(param
, node
) 
 653 class xxxGridBagSizer(xxxSizer
): 
 654     specials 
= ['growablecols', 'growablerows'] 
 655     allParams 
= ['vgap', 'hgap'] + specials
 
 656     paramDict 
= {'growablecols':ParamIntList, 'growablerows':ParamIntList}
 
 657     # Special processing for growable* parameters 
 658     # (they are represented by several nodes) 
 659     def special(self
, tag
, node
): 
 660         if not self
.params
.has_key(tag
): 
 661             # Create new multi-group 
 662             self
.params
[tag
] = xxxParamMulti(node
) 
 663         self
.params
[tag
].append(xxxParamInt(node
)) 
 664     def setSpecial(self
, param
, value
): 
 665         # Straightforward implementation: remove, add again 
 666         self
.params
[param
].remove() 
 667         del self
.params
[param
] 
 669             node 
= g
.tree
.dom
.createElement(param
) 
 670             text 
= g
.tree
.dom
.createTextNode(str(i
)) 
 671             node
.appendChild(text
) 
 672             self
.element
.appendChild(node
) 
 673             self
.special(param
, node
) 
 675 # Container with only one child. 
 677 class xxxChildContainer(xxxObject
): 
 678     hasName 
= hasStyle 
= False 
 680     def __init__(self
, parent
, element
): 
 681         xxxObject
.__init
__(self
, parent
, element
) 
 682         # Must have one child with 'object' tag, but we don't check it 
 683         nodes 
= element
.childNodes
[:]   # create copy 
 685             if node
.nodeType 
== minidom
.Node
.ELEMENT_NODE
: 
 686                 if node
.tagName 
== 'object': 
 687                     # Create new xxx object for child node 
 688                     self
.child 
= MakeXXXFromDOM(self
, node
) 
 689                     self
.child
.parent 
= parent
 
 690                     # Copy hasChildren and isSizer attributes 
 691                     self
.hasChildren 
= self
.child
.hasChildren
 
 692                     self
.isSizer 
= self
.child
.isSizer
 
 695                 element
.removeChild(node
) 
 697         assert 0, 'no child found' 
 699 class xxxSizerItem(xxxChildContainer
): 
 700     allParams 
= ['option', 'flag', 'border', 'minsize', 'ratio'] 
 701     paramDict 
= {'option': ParamInt, 'minsize': ParamPosSize, 'ratio': ParamPosSize}
 
 702     #default = {'cellspan': '1,1'} 
 703     def __init__(self
, parent
, element
): 
 704         # For GridBag sizer items, extra parameters added 
 705         if isinstance(parent
, xxxGridBagSizer
): 
 706             self
.allParams 
= self
.allParams 
+ ['cellpos', 'cellspan'] 
 707         xxxChildContainer
.__init
__(self
, parent
, element
) 
 708         # Remove pos parameter - not needed for sizeritems 
 709         if 'pos' in self
.child
.allParams
: 
 710             self
.child
.allParams 
= self
.child
.allParams
[:] 
 711             self
.child
.allParams
.remove('pos') 
 713 class xxxNotebookPage(xxxChildContainer
): 
 714     allParams 
= ['label', 'selected'] 
 715     paramDict 
= {'selected': ParamBool}
 
 717     def __init__(self
, parent
, element
): 
 718         xxxChildContainer
.__init
__(self
, parent
, element
) 
 719         # pos and size dont matter for notebookpages 
 720         if 'pos' in self
.child
.allParams
: 
 721             self
.child
.allParams 
= self
.child
.allParams
[:] 
 722             self
.child
.allParams
.remove('pos') 
 723         if 'size' in self
.child
.allParams
: 
 724             self
.child
.allParams 
= self
.child
.allParams
[:] 
 725             self
.child
.allParams
.remove('size') 
 727 class xxxSpacer(xxxObject
): 
 728     hasName 
= hasStyle 
= False 
 729     allParams 
= ['size', 'option', 'flag', 'border'] 
 730     paramDict 
= {'option': ParamInt}
 
 731     default 
= {'size': '0,0'}
 
 733 class xxxMenuBar(xxxContainer
): 
 734     allParams 
= ['style'] 
 735     paramDict 
= {'style': ParamNonGenericStyle}    
# no generic styles 
 736     winStyles 
= ['wxMB_DOCKABLE'] 
 738 class xxxMenu(xxxContainer
): 
 739     allParams 
= ['label', 'help', 'style'] 
 740     default 
= {'label': ''}
 
 741     paramDict 
= {'style': ParamNonGenericStyle}    
# no generic styles 
 742     winStyles 
= ['wxMENU_TEAROFF'] 
 744 class xxxMenuItem(xxxObject
): 
 745     allParams 
= ['label', 'bitmap', 'accel', 'help', 
 746                  'checkable', 'radio', 'enabled', 'checked'] 
 747     default 
= {'label': ''}
 
 750 class xxxSeparator(xxxObject
): 
 751     hasName 
= hasStyle 
= False 
 753 ################################################################################ 
 756 class xxxUnknown(xxxObject
): 
 757     allParams 
= ['pos', 'size', 'style'] 
 758     paramDict 
= {'style': ParamNonGenericStyle}    
# no generic styles 
 760 ################################################################################ 
 764     'wxDialog': xxxDialog
, 
 767     'wxToolBar': xxxToolBar
, 
 769     'wxBitmap': xxxBitmap
, 
 772     'wxButton': xxxButton
, 
 773     'wxBitmapButton': xxxBitmapButton
, 
 774     'wxRadioButton': xxxRadioButton
, 
 775     'wxSpinButton': xxxSpinButton
, 
 777     'wxStaticBox': xxxStaticBox
, 
 778     'wxStaticBitmap': xxxStaticBitmap
, 
 779     'wxRadioBox': xxxRadioBox
, 
 780     'wxComboBox': xxxComboBox
, 
 781     'wxCheckBox': xxxCheckBox
, 
 782     'wxListBox': xxxListBox
, 
 784     'wxStaticText': xxxStaticText
, 
 785     'wxStaticLine': xxxStaticLine
, 
 786     'wxTextCtrl': xxxTextCtrl
, 
 787     'wxChoice': xxxChoice
, 
 788     'wxSlider': xxxSlider
, 
 790     'wxScrollBar': xxxScrollBar
, 
 791     'wxTreeCtrl': xxxTreeCtrl
, 
 792     'wxListCtrl': xxxListCtrl
, 
 793     'wxCheckListBox': xxxCheckList
, 
 794     'wxNotebook': xxxNotebook
, 
 795     'wxSplitterWindow': xxxSplitterWindow
, 
 796     'notebookpage': xxxNotebookPage
, 
 797     'wxHtmlWindow': xxxHtmlWindow
, 
 798     'wxCalendarCtrl': xxxCalendarCtrl
, 
 799     'wxGenericDirCtrl': xxxGenericDirCtrl
, 
 800     'wxSpinCtrl': xxxSpinCtrl
, 
 801     'wxScrolledWindow': xxxScrolledWindow
, 
 803     'wxBoxSizer': xxxBoxSizer
, 
 804     'wxStaticBoxSizer': xxxStaticBoxSizer
, 
 805     'wxGridSizer': xxxGridSizer
, 
 806     'wxFlexGridSizer': xxxFlexGridSizer
, 
 807     'wxGridBagSizer': xxxGridBagSizer
, 
 808     'sizeritem': xxxSizerItem
, 
 811     'wxMenuBar': xxxMenuBar
, 
 813     'wxMenuItem': xxxMenuItem
, 
 814     'separator': xxxSeparator
, 
 816     'unknown': xxxUnknown
, 
 819 # Create IDs for all parameters of all classes 
 820 paramIDs 
= {'fg': wxNewId(), 'bg': wxNewId(), 'exstyle': wxNewId(), 'font': wxNewId(), 
 821             'enabled': wxNewId(), 'focused': wxNewId(), 'hidden': wxNewId(), 
 822             'tooltip': wxNewId(), 'encoding': wxNewId(), 
 823             'cellpos': wxNewId(), 'cellspan': wxNewId() 
 825 for cl 
in xxxDict
.values(): 
 827         for param 
in cl
.allParams 
+ cl
.paramDict
.keys(): 
 828             if not paramIDs
.has_key(param
): 
 829                 paramIDs
[param
] = wxNewId() 
 831 ################################################################################ 
 834 # Test for object elements 
 836     return node
.nodeType 
== minidom
.Node
.ELEMENT_NODE 
and node
.tagName 
== 'object' 
 838 # Make XXX object from some DOM object, selecting correct class 
 839 def MakeXXXFromDOM(parent
, element
): 
 841         klass 
= xxxDict
[element
.getAttribute('class')] 
 843         # If we encounter a weird class, use unknown template 
 844         print 'WARNING: unsupported class:', element
.getAttribute('class') 
 846     return klass(parent
, element
) 
 848 # Make empty DOM element 
 849 def MakeEmptyDOM(className
): 
 850     elem 
= g
.tree
.dom
.createElement('object') 
 851     elem
.setAttribute('class', className
) 
 852     # Set required and default parameters 
 853     xxxClass 
= xxxDict
[className
] 
 854     defaultNotRequired 
= filter(lambda x
, l
=xxxClass
.required
: x 
not in l
, 
 855                                 xxxClass
.default
.keys()) 
 856     for param 
in xxxClass
.required 
+ defaultNotRequired
: 
 857         textElem 
= g
.tree
.dom
.createElement(param
) 
 859             textNode 
= g
.tree
.dom
.createTextNode(xxxClass
.default
[param
]) 
 861             textNode 
= g
.tree
.dom
.createTextNode('') 
 862         textElem
.appendChild(textNode
) 
 863         elem
.appendChild(textElem
) 
 866 # Make empty XXX object 
 867 def MakeEmptyXXX(parent
, className
): 
 868     # Make corresponding DOM object first 
 869     elem 
= MakeEmptyDOM(className
) 
 870     # If parent is a sizer, we should create sizeritem object, except for spacers 
 872         if parent
.isSizer 
and className 
!= 'spacer': 
 873             sizerItemElem 
= MakeEmptyDOM('sizeritem') 
 874             sizerItemElem
.appendChild(elem
) 
 876         elif isinstance(parent
, xxxNotebook
): 
 877             pageElem 
= MakeEmptyDOM('notebookpage') 
 878             pageElem
.appendChild(elem
) 
 880     # Now just make object 
 881     return MakeXXXFromDOM(parent
, elem
)