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 wx
.html 
import HtmlWindow
 
  11 # Properties panel containing notebook 
  12 class Panel(wx
.Notebook
): 
  13     def __init__(self
, parent
, id = -1): 
  14         if wx
.Platform 
!= '__WXMAC__':   # some problems with this style on macs 
  15             wx
.Notebook
.__init
__(self
, parent
, id, style
=wx
.NB_BOTTOM
) 
  17             wx
.Notebook
.__init
__(self
, parent
, id) 
  19         g
.panel 
= panel 
= self
 
  24         cTmp 
= wx
.Button(self
, -1, '') 
  25         params
.buttonSize 
= (self
.DLG_SZE(buttonSizeD
)[0], cTmp
.GetSize()[1])         
  27         cTmp 
= wx
.TextCtrl(self
, -1, '') 
  28         params
.textSize 
= cTmp
.GetSize() 
  30         cTmp 
= wx
.CheckBox(self
, -1, 'growablerows ') # this is the longest 
  31         ParamPage
.labelSize 
= cTmp
.GetSize() 
  35         # List of child windows 
  37         # Create scrolled windows for pages 
  38         self
.page1 
= wx
.ScrolledWindow(self
, -1) 
  40         sizer
.Add(wx
.BoxSizer())         # dummy sizer 
  41         self
.page1
.SetAutoLayout(True) 
  42         self
.page1
.SetSizer(sizer
) 
  43         self
.AddPage(self
.page1
, 'Properties') 
  45         self
.page2 
= wx
.ScrolledWindow(self
, -1) 
  48         sizer
.Add(wx
.BoxSizer())         # dummy sizer 
  49         self
.page2
.SetAutoLayout(True) 
  50         self
.page2
.SetSizer(sizer
) 
  51         # Cache for already used panels 
  52         self
.pageCache 
= {}             # cached property panels 
  53         self
.stylePageCache 
= {}        # cached style panels 
  55     # Delete child windows and recreate page sizer 
  56     def ResetPage(self
, page
): 
  57         topSizer 
= page
.GetSizer() 
  58         sizer 
= topSizer
.GetChildren()[0].GetSizer() 
  59         for w 
in page
.GetChildren(): 
  61             if isinstance(w
, ParamPage
): 
  66         topSizer
.Remove(sizer
) 
  68         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
  69         # Special case - resize html window 
  71             topSizer
.Add(sizer
, 1, wx
.EXPAND
) 
  73             topSizer
.Add(sizer
, 1, wx
.ALL
, 5) 
  76     def SetData(self
, xxx
): 
  79         # Remove current objects and sizer 
  80         sizer 
= self
.ResetPage(self
.page1
) 
  81         if not xxx 
or (not xxx
.allParams 
and not xxx
.hasName 
and not xxx
.hasChild
): 
  83                 sizer
.Add(wx
.StaticText(self
.page1
, -1, 'This item has no properties.')) 
  84             else:                       # nothing selected 
  85                 # If first time, show some help 
  87                     html 
= HtmlWindow(self
.page1
, -1, wx
.DefaultPosition
, 
  88                                         wx
.DefaultSize
, wx
.SUNKEN_BORDER
) 
  89                     html
.SetPage(g
.helpText
) 
  90                     sizer
.Add(html
, 1, wx
.EXPAND
) 
  93                     sizer
.Add(wx
.StaticText(self
.page1
, -1, 'Select a tree item.')) 
  95             g
.currentXXX 
= xxx
.treeObject() 
  96             # Normal or SizerItem page 
  97             isGBSizerItem 
= isinstance(xxx
.parent
, xxxGridBagSizer
) 
  98             cacheID 
= (xxx
.panelName(), isGBSizerItem
) 
 100                 page 
= self
.pageCache
[cacheID
] 
 101                 page
.box
.SetLabel(xxx
.panelName()) 
 104                 page 
= PropPage(self
.page1
, xxx
.panelName(), xxx
) 
 105                 self
.pageCache
[cacheID
] = page
 
 107             self
.pages
.append(page
) 
 108             sizer
.Add(page
, 1, wx
.EXPAND
) 
 110                 # Special label for child objects - they may have different GUI 
 111                 cacheID 
= (xxx
.child
.panelName(), xxx
.__class
__) 
 113                     page 
= self
.pageCache
[cacheID
] 
 114                     page
.box
.SetLabel(xxx
.child
.panelName()) 
 117                     page 
= PropPage(self
.page1
, xxx
.child
.panelName(), xxx
.child
) 
 118                     self
.pageCache
[cacheID
] = page
 
 119                 page
.SetValues(xxx
.child
) 
 120                 self
.pages
.append(page
) 
 121                 sizer
.Add(page
, 0, wx
.EXPAND | wx
.TOP
, 5) 
 123         size 
= self
.page1
.GetSizer().GetMinSize() 
 124         self
.page1
.SetScrollbars(1, 1, size
.width
, size
.height
, 0, 0, True) 
 127         # Create if does not exist 
 128         if xxx 
and xxx
.treeObject().hasStyle
: 
 129             xxx 
= xxx
.treeObject() 
 130             # Simplest case: set data if class is the same 
 131             sizer 
= self
.ResetPage(self
.page2
) 
 133                 page 
= self
.stylePageCache
[xxx
.__class
__] 
 136                 page 
= StylePage(self
.page2
, xxx
.className 
+ ' style', xxx
) 
 137                 self
.stylePageCache
[xxx
.__class
__] = page
 
 139             self
.pages
.append(page
) 
 140             sizer
.Add(page
, 0, wx
.EXPAND
) 
 141             # Add page if not exists 
 142             if not self
.GetPageCount() == 2: 
 143                 self
.AddPage(self
.page2
, 'Style') 
 145             if 'wxGTK' in wx
.PlatformInfo
: 
 146                 self
.page2
.Show(True) 
 147             size 
= self
.page2
.GetSizer().GetMinSize() 
 148             self
.page2
.SetScrollbars(1, 1, size
.width
, size
.height
, 0, 0, True) 
 150             # Remove page if exists 
 151             if self
.GetPageCount() == 2: 
 155         self
.modified 
= False 
 159         self
.modified 
= False 
 161     # If some parameter has changed 
 162     def IsModified(self
): 
 165     def SetModified(self
, value
): 
 166         # Register undo object when modifying first time 
 167         if not self
.modified 
and value
: 
 168            g
.undoMan
.RegisterUndo(UndoEdit()) 
 169            g
.frame
.SetModified() 
 170         self
.modified 
= value
 
 173         for p 
in self
.pages
: p
.Apply() 
 175 ################################################################################ 
 177 # General class for notebook pages 
 178 class ParamPage(wx
.Panel
): 
 180     def __init__(self
, parent
, xxx
): 
 181         wx
.Panel
.__init
__(self
, parent
, -1) 
 183         # Register event handlers 
 184         for id in paramIDs
.values(): 
 185             wx
.EVT_CHECKBOX(self
, id, self
.OnCheckParams
) 
 187         self
.controls 
= {}              # save python objects 
 188         self
.controlName 
= None 
 190     def OnCheckParams(self
, evt
): 
 192         param 
= evt
.GetEventObject().GetName() 
 193         w 
= self
.controls
[param
] 
 197             # Ad  new text node in order of allParams 
 198             w
.SetValue('')              # set empty (default) value 
 199             w
.SetModified()             # mark as changed 
 200             elem 
= g
.tree
.dom
.createElement(param
) 
 201             # Some classes are special 
 203                 xxx
.params
[param
] = xxxParamFont(xxx
.node
, elem
) 
 204             elif param 
in xxxObject
.bitmapTags
: 
 205                 xxx
.params
[param
] = xxxParamBitmap(elem
) 
 207                 xxx
.params
[param
] = xxxParam(elem
) 
 208             # Find place to put new element: first present element after param 
 211                 paramStyles 
= xxx
.allParams 
+ xxx
.styles
 
 213                 paramStyles 
= xxx
.allParams 
 
 214             for p 
in paramStyles
[paramStyles
.index(param
) + 1:]: 
 215                 # Content params don't have same type 
 216                 if xxx
.params
.has_key(p
) and p 
!= 'content': 
 220                 nextTextElem 
= xxx
.params
[p
].node
 
 221                 objElem
.insertBefore(elem
, nextTextElem
) 
 223                 objElem
.appendChild(elem
) 
 226             xxx
.params
[param
].remove() 
 227             del xxx
.params
[param
] 
 229             w
.SetModified(False)        # mark as not changed 
 231         # Set modified flag (provokes undo storing is necessary) 
 232         panel
.SetModified(True) 
 236             name 
= self
.controlName
.GetValue() 
 239                 xxx
.node
.setAttribute('name', name
) 
 240         for param
, w 
in self
.controls
.items(): 
 242                 paramObj 
= xxx
.params
[param
] 
 244                 if param 
in xxx
.specials
: 
 245                     xxx
.setSpecial(param
, value
) 
 247                     paramObj
.update(value
) 
 251         self
.origChecks 
= map(lambda i
: (i
[0], i
[1].GetValue()), self
.checks
.items()) 
 252         self
.origControls 
= map(lambda i
: (i
[0], i
[1].GetValue(), i
[1].enabled
), 
 253                             self
.controls
.items()) 
 255             self
.origName 
= self
.controlName
.GetValue() 
 256     # Return original values 
 259             return (self
.origChecks
, self
.origControls
, self
.origName
) 
 261             return (self
.origChecks
, self
.origControls
) 
 262     # Set values from undo data 
 263     def SetState(self
, state
): 
 265             self
.checks
[k
].SetValue(v
) 
 266         for k
,v
,e 
in state
[1]: 
 267             self
.controls
[k
].SetValue(v
) 
 268             self
.controls
[k
].Enable(e
) 
 269             # Set all states to modified 
 270             if e 
and k 
in self
.xxx
.params
: self
.controls
[k
].modified 
= True             
 272             self
.controlName
.SetValue(state
[2]) 
 274 ################################################################################ 
 276 # Panel for displaying properties 
 277 class PropPage(ParamPage
): 
 278     renameDict 
= {'orient':'orientation', 'option':'proportion', 
 279                   'usenotebooksizer':'usesizer', 'dontattachtoframe':'dontattach', 
 281     def __init__(self
, parent
, label
, xxx
): 
 282         ParamPage
.__init
__(self
, parent
, xxx
) 
 283         self
.box 
= wx
.StaticBox(self
, -1, label
) 
 284         #self.box.SetFont(g.labelFont()) 
 285         topSizer 
= wx
.StaticBoxSizer(self
.box
, wx
.VERTICAL
) 
 286         sizer 
= wx
.FlexGridSizer(len(xxx
.allParams
), 2, 1, 5) 
 287         sizer
.AddGrowableCol(1) 
 289             label 
= wx
.StaticText(self
, -1, 'XML ID:', size
=self
.labelSize
) 
 290             control 
= ParamText(self
, 'XML_name', 200) 
 291             sizer
.AddMany([ (label
, 0, wx
.ALIGN_CENTER_VERTICAL
), 
 292                             (control
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.BOTTOM | wx
.GROW
, 10) ]) 
 293             self
.controlName 
= control
 
 294         for param 
in xxx
.allParams
: 
 295             present 
= xxx
.params
.has_key(param
) 
 296             sParam 
= self
.renameDict
.get(param
, param
) 
 297             if param 
in xxx
.required
: 
 298                 if isinstance(xxx
, xxxComment
): 
 301                     label 
= wx
.StaticText(self
, paramIDs
[param
], sParam
, 
 302                                           size 
= self
.labelSize
, name 
= param
) 
 304                 label 
= wx
.CheckBox(self
, paramIDs
[param
], sParam
, 
 305                                    size 
= self
.labelSize
, name 
= param
) 
 306                 self
.checks
[param
] = label
 
 308                 typeClass 
= xxx
.paramDict
[param
] 
 312                     typeClass 
= paramDict
[param
] 
 315                     typeClass 
= ParamText
 
 316             control 
= typeClass(self
, param
) 
 317             control
.Enable(present
) 
 318             # Comment has only one parameter 
 319             if isinstance(xxx
, xxxComment
): 
 320                 # Bind char event to check Enter key 
 321                 control
.text
.Bind(wx
.EVT_CHAR
, self
.OnEnter
) 
 322                 sizer
.Add(control
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.GROW
) 
 324                 sizer
.AddMany([ (label
, 0, wx
.ALIGN_CENTER_VERTICAL
), 
 325                                 (control
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.GROW
) ]) 
 326             self
.controls
[param
] = control
 
 327         topSizer
.Add(sizer
, 1, wx
.ALL | wx
.EXPAND
, 3) 
 328         self
.SetSizer(topSizer
) 
 331     def SetValues(self
, xxx
): 
 334         self
.origControls 
= [] 
 335         # Set values, checkboxes to False, disable defaults 
 337             self
.controlName
.SetValue(xxx
.name
) 
 338             self
.origName 
= xxx
.name
 
 339         for param 
in xxx
.allParams
: 
 340             w 
= self
.controls
[param
] 
 343                 value 
= xxx
.params
[param
].value() 
 346                 if not param 
in xxx
.required
: 
 347                     self
.checks
[param
].SetValue(True) 
 348                     self
.origChecks
.append((param
, True)) 
 349                 self
.origControls
.append((param
, value
, True)) 
 351                 # Optional param not present in xxx - set empty value 
 352                 self
.checks
[param
].SetValue(False) 
 355                 self
.origChecks
.append((param
, False)) 
 356                 self
.origControls
.append((param
, '', False)) 
 358     # This is called only for comment now 
 359     def OnEnter(self
, evt
): 
 360         if evt
.GetKeyCode() == 13: 
 361             g
.tree
.Apply(self
.xxx
, g
.tree
.selection
) 
 365 ################################################################################ 
 367 # Style notebook page 
 368 class StylePage(ParamPage
): 
 369     renameDict 
= {'fg':'foreground', 'bg':'background'}
 
 370     def __init__(self
, parent
, label
, xxx
): 
 371         ParamPage
.__init
__(self
, parent
, xxx
) 
 372         box 
= wx
.StaticBox(self
, -1, label
) 
 373         #box.SetFont(g.labelFont()) 
 374         topSizer 
= wx
.StaticBoxSizer(box
, wx
.VERTICAL
) 
 375         sizer 
= wx
.FlexGridSizer(len(xxx
.styles
), 2, 1, 5) 
 376         sizer
.AddGrowableCol(1) 
 377         for param 
in xxx
.styles
: 
 378             present 
= xxx
.params
.has_key(param
) 
 379             sParam 
= self
.renameDict
.get(param
, param
) 
 380             check 
= wx
.CheckBox(self
, paramIDs
[param
], 
 381                                 sParam
, size 
= self
.labelSize
, name 
= param
) 
 382             check
.SetValue(present
) 
 383             control 
= paramDict
[param
](self
, name 
= param
) 
 384             control
.Enable(present
) 
 385             sizer
.AddMany([ (check
, 0, wx
.ALIGN_CENTER_VERTICAL
), 
 386                             (control
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.GROW
) ]) 
 387             self
.checks
[param
] = check
 
 388             self
.controls
[param
] = control
 
 389         topSizer
.Add(sizer
, 1, wx
.ALL | wx
.EXPAND
, 3) 
 390         self
.SetAutoLayout(True) 
 391         self
.SetSizer(topSizer
) 
 394     # Set data for a cahced page 
 395     def SetValues(self
, xxx
): 
 398         self
.origControls 
= [] 
 399         for param 
in xxx
.styles
: 
 400             present 
= xxx
.params
.has_key(param
) 
 401             check 
= self
.checks
[param
] 
 402             check
.SetValue(present
) 
 403             w 
= self
.controls
[param
] 
 406                 value 
= xxx
.params
[param
].value() 
 411             self
.origChecks
.append((param
, present
)) 
 412             self
.origControls
.append((param
, value
, present
))