2 # Purpose:      XRC editor, Panel class and related 
   3 # Author:       Roman Rolinsky <rolinsky@mema.ucl.ac.be> 
   7 from xxx 
import *                       # xxx imports globals and params 
   9 from wxPython
.html 
import wxHtmlWindow
 
  11 # Properties panel containing notebook 
  12 class Panel(wxNotebook
): 
  13     def __init__(self
, parent
, id = -1): 
  14         if wxPlatform 
!= '__WXMAC__':   # some problems with this style on macs 
  15             wxNotebook
.__init
__(self
, parent
, id, style
=wxNB_BOTTOM
) 
  17             wxNotebook
.__init
__(self
, parent
, id) 
  19         g
.panel 
= panel 
= self
 
  22         # Set common button size for parameter buttons 
  23         bTmp 
= wxButton(self
, -1, '') 
  25         params
.buttonSize 
= (self
.DLG_SZE(buttonSize
)[0], bTmp
.GetSize()[1]) 
  29         # List of child windows 
  31         # Create scrolled windows for pages 
  32         self
.page1 
= wxScrolledWindow(self
, -1) 
  34         sizer
.Add(wxBoxSizer())         # dummy sizer 
  35         self
.page1
.SetAutoLayout(True) 
  36         self
.page1
.SetSizer(sizer
) 
  37         self
.AddPage(self
.page1
, 'Properties') 
  39         self
.page2 
= wxScrolledWindow(self
, -1) 
  41         sizer
.Add(wxBoxSizer())         # dummy sizer 
  42         self
.page2
.SetAutoLayout(True) 
  43         self
.page2
.SetSizer(sizer
) 
  44         # Cache for already used panels 
  45         self
.pageCache 
= {}             # cached property panels 
  46         self
.stylePageCache 
= {}        # cached style panels 
  47         # Dummy parent window for cache pages 
  48         self
.cacheParent 
= wxFrame(None, -1, 'i am invisible') 
  49     # Delete child windows and recreate page sizer 
  50     def ResetPage(self
, page
): 
  51         topSizer 
= page
.GetSizer() 
  52         sizer 
= topSizer
.GetChildren()[0].GetSizer() 
  53         for w 
in page
.GetChildren(): 
  55             if isinstance(w
, ParamPage
): 
  56                 # With SetParent, we wouldn't need this 
  57                 w
.Reparent(self
.cacheParent
) 
  60         topSizer
.RemoveSizer(sizer
) 
  62         sizer 
= wxBoxSizer(wxVERTICAL
) 
  63         # Special case - resize html window 
  65             topSizer
.Add(sizer
, 1, wxEXPAND
) 
  67             topSizer
.Add(sizer
, 0, wxALL
, 5) 
  69     def SetData(self
, xxx
): 
  72         # Set cached or new page 
  73         # Remove current objects and sizer 
  74         sizer 
= self
.ResetPage(self
.page1
) 
  75         if not xxx 
or (not xxx
.allParams 
and not xxx
.hasName
): 
  77                 sizer
.Add(wxStaticText(self
.page1
, -1, 'This item has no properties.')) 
  78             else:                       # nothing selected 
  79                 # If first time, show some help 
  81                     html 
= wxHtmlWindow(self
.page1
, -1, wxDefaultPosition
, 
  82                                         wxDefaultSize
, wxSUNKEN_BORDER
) 
  83                     html
.SetPage(g
.helpText
) 
  84                     sizer
.Add(html
, 1, wxEXPAND
) 
  87                     sizer
.Add(wxStaticText(self
.page1
, -1, 'Select a tree item.')) 
  89             g
.currentXXX 
= xxx
.treeObject() 
  90             # Normal or SizerItem page 
  91             isGBSizerItem 
= isinstance(xxx
.parent
, xxxGridBagSizer
) 
  92             cacheID 
= (xxx
.__class
__, isGBSizerItem
)             
  94                 page 
= self
.pageCache
[cacheID
] 
  95                 page
.box
.SetLabel(xxx
.panelName()) 
  96                 page
.Reparent(self
.page1
) 
  98                 page 
= PropPage(self
.page1
, xxx
.panelName(), xxx
) 
  99                 self
.pageCache
[cacheID
] = page
 
 101             self
.pages
.append(page
) 
 102             sizer
.Add(page
, 1, wxEXPAND
) 
 104                 # Special label for child objects - they may have different GUI 
 105                 cacheID 
= (xxx
.child
.__class
__, xxx
.__class
__) 
 107                     page 
= self
.pageCache
[cacheID
] 
 108                     page
.box
.SetLabel(xxx
.child
.panelName()) 
 109                     page
.Reparent(self
.page1
) 
 111                     page 
= PropPage(self
.page1
, xxx
.child
.panelName(), xxx
.child
) 
 112                     self
.pageCache
[cacheID
] = page
 
 113                 page
.SetValues(xxx
.child
) 
 114                 self
.pages
.append(page
) 
 115                 sizer
.Add(page
, 0, wxEXPAND | wxTOP
, 5) 
 117         size 
= self
.page1
.GetSizer().GetMinSize() 
 118         self
.page1
.SetScrollbars(1, 1, size
.width
, size
.height
, 0, 0, True) 
 121         # Create if does not exist 
 122         if xxx 
and xxx
.treeObject().hasStyle
: 
 123             xxx 
= xxx
.treeObject() 
 124             # Simplest case: set data if class is the same 
 125             sizer 
= self
.ResetPage(self
.page2
) 
 127                 page 
= self
.stylePageCache
[xxx
.__class
__] 
 128                 page
.Reparent(self
.page2
) 
 130                 page 
= StylePage(self
.page2
, xxx
.className 
+ ' style', xxx
) 
 131                 self
.stylePageCache
[xxx
.__class
__] = page
 
 133             self
.pages
.append(page
) 
 134             sizer
.Add(page
, 0, wxEXPAND
) 
 135             # Add page if not exists 
 136             if not self
.GetPageCount() == 2: 
 137                 self
.AddPage(self
.page2
, 'Style') 
 139             size 
= self
.page2
.GetSizer().GetMinSize() 
 140             self
.page2
.SetScrollbars(1, 1, size
.width
, size
.height
, 0, 0, True) 
 142             # Remove page if exists 
 143             if self
.GetPageCount() == 2: 
 147         self
.modified 
= False 
 150         self
.modified 
= False 
 151     # If some parameter has changed 
 152     def IsModified(self
): 
 154     def SetModified(self
, value
): 
 155         # Register undo object when modifying first time 
 156         if not self
.modified 
and value
: 
 157            g
.undoMan
.RegisterUndo(UndoEdit()) 
 158         self
.modified 
= value
 
 160         for p 
in self
.pages
: p
.Apply() 
 162 ################################################################################ 
 164 # General class for notebook pages 
 165 class ParamPage(wxPanel
): 
 166     def __init__(self
, parent
, xxx
): 
 167         wxPanel
.__init
__(self
, parent
, -1) 
 168         self
.SetBackgroundColour(parent
.GetBackgroundColour()) 
 169         self
.SetForegroundColour(parent
.GetForegroundColour()) 
 171         # Register event handlers 
 172         for id in paramIDs
.values(): 
 173             EVT_CHECKBOX(self
, id, self
.OnCheckParams
) 
 175         self
.controls 
= {}              # save python objects 
 176         self
.controlName 
= None 
 178     def OnCheckParams(self
, evt
): 
 180         param 
= evt
.GetEventObject().GetName() 
 181         w 
= self
.controls
[param
] 
 183         objElem 
= xxx
.element
 
 185             # Ad  new text node in order of allParams 
 186             w
.SetValue('')              # set empty (default) value 
 187             w
.SetModified()             # mark as changed 
 188             elem 
= g
.tree
.dom
.createElement(param
) 
 189             # Some classes are special 
 191                 xxx
.params
[param
] = xxxParamFont(xxx
.element
, elem
) 
 192             elif param 
in xxxObject
.bitmapTags
: 
 193                 xxx
.params
[param
] = xxxParamBitmap(elem
) 
 195                 xxx
.params
[param
] = xxxParam(elem
) 
 196             # Find place to put new element: first present element after param 
 198             paramStyles 
= xxx
.allParams 
+ xxx
.styles
 
 199             for p 
in paramStyles
[paramStyles
.index(param
) + 1:]: 
 200                 # Content params don't have same type 
 201                 if xxx
.params
.has_key(p
) and p 
!= 'content': 
 205                 nextTextElem 
= xxx
.params
[p
].node
 
 206                 objElem
.insertBefore(elem
, nextTextElem
) 
 208                 objElem
.appendChild(elem
) 
 211             xxx
.params
[param
].remove() 
 212             del xxx
.params
[param
] 
 214             w
.modified 
= False          # mark as not changed 
 216         # Set modified flag (provokes undo storing is necessary) 
 217         panel
.SetModified(True) 
 221             name 
= self
.controlName
.GetValue() 
 224                 xxx
.element
.setAttribute('name', name
) 
 225         for param
, w 
in self
.controls
.items(): 
 227                 paramObj 
= xxx
.params
[param
] 
 229                 if param 
in xxx
.specials
: 
 230                     xxx
.setSpecial(param
, value
) 
 232                     paramObj
.update(value
) 
 235         self
.origChecks 
= map(lambda i
: (i
[0], i
[1].GetValue()), self
.checks
.items()) 
 236         self
.origControls 
= map(lambda i
: (i
[0], i
[1].GetValue(), i
[1].IsEnabled()), 
 237                             self
.controls
.items()) 
 239             self
.origName 
= self
.controlName
.GetValue() 
 240     # Return original values 
 243             return (self
.origChecks
, self
.origControls
, self
.origName
) 
 245             return (self
.origChecks
, self
.origControls
) 
 246     # Set values from undo data 
 247     def SetState(self
, state
): 
 249             self
.checks
[k
].SetValue(v
) 
 250         for k
,v
,e 
in state
[1]: 
 251             self
.controls
[k
].SetValue(v
) 
 252             self
.controls
[k
].Enable(e
) 
 253             if e
: self
.controls
[k
].modified 
= True 
 255             self
.controlName
.SetValue(state
[2]) 
 257 ################################################################################ 
 259 # Panel for displaying properties 
 260 class PropPage(ParamPage
): 
 261     def __init__(self
, parent
, label
, xxx
): 
 262         ParamPage
.__init
__(self
, parent
, xxx
) 
 263         self
.box 
= wxStaticBox(self
, -1, label
) 
 264         self
.box
.SetFont(g
.labelFont()) 
 265         topSizer 
= wxStaticBoxSizer(self
.box
, wxVERTICAL
) 
 266         sizer 
= wxFlexGridSizer(len(xxx
.allParams
), 2, 1, 1) 
 267         sizer
.AddGrowableCol(1) 
 269             label 
= wxStaticText(self
, -1, 'XML ID:', size
=(100,-1)) 
 270             control 
= ParamText(self
, 'XML_name', 200) 
 271             sizer
.AddMany([ (label
, 0, wxALIGN_CENTER_VERTICAL
), 
 272                             (control
, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM | wxGROW
, 5) ]) 
 273             self
.controlName 
= control
 
 274         for param 
in xxx
.allParams
: 
 275             present 
= xxx
.params
.has_key(param
) 
 276             if param 
in xxx
.required
: 
 277                 label 
= wxStaticText(self
, paramIDs
[param
], param 
+ ':', 
 278                                      size 
= (100,-1), name 
= param
) 
 280                 # Notebook has one very loooooong parameter 
 281                 if param 
== 'usenotebooksizer': sParam 
= 'usesizer:' 
 282                 else: sParam 
= param 
+ ':' 
 283                 label 
= wxCheckBox(self
, paramIDs
[param
], sParam
, 
 284                                    size 
= (100,-1), name 
= param
) 
 285                 self
.checks
[param
] = label
 
 287                 typeClass 
= xxx
.paramDict
[param
] 
 291                     typeClass 
= paramDict
[param
] 
 294                     typeClass 
= ParamText
 
 295             control 
= typeClass(self
, param
) 
 296             control
.Enable(present
) 
 297             sizer
.AddMany([ (label
, 0, wxALIGN_CENTER_VERTICAL
), 
 298                             (control
, 0, wxALIGN_CENTER_VERTICAL | wxGROW
) ]) 
 299             self
.controls
[param
] = control
 
 300         topSizer
.Add(sizer
, 1, wxALL | wxEXPAND
, 3) 
 301         self
.SetAutoLayout(True) 
 302         self
.SetSizer(topSizer
) 
 304     def SetValues(self
, xxx
): 
 307         self
.origControls 
= [] 
 308         # Set values, checkboxes to False, disable defaults 
 310             self
.controlName
.SetValue(xxx
.name
) 
 311             self
.origName 
= xxx
.name
 
 312         for param 
in xxx
.allParams
: 
 313             w 
= self
.controls
[param
] 
 316                 value 
= xxx
.params
[param
].value() 
 319                 if not param 
in xxx
.required
: 
 320                     self
.checks
[param
].SetValue(True) 
 321                     self
.origChecks
.append((param
, True)) 
 322                 self
.origControls
.append((param
, value
, True)) 
 324                 self
.checks
[param
].SetValue(False) 
 327                 self
.origChecks
.append((param
, False)) 
 328                 self
.origControls
.append((param
, '', False)) 
 330 ################################################################################ 
 332 # Style notebook page 
 333 class StylePage(ParamPage
): 
 334     def __init__(self
, parent
, label
, xxx
): 
 335         ParamPage
.__init
__(self
, parent
, xxx
) 
 336         box 
= wxStaticBox(self
, -1, label
) 
 337         box
.SetFont(g
.labelFont()) 
 338         topSizer 
= wxStaticBoxSizer(box
, wxVERTICAL
) 
 339         sizer 
= wxFlexGridSizer(len(xxx
.styles
), 2, 1, 1) 
 340         sizer
.AddGrowableCol(1) 
 341         for param 
in xxx
.styles
: 
 342             present 
= xxx
.params
.has_key(param
) 
 343             check 
= wxCheckBox(self
, paramIDs
[param
], 
 344                                param 
+ ':', size 
= (100,-1), name 
= param
) 
 345             check
.SetValue(present
) 
 346             control 
= paramDict
[param
](self
, name 
= param
) 
 347             control
.Enable(present
) 
 348             sizer
.AddMany([ (check
, 0, wxALIGN_CENTER_VERTICAL
), 
 349                             (control
, 0, wxALIGN_CENTER_VERTICAL | wxGROW
) ]) 
 350             self
.checks
[param
] = check
 
 351             self
.controls
[param
] = control
 
 352         topSizer
.Add(sizer
, 1, wxALL | wxEXPAND
, 3) 
 353         self
.SetAutoLayout(True) 
 354         self
.SetSizer(topSizer
) 
 356     # Set data for a cahced page 
 357     def SetValues(self
, xxx
): 
 360         self
.origControls 
= [] 
 361         for param 
in xxx
.styles
: 
 362             present 
= xxx
.params
.has_key(param
) 
 363             check 
= self
.checks
[param
] 
 364             check
.SetValue(present
) 
 365             w 
= self
.controls
[param
] 
 368                 value 
= xxx
.params
[param
].value() 
 373             self
.origChecks
.append((param
, present
)) 
 374             self
.origControls
.append((param
, value
, present
))