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
22 # Set common button size for parameter buttons
23 bTmp
= wx
.Button(self
, -1, '')
25 params
.buttonSize
= (self
.DLG_SZE(buttonSizeD
)[0], bTmp
.GetSize()[1])
29 # List of child windows
31 # Create scrolled windows for pages
32 self
.page1
= wx
.ScrolledWindow(self
, -1)
34 sizer
.Add(wx
.BoxSizer()) # dummy sizer
35 self
.page1
.SetAutoLayout(True)
36 self
.page1
.SetSizer(sizer
)
37 self
.AddPage(self
.page1
, 'Properties')
39 self
.page2
= wx
.ScrolledWindow(self
, -1)
42 sizer
.Add(wx
.BoxSizer()) # 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
= wx
.BoxSizer(wx
.VERTICAL
)
63 # Special case - resize html window
65 topSizer
.Add(sizer
, 1, wx
.EXPAND
)
67 topSizer
.Add(sizer
, 0, wx
.ALL
, 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(wx
.StaticText(self
.page1
, -1, 'This item has no properties.'))
78 else: # nothing selected
79 # If first time, show some help
81 html
= HtmlWindow(self
.page1
, -1, wx
.DefaultPosition
,
82 wx
.DefaultSize
, wx
.SUNKEN_BORDER
)
83 html
.SetPage(g
.helpText
)
84 sizer
.Add(html
, 1, wx
.EXPAND
)
87 sizer
.Add(wx
.StaticText(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
.panelName(), 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, wx
.EXPAND
)
104 # Special label for child objects - they may have different GUI
105 cacheID
= (xxx
.child
.panelName(), 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, wx
.EXPAND | wx
.TOP
, 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, wx
.EXPAND
)
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 g
.frame
.SetModified()
164 self
.modified
= value
167 for p
in self
.pages
: p
.Apply()
169 ################################################################################
171 # General class for notebook pages
172 class ParamPage(wx
.Panel
):
173 def __init__(self
, parent
, xxx
):
174 wx
.Panel
.__init
__(self
, parent
, -1)
176 # Register event handlers
177 for id in paramIDs
.values():
178 wx
.EVT_CHECKBOX(self
, id, self
.OnCheckParams
)
180 self
.controls
= {} # save python objects
181 self
.controlName
= None
183 def OnCheckParams(self
, evt
):
185 param
= evt
.GetEventObject().GetName()
186 w
= self
.controls
[param
]
190 # Ad new text node in order of allParams
191 w
.SetValue('') # set empty (default) value
192 w
.SetModified() # mark as changed
193 elem
= g
.tree
.dom
.createElement(param
)
194 # Some classes are special
196 xxx
.params
[param
] = xxxParamFont(xxx
.node
, elem
)
197 elif param
in xxxObject
.bitmapTags
:
198 xxx
.params
[param
] = xxxParamBitmap(elem
)
200 xxx
.params
[param
] = xxxParam(elem
)
201 # Find place to put new element: first present element after param
204 paramStyles
= xxx
.allParams
+ xxx
.styles
206 paramStyles
= xxx
.allParams
207 for p
in paramStyles
[paramStyles
.index(param
) + 1:]:
208 # Content params don't have same type
209 if xxx
.params
.has_key(p
) and p
!= 'content':
213 nextTextElem
= xxx
.params
[p
].node
214 objElem
.insertBefore(elem
, nextTextElem
)
216 objElem
.appendChild(elem
)
219 xxx
.params
[param
].remove()
220 del xxx
.params
[param
]
222 w
.SetModified(False) # mark as not changed
224 # Set modified flag (provokes undo storing is necessary)
225 panel
.SetModified(True)
229 name
= self
.controlName
.GetValue()
232 xxx
.node
.setAttribute('name', name
)
233 for param
, w
in self
.controls
.items():
235 paramObj
= xxx
.params
[param
]
237 if param
in xxx
.specials
:
238 xxx
.setSpecial(param
, value
)
240 paramObj
.update(value
)
244 self
.origChecks
= map(lambda i
: (i
[0], i
[1].GetValue()), self
.checks
.items())
245 self
.origControls
= map(lambda i
: (i
[0], i
[1].GetValue(), i
[1].enabled
),
246 self
.controls
.items())
248 self
.origName
= self
.controlName
.GetValue()
249 # Return original values
252 return (self
.origChecks
, self
.origControls
, self
.origName
)
254 return (self
.origChecks
, self
.origControls
)
255 # Set values from undo data
256 def SetState(self
, state
):
258 self
.checks
[k
].SetValue(v
)
259 for k
,v
,e
in state
[1]:
260 self
.controls
[k
].SetValue(v
)
261 self
.controls
[k
].Enable(e
)
262 # Set all states to modified
263 if e
and k
in self
.xxx
.params
: self
.controls
[k
].modified
= True
265 self
.controlName
.SetValue(state
[2])
267 ################################################################################
271 # Panel for displaying properties
272 class PropPage(ParamPage
):
273 def __init__(self
, parent
, label
, xxx
):
274 ParamPage
.__init
__(self
, parent
, xxx
)
275 self
.box
= wx
.StaticBox(self
, -1, label
)
276 self
.box
.SetFont(g
.labelFont())
277 topSizer
= wx
.StaticBoxSizer(self
.box
, wx
.VERTICAL
)
278 sizer
= wx
.FlexGridSizer(len(xxx
.allParams
), 2, 0, 1)
279 sizer
.AddGrowableCol(1)
281 label
= wx
.StaticText(self
, -1, 'XML ID:', size
=(LABEL_WIDTH
,-1))
282 control
= ParamText(self
, 'XML_name', 200)
283 sizer
.AddMany([ (label
, 0, wx
.ALIGN_CENTER_VERTICAL
),
284 (control
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.BOTTOM | wx
.GROW
, 10) ])
285 self
.controlName
= control
286 for param
in xxx
.allParams
:
287 present
= xxx
.params
.has_key(param
)
288 if param
in xxx
.required
:
289 if isinstance(xxx
, xxxComment
):
292 label
= wx
.StaticText(self
, paramIDs
[param
], param
+ ':',
293 size
= (LABEL_WIDTH
,-1), name
= param
)
295 # Rename some parameters
296 if param
== 'usenotebooksizer': sParam
= 'usesizer:'
297 elif param
== 'option': sParam
= 'proportion'
298 else: sParam
= param
+ ':'
299 label
= wx
.CheckBox(self
, paramIDs
[param
], sParam
,
300 size
= (LABEL_WIDTH
,-1), name
= param
)
301 self
.checks
[param
] = label
303 typeClass
= xxx
.paramDict
[param
]
307 typeClass
= paramDict
[param
]
310 typeClass
= ParamText
311 control
= typeClass(self
, param
)
312 control
.Enable(present
)
313 # Comment has only one parameter
314 if isinstance(xxx
, xxxComment
):
315 # Bind char event to check Enter key
316 control
.text
.Bind(wx
.EVT_CHAR
, self
.OnEnter
)
317 sizer
.Add(control
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.GROW
)
319 sizer
.AddMany([ (label
, 0, wx
.ALIGN_CENTER_VERTICAL
),
320 (control
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.GROW
) ])
321 self
.controls
[param
] = control
322 topSizer
.Add(sizer
, 1, wx
.ALL | wx
.EXPAND
, 3)
323 self
.SetSizer(topSizer
)
326 def SetValues(self
, xxx
):
329 self
.origControls
= []
330 # Set values, checkboxes to False, disable defaults
332 self
.controlName
.SetValue(xxx
.name
)
333 self
.origName
= xxx
.name
334 for param
in xxx
.allParams
:
335 w
= self
.controls
[param
]
338 value
= xxx
.params
[param
].value()
341 if not param
in xxx
.required
:
342 self
.checks
[param
].SetValue(True)
343 self
.origChecks
.append((param
, True))
344 self
.origControls
.append((param
, value
, True))
346 self
.checks
[param
].SetValue(False)
349 self
.origChecks
.append((param
, False))
350 self
.origControls
.append((param
, '', False))
352 # This is called only for comment now
353 def OnEnter(self
, evt
):
354 if evt
.GetKeyCode() == 13:
355 g
.tree
.Apply(self
.xxx
, g
.tree
.selection
)
359 ################################################################################
361 # Style notebook page
362 class StylePage(ParamPage
):
363 def __init__(self
, parent
, label
, xxx
):
364 ParamPage
.__init
__(self
, parent
, xxx
)
365 box
= wx
.StaticBox(self
, -1, label
)
366 box
.SetFont(g
.labelFont())
367 topSizer
= wx
.StaticBoxSizer(box
, wx
.VERTICAL
)
368 sizer
= wx
.FlexGridSizer(len(xxx
.styles
), 2, 0, 1)
369 sizer
.AddGrowableCol(1)
370 for param
in xxx
.styles
:
371 present
= xxx
.params
.has_key(param
)
372 check
= wx
.CheckBox(self
, paramIDs
[param
],
373 param
+ ':', size
= (LABEL_WIDTH
,-1), name
= param
)
374 check
.SetValue(present
)
375 control
= paramDict
[param
](self
, name
= param
)
376 control
.Enable(present
)
377 sizer
.AddMany([ (check
, 0, wx
.ALIGN_CENTER_VERTICAL
),
378 (control
, 0, wx
.ALIGN_CENTER_VERTICAL | wx
.GROW
) ])
379 self
.checks
[param
] = check
380 self
.controls
[param
] = control
381 topSizer
.Add(sizer
, 1, wx
.ALL | wx
.EXPAND
, 3)
382 self
.SetAutoLayout(True)
383 self
.SetSizer(topSizer
)
386 # Set data for a cahced page
387 def SetValues(self
, xxx
):
390 self
.origControls
= []
391 for param
in xxx
.styles
:
392 present
= xxx
.params
.has_key(param
)
393 check
= self
.checks
[param
]
394 check
.SetValue(present
)
395 w
= self
.controls
[param
]
398 value
= xxx
.params
[param
].value()
403 self
.origChecks
.append((param
, present
))
404 self
.origControls
.append((param
, value
, present
))