]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/tools/XRCed/panel.py
drag-and-drop with left button
[wxWidgets.git] / wxPython / wx / tools / XRCed / panel.py
1 # Name: panel.py
2 # Purpose: XRC editor, Panel class and related
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
4 # Created: 02.12.2002
5 # RCS-ID: $Id$
6
7 from xxx import * # xxx imports globals and params
8 from undo import *
9 from wx.html import HtmlWindow
10
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)
16 else:
17 wx.Notebook.__init__(self, parent, id)
18 global panel
19 g.panel = panel = self
20 self.modified = False
21
22 # Set common sizes
23 import params
24 cTmp = wx.Button(self, -1, '')
25 params.buttonSize = (self.DLG_SZE(buttonSizeD)[0], cTmp.GetSize()[1])
26 cTmp.Destroy()
27 cTmp = wx.TextCtrl(self, -1, '')
28 params.textSize = cTmp.GetSize()
29 cTmp.Destroy()
30 cTmp = wx.CheckBox(self, -1, 'growablerows ') # this is the longest
31 ParamPage.labelSize = cTmp.GetSize()
32 cTmp.Destroy()
33 del cTmp
34
35 # List of child windows
36 self.pages = []
37 # Create scrolled windows for pages
38 self.page1 = wx.ScrolledWindow(self, -1)
39 sizer = wx.BoxSizer()
40 sizer.Add(wx.BoxSizer()) # dummy sizer
41 self.page1.SetAutoLayout(True)
42 self.page1.SetSizer(sizer)
43 self.AddPage(self.page1, 'Properties')
44 # Second page
45 self.page2 = wx.ScrolledWindow(self, -1)
46 self.page2.Hide()
47 sizer = wx.BoxSizer()
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
54
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():
60 sizer.Detach(w)
61 if isinstance(w, ParamPage):
62 if w.IsShown():
63 w.Hide()
64 else:
65 w.Destroy()
66 topSizer.Remove(sizer)
67 # Create new windows
68 sizer = wx.BoxSizer(wx.VERTICAL)
69 # Special case - resize html window
70 if g.conf.panic:
71 topSizer.Add(sizer, 1, wx.EXPAND)
72 else:
73 topSizer.Add(sizer, 0, wx.ALL, 5)
74 return sizer
75
76 def SetData(self, xxx):
77 self.pages = []
78 # First page
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):
82 if g.tree.selection:
83 sizer.Add(wx.StaticText(self.page1, -1, 'This item has no properties.'))
84 else: # nothing selected
85 # If first time, show some help
86 if g.conf.panic:
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)
91 g.conf.panic = False
92 else:
93 sizer.Add(wx.StaticText(self.page1, -1, 'Select a tree item.'))
94 else:
95 g.currentXXX = xxx.treeObject()
96 # Normal or SizerItem page
97 isGBSizerItem = isinstance(xxx.parent, xxxGridBagSizer)
98 cacheID = (xxx.panelName(), isGBSizerItem)
99 try:
100 page = self.pageCache[cacheID]
101 page.box.SetLabel(xxx.panelName())
102 page.Show()
103 except KeyError:
104 page = PropPage(self.page1, xxx.panelName(), xxx)
105 self.pageCache[cacheID] = page
106 page.SetValues(xxx)
107 self.pages.append(page)
108 sizer.Add(page, 1, wx.EXPAND)
109 if xxx.hasChild:
110 # Special label for child objects - they may have different GUI
111 cacheID = (xxx.child.panelName(), xxx.__class__)
112 try:
113 page = self.pageCache[cacheID]
114 page.box.SetLabel(xxx.child.panelName())
115 page.Show()
116 except KeyError:
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)
122 self.page1.Layout()
123 size = self.page1.GetSizer().GetMinSize()
124 self.page1.SetScrollbars(1, 1, size.width, size.height, 0, 0, True)
125
126 # Second page
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)
132 try:
133 page = self.stylePageCache[xxx.__class__]
134 page.Show()
135 except KeyError:
136 page = StylePage(self.page2, xxx.className + ' style', xxx)
137 self.stylePageCache[xxx.__class__] = page
138 page.SetValues(xxx)
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')
144 self.page2.Layout()
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)
149 else:
150 # Remove page if exists
151 if self.GetPageCount() == 2:
152 self.SetSelection(0)
153 self.page1.Refresh()
154 self.RemovePage(1)
155 self.modified = False
156
157 def Clear(self):
158 self.SetData(None)
159 self.modified = False
160
161 # If some parameter has changed
162 def IsModified(self):
163 return self.modified
164
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
171
172 def Apply(self):
173 for p in self.pages: p.Apply()
174
175 ################################################################################
176
177 # General class for notebook pages
178 class ParamPage(wx.Panel):
179 labelSize = None
180 def __init__(self, parent, xxx):
181 wx.Panel.__init__(self, parent, -1)
182 self.xxx = xxx
183 # Register event handlers
184 for id in paramIDs.values():
185 wx.EVT_CHECKBOX(self, id, self.OnCheckParams)
186 self.checks = {}
187 self.controls = {} # save python objects
188 self.controlName = None
189
190 def OnCheckParams(self, evt):
191 xxx = self.xxx
192 param = evt.GetEventObject().GetName()
193 w = self.controls[param]
194 w.Enable(True)
195 objElem = xxx.node
196 if evt.IsChecked():
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
202 if param == 'font':
203 xxx.params[param] = xxxParamFont(xxx.node, elem)
204 elif param in xxxObject.bitmapTags:
205 xxx.params[param] = xxxParamBitmap(elem)
206 else:
207 xxx.params[param] = xxxParam(elem)
208 # Find place to put new element: first present element after param
209 found = False
210 if xxx.hasStyle:
211 paramStyles = xxx.allParams + xxx.styles
212 else:
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':
217 found = True
218 break
219 if found:
220 nextTextElem = xxx.params[p].node
221 objElem.insertBefore(elem, nextTextElem)
222 else:
223 objElem.appendChild(elem)
224 else:
225 # Remove parameter
226 xxx.params[param].remove()
227 del xxx.params[param]
228 w.SetValue('')
229 w.SetModified(False) # mark as not changed
230 w.Enable(False)
231 # Set modified flag (provokes undo storing is necessary)
232 panel.SetModified(True)
233 def Apply(self):
234 xxx = self.xxx
235 if self.controlName:
236 name = self.controlName.GetValue()
237 if xxx.name != name:
238 xxx.name = name
239 xxx.node.setAttribute('name', name)
240 for param, w in self.controls.items():
241 if w.modified:
242 paramObj = xxx.params[param]
243 value = w.GetValue()
244 if param in xxx.specials:
245 xxx.setSpecial(param, value)
246 else:
247 paramObj.update(value)
248
249 # Save current state
250 def SaveState(self):
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())
254 if self.controlName:
255 self.origName = self.controlName.GetValue()
256 # Return original values
257 def GetState(self):
258 if self.controlName:
259 return (self.origChecks, self.origControls, self.origName)
260 else:
261 return (self.origChecks, self.origControls)
262 # Set values from undo data
263 def SetState(self, state):
264 for k,v in state[0]:
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
271 if self.controlName:
272 self.controlName.SetValue(state[2])
273
274 ################################################################################
275
276 # Panel for displaying properties
277 class PropPage(ParamPage):
278 renameDict = {'orient':'orientation', 'option':'proportion',
279 'usenotebooksizer':'usesizer', 'dontattachtoframe':'dontattach',
280 }
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)
288 if xxx.hasName:
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):
299 label = None
300 else:
301 label = wx.StaticText(self, paramIDs[param], sParam,
302 size = self.labelSize, name = param)
303 else:
304 label = wx.CheckBox(self, paramIDs[param], sParam,
305 size = self.labelSize, name = param)
306 self.checks[param] = label
307 try:
308 typeClass = xxx.paramDict[param]
309 except KeyError:
310 try:
311 # Standart type
312 typeClass = paramDict[param]
313 except KeyError:
314 # Default
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)
323 else:
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)
329 topSizer.Fit(self)
330
331 def SetValues(self, xxx):
332 self.xxx = xxx
333 self.origChecks = []
334 self.origControls = []
335 # Set values, checkboxes to False, disable defaults
336 if xxx.hasName:
337 self.controlName.SetValue(xxx.name)
338 self.origName = xxx.name
339 for param in xxx.allParams:
340 w = self.controls[param]
341 w.modified = False
342 try:
343 value = xxx.params[param].value()
344 w.Enable(True)
345 w.SetValue(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))
350 except KeyError:
351 # Optional param not present in xxx - set empty value
352 self.checks[param].SetValue(False)
353 w.SetValue('')
354 w.Enable(False)
355 self.origChecks.append((param, False))
356 self.origControls.append((param, '', False))
357
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)
362 else:
363 evt.Skip()
364
365 ################################################################################
366
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)
392 topSizer.Fit(self)
393
394 # Set data for a cahced page
395 def SetValues(self, xxx):
396 self.xxx = xxx
397 self.origChecks = []
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]
404 w.modified = False
405 if present:
406 value = xxx.params[param].value()
407 else:
408 value = ''
409 w.SetValue(value)
410 w.Enable(present)
411 self.origChecks.append((param, present))
412 self.origControls.append((param, value, present))
413