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) 
  42         sizer
.Add(wxBoxSizer())         # dummy sizer 
  43         self
.page2
.SetAutoLayout(True) 
  44         self
.page2
.SetSizer(sizer
) 
  45         # Cache for already used panels 
  46         self
.pageCache 
= {}             # cached property panels 
  47         self
.stylePageCache 
= {}        # cached style panels 
  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
): 
  60         topSizer
.Remove(sizer
) 
  62         sizer 
= wxBoxSizer(wxVERTICAL
) 
  63         # Special case - resize html window 
  65             topSizer
.Add(sizer
, 1, wxEXPAND
) 
  67             topSizer
.Add(sizer
, 0, wxALL
, 5) 
  70     def SetData(self
, xxx
): 
  73         # Remove current objects and sizer 
  74         sizer 
= self
.ResetPage(self
.page1
) 
  75         if not xxx 
or (not xxx
.allParams 
and not xxx
.hasName 
and not xxx
.hasChild
): 
  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()) 
  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()) 
 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
__] 
 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             if 'wxGTK' in wx
.PlatformInfo
: 
 140                 self
.page2
.Show(True) 
 141             size 
= self
.page2
.GetSizer().GetMinSize() 
 142             self
.page2
.SetScrollbars(1, 1, size
.width
, size
.height
, 0, 0, True) 
 144             # Remove page if exists 
 145             if self
.GetPageCount() == 2: 
 149         self
.modified 
= False 
 153         self
.modified 
= False 
 155     # If some parameter has changed 
 156     def IsModified(self
): 
 159     def SetModified(self
, value
): 
 160         # Register undo object when modifying first time 
 161         if not self
.modified 
and value
: 
 162            g
.undoMan
.RegisterUndo(UndoEdit()) 
 163         self
.modified 
= value
 
 166         for p 
in self
.pages
: p
.Apply() 
 168 ################################################################################ 
 170 # General class for notebook pages 
 171 class ParamPage(wxPanel
): 
 172     def __init__(self
, parent
, xxx
): 
 173         wxPanel
.__init
__(self
, parent
, -1) 
 175         # Register event handlers 
 176         for id in paramIDs
.values(): 
 177             EVT_CHECKBOX(self
, id, self
.OnCheckParams
) 
 179         self
.controls 
= {}              # save python objects 
 180         self
.controlName 
= None 
 182     def OnCheckParams(self
, evt
): 
 184         param 
= evt
.GetEventObject().GetName() 
 185         w 
= self
.controls
[param
] 
 187         objElem 
= xxx
.element
 
 189             # Ad  new text node in order of allParams 
 190             w
.SetValue('')              # set empty (default) value 
 191             w
.SetModified()             # mark as changed 
 192             elem 
= g
.tree
.dom
.createElement(param
) 
 193             # Some classes are special 
 195                 xxx
.params
[param
] = xxxParamFont(xxx
.element
, elem
) 
 196             elif param 
in xxxObject
.bitmapTags
: 
 197                 xxx
.params
[param
] = xxxParamBitmap(elem
) 
 199                 xxx
.params
[param
] = xxxParam(elem
) 
 200             # Find place to put new element: first present element after param 
 203                 paramStyles 
= xxx
.allParams 
+ xxx
.styles
 
 205                 paramStyles 
= xxx
.allParams 
 
 206             for p 
in paramStyles
[paramStyles
.index(param
) + 1:]: 
 207                 # Content params don't have same type 
 208                 if xxx
.params
.has_key(p
) and p 
!= 'content': 
 212                 nextTextElem 
= xxx
.params
[p
].node
 
 213                 objElem
.insertBefore(elem
, nextTextElem
) 
 215                 objElem
.appendChild(elem
) 
 218             xxx
.params
[param
].remove() 
 219             del xxx
.params
[param
] 
 221             w
.modified 
= False          # mark as not changed 
 223         # Set modified flag (provokes undo storing is necessary) 
 224         panel
.SetModified(True) 
 228             name 
= self
.controlName
.GetValue() 
 231                 xxx
.element
.setAttribute('name', name
) 
 232         for param
, w 
in self
.controls
.items(): 
 234                 paramObj 
= xxx
.params
[param
] 
 236                 if param 
in xxx
.specials
: 
 237                     xxx
.setSpecial(param
, value
) 
 239                     paramObj
.update(value
) 
 242         self
.origChecks 
= map(lambda i
: (i
[0], i
[1].GetValue()), self
.checks
.items()) 
 243         self
.origControls 
= map(lambda i
: (i
[0], i
[1].GetValue(), i
[1].IsEnabled()), 
 244                             self
.controls
.items()) 
 246             self
.origName 
= self
.controlName
.GetValue() 
 247     # Return original values 
 250             return (self
.origChecks
, self
.origControls
, self
.origName
) 
 252             return (self
.origChecks
, self
.origControls
) 
 253     # Set values from undo data 
 254     def SetState(self
, state
): 
 256             self
.checks
[k
].SetValue(v
) 
 257         for k
,v
,e 
in state
[1]: 
 258             self
.controls
[k
].SetValue(v
) 
 259             self
.controls
[k
].Enable(e
) 
 260             if e
: self
.controls
[k
].modified 
= True 
 262             self
.controlName
.SetValue(state
[2]) 
 264 ################################################################################ 
 268 # Panel for displaying properties 
 269 class PropPage(ParamPage
): 
 270     def __init__(self
, parent
, label
, xxx
): 
 271         ParamPage
.__init
__(self
, parent
, xxx
) 
 272         self
.box 
= wxStaticBox(self
, -1, label
) 
 273         self
.box
.SetFont(g
.labelFont()) 
 274         topSizer 
= wxStaticBoxSizer(self
.box
, wxVERTICAL
) 
 275         sizer 
= wxFlexGridSizer(len(xxx
.allParams
), 2, 0, 1) 
 276         sizer
.AddGrowableCol(1) 
 278             label 
= wxStaticText(self
, -1, 'XML ID:', size
=(LABEL_WIDTH
,-1)) 
 279             control 
= ParamText(self
, 'XML_name', 200) 
 280             sizer
.AddMany([ (label
, 0, wxALIGN_CENTER_VERTICAL
), 
 281                             (control
, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM | wxGROW
, 10) ]) 
 282             self
.controlName 
= control
 
 283         for param 
in xxx
.allParams
: 
 284             present 
= xxx
.params
.has_key(param
) 
 285             if param 
in xxx
.required
: 
 286                 label 
= wxStaticText(self
, paramIDs
[param
], param 
+ ':', 
 287                                      size 
= (LABEL_WIDTH
,-1), name 
= param
) 
 289                 # Notebook has one very loooooong parameter 
 290                 if param 
== 'usenotebooksizer': sParam 
= 'usesizer:' 
 291                 else: sParam 
= param 
+ ':' 
 292                 label 
= wxCheckBox(self
, paramIDs
[param
], sParam
, 
 293                                    size 
= (LABEL_WIDTH
,-1), name 
= param
) 
 294                 self
.checks
[param
] = label
 
 296                 typeClass 
= xxx
.paramDict
[param
] 
 300                     typeClass 
= paramDict
[param
] 
 303                     typeClass 
= ParamText
 
 304             control 
= typeClass(self
, param
) 
 305             control
.Enable(present
) 
 306             sizer
.AddMany([ (label
, 0, wxALIGN_CENTER_VERTICAL
), 
 307                             (control
, 0, wxALIGN_CENTER_VERTICAL | wxGROW
) ]) 
 308             self
.controls
[param
] = control
 
 309         topSizer
.Add(sizer
, 1, wxALL | wxEXPAND
, 3) 
 310         self
.SetAutoLayout(True) 
 311         self
.SetSizer(topSizer
) 
 313     def SetValues(self
, xxx
): 
 316         self
.origControls 
= [] 
 317         # Set values, checkboxes to False, disable defaults 
 319             self
.controlName
.SetValue(xxx
.name
) 
 320             self
.origName 
= xxx
.name
 
 321         for param 
in xxx
.allParams
: 
 322             w 
= self
.controls
[param
] 
 325                 value 
= xxx
.params
[param
].value() 
 328                 if not param 
in xxx
.required
: 
 329                     self
.checks
[param
].SetValue(True) 
 330                     self
.origChecks
.append((param
, True)) 
 331                 self
.origControls
.append((param
, value
, True)) 
 333                 self
.checks
[param
].SetValue(False) 
 336                 self
.origChecks
.append((param
, False)) 
 337                 self
.origControls
.append((param
, '', False)) 
 339 ################################################################################ 
 341 # Style notebook page 
 342 class StylePage(ParamPage
): 
 343     def __init__(self
, parent
, label
, xxx
): 
 344         ParamPage
.__init
__(self
, parent
, xxx
) 
 345         box 
= wxStaticBox(self
, -1, label
) 
 346         box
.SetFont(g
.labelFont()) 
 347         topSizer 
= wxStaticBoxSizer(box
, wxVERTICAL
) 
 348         sizer 
= wxFlexGridSizer(len(xxx
.styles
), 2, 0, 1) 
 349         sizer
.AddGrowableCol(1) 
 350         for param 
in xxx
.styles
: 
 351             present 
= xxx
.params
.has_key(param
) 
 352             check 
= wxCheckBox(self
, paramIDs
[param
], 
 353                                param 
+ ':', size 
= (LABEL_WIDTH
,-1), name 
= param
) 
 354             check
.SetValue(present
) 
 355             control 
= paramDict
[param
](self
, name 
= param
) 
 356             control
.Enable(present
) 
 357             sizer
.AddMany([ (check
, 0, wxALIGN_CENTER_VERTICAL
), 
 358                             (control
, 0, wxALIGN_CENTER_VERTICAL | wxGROW
) ]) 
 359             self
.checks
[param
] = check
 
 360             self
.controls
[param
] = control
 
 361         topSizer
.Add(sizer
, 1, wxALL | wxEXPAND
, 3) 
 362         self
.SetAutoLayout(True) 
 363         self
.SetSizer(topSizer
) 
 365     # Set data for a cahced page 
 366     def SetValues(self
, xxx
): 
 369         self
.origControls 
= [] 
 370         for param 
in xxx
.styles
: 
 371             present 
= xxx
.params
.has_key(param
) 
 372             check 
= self
.checks
[param
] 
 373             check
.SetValue(present
) 
 374             w 
= self
.controls
[param
] 
 377                 value 
= xxx
.params
[param
].value() 
 382             self
.origChecks
.append((param
, present
)) 
 383             self
.origControls
.append((param
, value
, present
))