]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/tools/XRCed/params.py
added support for drop down toolbar buttons (patch 1713470)
[wxWidgets.git] / wxPython / wx / tools / XRCed / params.py
1 # Name: params.py
2 # Purpose: Classes for parameter introduction
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
4 # Created: 22.08.2001
5 # RCS-ID: $Id$
6
7 import string
8 import os.path
9 from globals import *
10 from types import *
11
12 genericStyles = [
13 'wxSIMPLE_BORDER', 'wxSUNKEN_BORDER', 'wxDOUBLE_BORDER',
14 'wxRAISED_BORDER', 'wxSTATIC_BORDER', 'wxNO_BORDER',
15 'wxCLIP_CHILDREN', 'wxTRANSPARENT_WINDOW', 'wxWANTS_CHARS',
16 'wxNO_FULL_REPAINT_ON_RESIZE', 'wxFULL_REPAINT_ON_RESIZE'
17 ]
18
19 genericExStyles = [
20 'wxWS_EX_VALIDATE_RECURSIVELY',
21 'wxWS_EX_BLOCK_EVENTS',
22 'wxWS_EX_TRANSIENT',
23 'wxFRAME_EX_CONTEXTHELP',
24 'wxWS_EX_PROCESS_IDLE',
25 'wxWS_EX_PROCESS_UI_UPDATES'
26 ]
27
28 # Global vars initialized in Panel.__init__ for button and textbox size in screen pixels
29 buttonSize = textSise = None
30 # Default Button size in dialog units
31 buttonSizeD = (35,-1)
32
33
34 # Class that can properly disable children
35 class PPanel(wx.Panel):
36 def __init__(self, parent, name):
37 wx.Panel.__init__(self, parent, -1, name=name)
38 self.modified = self.freeze = False
39 def Enable(self, value):
40 self.enabled = value
41 # Something strange is going on with enable so we make sure...
42 for w in self.GetChildren():
43 w.Enable(value)
44 #wx.Panel.Enable(self, value)
45 def SetModified(self, state=True):
46 self.modified = state
47 if state: g.panel.SetModified(True)
48 # Common method to set modified state
49 def OnChange(self, evt):
50 if self.freeze: return
51 self.SetModified()
52 evt.Skip()
53
54 class ParamBinaryOr(PPanel):
55 def __init__(self, parent, name):
56 PPanel.__init__(self, parent, name)
57 self.ID_TEXT_CTRL = wx.NewId()
58 self.ID_BUTTON_CHOICES = wx.NewId()
59 sizer = wx.BoxSizer()
60 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
61 sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
62 self.button = wx.Button(self, self.ID_BUTTON_CHOICES, 'Edit...',
63 size=(buttonSize[0], textSize[1]))
64 sizer.Add(self.button, 0, wx.EXPAND)
65 self.SetSizerAndFit(sizer)
66 wx.EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices)
67 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
68 def GetValue(self):
69 return self.text.GetValue()
70 def SetValue(self, value):
71 self.freeze = True
72 self.text.SetValue(value)
73 self.freeze = False
74 def OnButtonChoices(self, evt):
75 dlg = g.frame.res.LoadDialog(self, 'DIALOG_CHOICES')
76 if self.GetName() == 'flag': dlg.SetTitle('Sizer item flags')
77 elif self.GetName() == 'style': dlg.SetTitle('Window styles')
78 elif self.GetName() == 'exstyle': dlg.SetTitle('Extended window styles')
79 listBox = xrc.XRCCTRL(dlg, 'CHECKLIST')
80 listBox.InsertItems(self.values, 0)
81 value = map(string.strip, self.text.GetValue().split('|'))
82 if value == ['']: value = []
83 ignored = []
84 for i in value:
85 try:
86 listBox.Check(self.values.index(i))
87 except ValueError:
88 # Try to find equal
89 if self.equal.has_key(i):
90 listBox.Check(self.values.index(self.equal[i]))
91 else:
92 print 'WARNING: unknown flag: %s: ignored.' % i
93 ignored.append(i)
94 if dlg.ShowModal() == wx.ID_OK:
95 value = []
96 for i in range(listBox.GetCount()):
97 if listBox.IsChecked(i):
98 value.append(self.values[i])
99 # Add ignored flags
100 value.extend(ignored)
101 self.SetValue('|'.join(value))
102 self.SetModified()
103 dlg.Destroy()
104
105 class ParamFlag(ParamBinaryOr):
106 values = ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL',
107 'wxEXPAND', 'wxGROW', 'wxSHAPED', 'wxSTRETCH_NOT',
108 'wxALIGN_CENTRE', 'wxALIGN_LEFT', 'wxALIGN_RIGHT',
109 'wxALIGN_TOP', 'wxALIGN_BOTTOM',
110 'wxALIGN_CENTRE_VERTICAL', 'wxALIGN_CENTRE_HORIZONTAL',
111 'wxADJUST_MINSIZE', 'wxFIXED_MINSIZE'
112 ]
113 equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE',
114 'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL',
115 'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL',
116 'wxUP': 'wxTOP', 'wxDOWN': 'wxBOTTOM', 'wxNORTH': 'wxTOP',
117 'wxSOUTH': 'wxBOTTOM', 'wxWEST': 'wxLEFT', 'wxEAST': 'wxRIGHT'}
118 def __init__(self, parent, name):
119 ParamBinaryOr.__init__(self, parent, name)
120
121 class ParamNonGenericStyle(ParamBinaryOr):
122 def __init__(self, parent, name):
123 self.values = g.currentXXX.winStyles
124 ParamBinaryOr.__init__(self, parent, name)
125
126 class ParamStyle(ParamBinaryOr):
127 equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
128 def __init__(self, parent, name):
129 ParamBinaryOr.__init__(self, parent, name)
130 self.valuesSpecific = g.currentXXX.winStyles
131 if self.valuesSpecific: # override if using specific styles
132 # Remove duplicates
133 self.valuesGeneric = [s for s in genericStyles
134 if s not in self.valuesSpecific]
135 wx.EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoicesBoth)
136 else:
137 self.values = genericStyles
138 def OnButtonChoicesBoth(self, evt):
139 dlg = g.frame.res.LoadDialog(self, 'DIALOG_STYLES')
140 listBoxSpecific = xrc.XRCCTRL(dlg, 'CHECKLIST_SPECIFIC')
141 listBoxSpecific.InsertItems(self.valuesSpecific, 0)
142 listBoxGeneric = xrc.XRCCTRL(dlg, 'CHECKLIST_GENERIC')
143 listBoxGeneric.InsertItems(self.valuesGeneric, 0)
144 value = map(string.strip, self.text.GetValue().split('|'))
145 if value == ['']: value = []
146 # Set specific styles
147 value2 = [] # collect generic and ignored here
148 for i in value:
149 try:
150 listBoxSpecific.Check(self.valuesSpecific.index(i))
151 except ValueError:
152 # Try to find equal
153 if self.equal.has_key(i):
154 listBoxSpecific.Check(self.valuesSpecific.index(self.equal[i]))
155 else:
156 value2.append(i)
157 ignored = []
158 # Set generic styles, collect non-standart values
159 for i in value2:
160 try:
161 listBoxGeneric.Check(self.valuesGeneric.index(i))
162 except ValueError:
163 # Try to find equal
164 if self.equal.has_key(i):
165 listBoxGeneric.Check(self.valuesGeneric.index(self.equal[i]))
166 else:
167 print 'WARNING: unknown flag: %s: ignored.' % i
168 ignored.append(i)
169 if dlg.ShowModal() == wx.ID_OK:
170 value = [self.valuesSpecific[i]
171 for i in range(listBoxSpecific.GetCount())
172 if listBoxSpecific.IsChecked(i)] + \
173 [self.valuesGeneric[i]
174 for i in range(listBoxGeneric.GetCount())
175 if listBoxGeneric.IsChecked(i)] + ignored
176 self.SetValue('|'.join(value))
177 self.SetModified()
178 dlg.Destroy()
179
180 class ParamExStyle(ParamBinaryOr):
181 def __init__(self, parent, name):
182 if g.currentXXX:
183 self.values = g.currentXXX.exStyles + genericExStyles
184 else:
185 self.values = []
186 ParamBinaryOr.__init__(self, parent, name)
187
188 class ParamColour(PPanel):
189 def __init__(self, parent, name):
190 PPanel.__init__(self, parent, name)
191 self.ID_TEXT_CTRL = wx.NewId()
192 self.ID_BUTTON = wx.NewId()
193 sizer = wx.BoxSizer()
194 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=(80,-1))
195 sizer.Add(self.text, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2)
196 self.button = wx.Panel(self, self.ID_BUTTON, wx.DefaultPosition, wx.Size(20, 20))
197 sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
198 self.SetSizer(sizer)
199 self.textModified = False
200 wx.EVT_PAINT(self.button, self.OnPaintButton)
201 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
202 wx.EVT_LEFT_DOWN(self.button, self.OnLeftDown)
203 def GetValue(self):
204 return self.text.GetValue()
205 def SetValue(self, value):
206 self.freeze = True
207 if not value: value = '#FFFFFF'
208 self.text.SetValue(str(value)) # update text ctrl
209 try:
210 colour = wx.Colour(int(value[1:3], 16), int(value[3:5], 16), int(value[5:7], 16))
211 self.button.SetBackgroundColour(colour)
212 except: # ignore errors
213 pass
214 self.button.Refresh()
215 self.freeze = False
216 def OnPaintButton(self, evt):
217 dc = wx.PaintDC(self.button)
218 dc.SetBrush(wx.TRANSPARENT_BRUSH)
219 if self.IsEnabled(): dc.SetPen(wx.BLACK_PEN)
220 else: dc.SetPen(wx.GREY_PEN)
221 size = self.button.GetSize()
222 dc.DrawRectangle(0, 0, size.width, size.height)
223 def OnLeftDown(self, evt):
224 data = wx.ColourData()
225 data.SetColour(self.GetValue())
226 dlg = wx.ColourDialog(self, data)
227 if dlg.ShowModal() == wx.ID_OK:
228 self.SetValue('#%02X%02X%02X' % dlg.GetColourData().GetColour().Get())
229 self.SetModified()
230 dlg.Destroy()
231
232 ################################################################################
233
234 # Mapping from wx constants to XML strings
235 fontFamiliesWx2Xml = {wx.DEFAULT: 'default', wx.DECORATIVE: 'decorative',
236 wx.ROMAN: 'roman', wx.SCRIPT: 'script', wx.SWISS: 'swiss',
237 wx.MODERN: 'modern'}
238 fontStylesWx2Xml = {wx.NORMAL: 'normal', wx.SLANT: 'slant', wx.ITALIC: 'italic'}
239 fontWeightsWx2Xml = {wx.NORMAL: 'normal', wx.LIGHT: 'light', wx.BOLD: 'bold'}
240 def ReverseMap(m):
241 rm = {}
242 for k,v in m.items(): rm[v] = k
243 return rm
244 fontFamiliesXml2wx = ReverseMap(fontFamiliesWx2Xml)
245 fontStylesXml2wx = ReverseMap(fontStylesWx2Xml)
246 fontWeightsXml2wx = ReverseMap(fontWeightsWx2Xml)
247
248 class ParamFont(PPanel):
249 def __init__(self, parent, name):
250 PPanel.__init__(self, parent, name)
251 self.ID_TEXT_CTRL = wx.NewId()
252 self.ID_BUTTON_SELECT = wx.NewId()
253 sizer = wx.BoxSizer()
254 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=(200,-1))
255 sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
256 self.button = wx.Button(self, self.ID_BUTTON_SELECT, 'Select...', size=buttonSize)
257 sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
258 self.SetSizer(sizer)
259 self.textModified = False
260 wx.EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect)
261 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
262 def OnChange(self, evt):
263 PPanel.OnChange(self, evt)
264 self.textModified = True
265 def _defaultValue(self):
266 return [`g.sysFont().GetPointSize()`, 'default', 'normal', 'normal', '0', '', '']
267 def GetValue(self):
268 if self.textModified: # text has newer value
269 try:
270 return eval(self.text.GetValue())
271 except SyntaxError:
272 wx.LogError('Syntax error in parameter value: ' + self.GetName())
273 return self._defaultValue()
274 return self.value
275 def SetValue(self, value):
276 self.freeze = True # disable other handlers
277 if not value: value = self._defaultValue()
278 self.value = value
279 self.text.SetValue(str(value)) # update text ctrl
280 self.freeze = False
281 def OnButtonSelect(self, evt):
282 if self.textModified: # text has newer value
283 try:
284 self.value = eval(self.text.GetValue())
285 except SyntaxError:
286 wx.LogError('Syntax error in parameter value: ' + self.GetName())
287 self.value = self._defaultValue()
288 # Make initial font
289 # Default values
290 size = g.sysFont().GetPointSize()
291 family = wx.DEFAULT
292 style = weight = wx.NORMAL
293 underlined = 0
294 face = ''
295 enc = wx.FONTENCODING_DEFAULT
296 # Fall back to default if exceptions
297 error = False
298 try:
299 try: size = int(self.value[0])
300 except ValueError: error = True; wx.LogError('Invalid size specification')
301 try: family = fontFamiliesXml2wx[self.value[1]]
302 except KeyError: error = True; wx.LogError('Invalid family specification')
303 try: style = fontStylesXml2wx[self.value[2]]
304 except KeyError: error = True; wx.LogError('Invalid style specification')
305 try: weight = fontWeightsXml2wx[self.value[3]]
306 except KeyError: error = True; wx.LogError('Invalid weight specification')
307 try: underlined = bool(self.value[4])
308 except ValueError: error = True; wx.LogError('Invalid underlined flag specification')
309 face = self.value[5]
310 except IndexError:
311 error = True
312 mapper = wx.FontMapper()
313 if not self.value[6]: enc = mapper.CharsetToEncoding(self.value[6])
314
315 if error: wx.LogError('Invalid font specification')
316 if enc == wx.FONTENCODING_DEFAULT: enc = wx.FONTENCODING_SYSTEM
317 font = wx.Font(size, family, style, weight, underlined, face, enc)
318 data = wx.FontData()
319 data.SetInitialFont(font)
320 dlg = wx.FontDialog(self, data)
321 if dlg.ShowModal() == wx.ID_OK:
322 font = dlg.GetFontData().GetChosenFont()
323 if font.GetEncoding() == wx.FONTENCODING_SYSTEM:
324 encName = ''
325 else:
326 encName = wx.FontMapper.GetEncodingName(font.GetEncoding()).encode()
327 value = [str(font.GetPointSize()),
328 fontFamiliesWx2Xml.get(font.GetFamily(), "default"),
329 fontStylesWx2Xml.get(font.GetStyle(), "normal"),
330 fontWeightsWx2Xml.get(font.GetWeight(), "normal"),
331 str(int(font.GetUnderlined())),
332 font.GetFaceName().encode(),
333 encName
334 ]
335 self.SetValue(value)
336 self.SetModified()
337 self.textModified = False
338 dlg.Destroy()
339
340 ################################################################################
341
342 class ParamInt(PPanel):
343 def __init__(self, parent, name):
344 PPanel.__init__(self, parent, name)
345 self.ID_SPIN_CTRL = wx.NewId()
346 sizer = wx.BoxSizer()
347 self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1))
348 self.spin.SetRange(-2147483648, 2147483647) # min/max integers
349 sizer.Add(self.spin)
350 self.SetSizer(sizer)
351 wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange)
352 def GetValue(self):
353 return str(self.spin.GetValue())
354 def SetValue(self, value):
355 self.freeze = True
356 if not value: value = 0
357 self.spin.SetValue(int(value))
358 self.freeze = False
359
360 # Non-negative number
361 class ParamIntNN(PPanel):
362 def __init__(self, parent, name):
363 PPanel.__init__(self, parent, name)
364 self.ID_SPIN_CTRL = wx.NewId()
365 sizer = wx.BoxSizer()
366 self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1))
367 self.spin.SetRange(0, 10000) # min/max integers
368 sizer.Add(self.spin)
369 self.SetSizer(sizer)
370 wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange)
371 def GetValue(self):
372 return str(self.spin.GetValue())
373 def SetValue(self, value):
374 self.freeze = True
375 if not value: value = 0
376 self.spin.SetValue(int(value))
377 self.freeze = False
378
379 # Same as int but allows dialog units (XXXd)
380 class ParamUnit(PPanel):
381 def __init__(self, parent, name):
382 PPanel.__init__(self, parent, name)
383 self.ID_TEXT_CTRL = wx.NewId()
384 self.ID_SPIN_BUTTON = wx.NewId()
385 sizer = wx.BoxSizer(wx.HORIZONTAL)
386 self.spin = wx.SpinButton(self, self.ID_SPIN_BUTTON, style = wx.SP_VERTICAL, size=(-1,0))
387 textW = 60 - self.spin.GetSize()[0]
388 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=(textW,-1))
389 self.spin.SetRange(-10000, 10000)
390 sizer.Add(self.text, 0, wx.EXPAND)
391 sizer.Add(self.spin, 0, wx.EXPAND)
392 self.SetSizer(sizer)
393 self.spin.Bind(wx.EVT_SPIN_UP, self.OnSpinUp)
394 self.spin.Bind(wx.EVT_SPIN_DOWN, self.OnSpinDown)
395 self.text.Bind(wx.EVT_TEXT, self.OnChange)
396
397 def GetValue(self):
398 return self.text.GetValue()
399 def SetValue(self, value):
400 self.freeze = True
401 if not value: value = '0'
402 self.text.SetValue(value)
403 self.Change(0)
404 self.freeze = False
405 def Change(self, x):
406 self.freeze = True
407 # Check if we are working with dialog units
408 value = self.text.GetValue()
409 units = ''
410 if value[-1].upper() == 'D':
411 units = value[-1]
412 value = value[:-1]
413 try:
414 intValue = int(value) + x
415 self.spin.SetValue(intValue)
416 if x: # 0 can be passed to update spin value only
417 self.text.SetValue(str(intValue) + units)
418 self.SetModified()
419 except:
420 # !!! Strange, if I use wx.LogWarning, event is re-generated
421 print 'ERROR: incorrect unit format'
422 self.freeze = False
423 def OnSpinUp(self, evt):
424 self.freeze = True
425 self.Change(1)
426 def OnSpinDown(self, evt):
427 if self.freeze: return
428 self.freeze = True
429 self.Change(-1)
430
431 class ParamMultilineText(PPanel):
432 def __init__(self, parent, name, textWidth=-1):
433 PPanel.__init__(self, parent, name)
434 self.ID_TEXT_CTRL = wx.NewId()
435 self.ID_BUTTON_EDIT = wx.NewId()
436 sizer = wx.BoxSizer()
437 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
438 sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
439 self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
440 sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
441 self.SetSizerAndFit(sizer)
442 wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
443 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
444 def GetValue(self):
445 return self.text.GetValue()
446 def SetValue(self, value):
447 self.freeze = True # disable other handlers
448 self.text.SetValue(value)
449 self.freeze = False # disable other handlers
450 def OnButtonEdit(self, evt):
451 dlg = g.frame.res.LoadDialog(self, 'DIALOG_TEXT')
452 textCtrl = xrc.XRCCTRL(dlg, 'TEXT')
453 textCtrl.SetValue(self.text.GetValue())
454 if dlg.ShowModal() == wx.ID_OK:
455 self.text.SetValue(textCtrl.GetValue())
456 self.SetModified()
457 dlg.Destroy()
458
459 class ParamText(PPanel):
460 def __init__(self, parent, name, textWidth=-1, style=0):
461 PPanel.__init__(self, parent, name)
462 self.ID_TEXT_CTRL = wx.NewId()
463 # We use sizer even here to have the same size of text control
464 sizer = wx.BoxSizer()
465 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(textWidth,-1), style=style)
466 if textWidth == -1: option = 1
467 else: option = 0
468 sizer.Add(self.text, option, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2)
469 self.SetSizer(sizer)
470 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
471 def GetValue(self):
472 return self.text.GetValue()
473 def SetValue(self, value):
474 self.freeze = True # disable other handlers
475 self.text.SetValue(value)
476 self.freeze = False # disable other handlers
477
478 class ParamAccel(ParamText):
479 def __init__(self, parent, name):
480 ParamText.__init__(self, parent, name, 100)
481
482 class ParamPosSize(ParamText):
483 def __init__(self, parent, name):
484 ParamText.__init__(self, parent, name, 80)
485
486 class ParamLabel(ParamText):
487 def __init__(self, parent, name):
488 ParamText.__init__(self, parent, name, 200)
489
490 class ParamEncoding(ParamText):
491 def __init__(self, parent, name):
492 ParamText.__init__(self, parent, name, 100)
493
494 class ParamComment(ParamText):
495 def __init__(self, parent, name):
496 ParamText.__init__(self, parent, name, 330 + buttonSize[0],
497 style=wx.TE_PROCESS_ENTER)
498
499 class ContentDialog(wx.Dialog):
500 def __init__(self, parent, value):
501 # Load from resource
502 pre = wx.PreDialog()
503 g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT')
504 self.PostCreate(pre)
505 self.list = xrc.XRCCTRL(self, 'LIST')
506 # Set list items
507 for v in value:
508 self.list.Append(v)
509 self.SetAutoLayout(True)
510 self.GetSizer().Fit(self)
511 # Callbacks
512 self.ID_BUTTON_APPEND = xrc.XRCID('BUTTON_APPEND')
513 self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
514 self.ID_BUTTON_UP = xrc.XRCID('BUTTON_UP')
515 self.ID_BUTTON_DOWN = xrc.XRCID('BUTTON_DOWN')
516 wx.EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
517 wx.EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
518 wx.EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
519 wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
520 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
521 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
522 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
523 def OnButtonUp(self, evt):
524 i = self.list.GetSelection()
525 str = self.list.GetString(i)
526 self.list.Delete(i)
527 self.list.InsertItems([str], i-1)
528 self.list.SetSelection(i-1)
529 def OnButtonDown(self, evt):
530 i = self.list.GetSelection()
531 str = self.list.GetString(i)
532 self.list.Delete(i)
533 self.list.InsertItems([str], i+1)
534 self.list.SetSelection(i+1)
535 def OnButtonAppend(self, evt):
536 str = wx.GetTextFromUser('Enter new item:', 'Append', '', self)
537 self.list.Append(str)
538 def OnButtonRemove(self, evt):
539 self.list.Delete(self.list.GetSelection())
540 def OnUpdateUI(self, evt):
541 if evt.GetId() == self.ID_BUTTON_REMOVE:
542 evt.Enable(self.list.GetSelection() != -1)
543 elif evt.GetId() == self.ID_BUTTON_UP:
544 evt.Enable(self.list.GetSelection() > 0)
545 elif evt.GetId() == self.ID_BUTTON_DOWN:
546 evt.Enable(self.list.GetSelection() != -1 and \
547 self.list.GetSelection() < self.list.GetCount() - 1)
548
549 class ContentCheckListDialog(wx.Dialog):
550 def __init__(self, parent, value):
551 pre = wx.PreDialog()
552 g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT_CHECKLIST')
553 self.PostCreate(pre)
554 self.list = xrc.XRCCTRL(self, 'CHECK_LIST')
555 # Set list items
556 i = 0
557 for v,ch in value:
558 self.list.Append(v)
559 self.list.Check(i, ch)
560 i += 1
561 self.SetAutoLayout(True)
562 self.GetSizer().Fit(self)
563 # Callbacks
564 self.ID_BUTTON_APPEND = xrc.XRCID('BUTTON_APPEND')
565 self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
566 self.ID_BUTTON_UP = xrc.XRCID('BUTTON_UP')
567 self.ID_BUTTON_DOWN = xrc.XRCID('BUTTON_DOWN')
568 wx.EVT_CHECKLISTBOX(self, self.list.GetId(), self.OnCheck)
569 wx.EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
570 wx.EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
571 wx.EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
572 wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
573 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
574 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
575 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
576 def OnCheck(self, evt):
577 # !!! Wrong wxGTK (wxMSW?) behavior: toggling selection if checking
578 self.list.Deselect(evt.GetSelection())
579 def OnButtonUp(self, evt):
580 i = self.list.GetSelection()
581 str, ch = self.list.GetString(i), self.list.IsChecked(i)
582 self.list.Delete(i)
583 self.list.InsertItems([str], i-1)
584 self.list.Check(i-1, ch)
585 self.list.SetSelection(i-1)
586 def OnButtonDown(self, evt):
587 i = self.list.GetSelection()
588 str, ch = self.list.GetString(i), self.list.IsChecked(i)
589 self.list.Delete(i)
590 self.list.InsertItems([str], i+1)
591 self.list.Check(i+1, ch)
592 self.list.SetSelection(i+1)
593 def OnButtonAppend(self, evt):
594 str = wx.GetTextFromUser('Enter new item:', 'Append', '', self)
595 self.list.Append(str)
596 def OnButtonRemove(self, evt):
597 self.list.Delete(self.list.GetSelection())
598 def OnUpdateUI(self, evt):
599 if evt.GetId() == self.ID_BUTTON_REMOVE:
600 evt.Enable(self.list.GetSelection() != -1)
601 elif evt.GetId() == self.ID_BUTTON_UP:
602 evt.Enable(self.list.GetSelection() > 0)
603 elif evt.GetId() == self.ID_BUTTON_DOWN:
604 evt.Enable(self.list.GetSelection() != -1 and \
605 self.list.GetSelection() < self.list.GetCount() - 1)
606
607 class ParamContent(PPanel):
608 def __init__(self, parent, name):
609 PPanel.__init__(self, parent, name)
610 self.ID_TEXT_CTRL = wx.NewId()
611 self.ID_BUTTON_EDIT = wx.NewId()
612 sizer = wx.BoxSizer()
613 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
614 sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
615 self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
616 sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
617 self.SetSizer(sizer)
618 self.textModified = False
619 wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
620 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
621 def OnChange(self, evt):
622 PPanel.OnChange(self, evt)
623 self.textModified = True
624 def GetValue(self):
625 if self.textModified: # text has newer value
626 try:
627 return self.text.GetValue().split('|')
628 except ValueError:
629 return []
630 return self.value
631 def SetValue(self, value):
632 self.freeze = True
633 if not value: value = []
634 self.value = value
635 repr_ = '|'.join(map(str, value))
636 self.text.SetValue(repr_) # update text ctrl
637 self.freeze = False
638 def OnButtonEdit(self, evt):
639 if self.textModified: # text has newer value
640 self.value = self.GetValue()
641 dlg = ContentDialog(self, self.value)
642 if dlg.ShowModal() == wx.ID_OK:
643 value = []
644 for i in range(dlg.list.GetCount()):
645 value.append(dlg.list.GetString(i))
646 self.SetValue(value)
647 self.SetModified()
648 self.textModified = False
649 dlg.Destroy()
650 def SetModified(self, state=True):
651 PPanel.SetModified(self, state)
652 self.textModified = False
653
654 # CheckList content
655 class ParamContentCheckList(ParamContent):
656 def __init__(self, parent, name):
657 ParamContent.__init__(self, parent, name)
658 def OnButtonEdit(self, evt):
659 if self.textModified: # text has newer value
660 self.value = self.GetValue()
661 dlg = ContentCheckListDialog(self, self.value)
662 if dlg.ShowModal() == wx.ID_OK:
663 value = []
664 for i in range(dlg.list.GetCount()):
665 value.append((dlg.list.GetString(i), int(dlg.list.IsChecked(i))))
666 self.SetValue(value)
667 self.SetModified()
668 self.textModified = False
669 dlg.Destroy()
670 def SetValue(self, value):
671 self.freeze = True
672 if not value: value = []
673 self.value = value
674 repr_ = '|'.join(map(str,value))
675 self.text.SetValue(repr_) # update text ctrl
676 self.freeze = False
677
678 class IntListDialog(wx.Dialog):
679 def __init__(self, parent, value):
680 pre = wx.PreDialog()
681 g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_INTLIST')
682 self.PostCreate(pre)
683 self.list = xrc.XRCCTRL(self, 'LIST')
684 # Set list items
685 value.sort()
686 for v in value:
687 if type(v) != IntType:
688 wx.LogError('Invalid item type')
689 else:
690 self.list.Append(str(v))
691 self.SetAutoLayout(True)
692 self.GetSizer().Fit(self)
693 # Callbacks
694 self.spinCtrl = xrc.XRCCTRL(self, 'SPIN')
695 wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_ADD'), self.OnButtonAdd)
696 self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
697 wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
698 wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_CLEAR'), self.OnButtonClear)
699 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
700 def OnButtonAdd(self, evt):
701 # Check that it's unique
702 try:
703 v = self.spinCtrl.GetValue()
704 s = str(v) # to be sure
705 i = self.list.FindString(s)
706 if i == -1: # ignore non-unique
707 # Find place to insert
708 found = False
709 for i in range(self.list.GetCount()):
710 if int(self.list.GetString(i)) > v:
711 found = True
712 break
713 if found: self.list.InsertItems([s], i)
714 else: self.list.Append(s)
715 except ValueError:
716 wx.LogError('List item is not an int!')
717 def OnButtonRemove(self, evt):
718 self.list.Delete(self.list.GetSelection())
719 def OnButtonClear(self, evt):
720 self.list.Clear()
721 def OnUpdateUI(self, evt):
722 if evt.GetId() == self.ID_BUTTON_REMOVE:
723 evt.Enable(self.list.GetSelection() != -1)
724
725 # For growable list
726 class ParamIntList(ParamContent):
727 def __init__(self, parent, name):
728 ParamContent.__init__(self, parent, name)
729 def OnButtonEdit(self, evt):
730 if self.textModified: # text has newer value
731 try:
732 self.value = map(int, self.text.GetValue().split('|'))
733 except ValueError:
734 self.value = []
735 dlg = IntListDialog(self, self.value)
736 if dlg.ShowModal() == wx.ID_OK:
737 value = []
738 for i in range(dlg.list.GetCount()):
739 value.append(int(dlg.list.GetString(i)))
740 self.SetValue(value)
741 self.SetModified()
742 self.textModified = False
743 dlg.Destroy()
744
745 # Boxless radiobox
746 class RadioBox(PPanel):
747 def __init__(self, parent, id, choices,
748 pos=wx.DefaultPosition, name='radiobox'):
749 PPanel.__init__(self, parent, name)
750 self.choices = choices
751 topSizer = wx.BoxSizer()
752 for i in choices:
753 button = wx.RadioButton(self, -1, i, size=(-1,buttonSize[1]), name=i)
754 topSizer.Add(button, 0, wx.RIGHT, 5)
755 wx.EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice)
756 self.SetSizer(topSizer)
757 def SetStringSelection(self, value):
758 self.freeze = True
759 for i in self.choices:
760 self.FindWindowByName(i).SetValue(i == value)
761 self.value = value
762 self.freeze = False
763 def OnRadioChoice(self, evt):
764 if self.freeze: return
765 if evt.GetSelection():
766 self.value = evt.GetEventObject().GetName()
767 self.SetModified()
768 def GetStringSelection(self):
769 return self.value
770
771 class ParamBool(RadioBox):
772 values = {'yes': '1', 'no': '0'}
773 seulav = {'1': 'yes', '0': 'no'}
774 def __init__(self, parent, name):
775 RadioBox.__init__(self, parent, -1, choices=self.values.keys(), name=name)
776 def GetValue(self):
777 return self.values[self.GetStringSelection()]
778 def SetValue(self, value):
779 if not value: value = '1'
780 self.SetStringSelection(self.seulav[value])
781
782 class ParamOrient(RadioBox):
783 values = {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
784 seulav = {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
785 def __init__(self, parent, name):
786 RadioBox.__init__(self, parent, -1, choices=self.values.keys(), name=name)
787 def GetValue(self):
788 return self.values[self.GetStringSelection()]
789 def SetValue(self, value):
790 if not value: value = 'wxHORIZONTAL'
791 self.SetStringSelection(self.seulav[value])
792
793 class ParamOrientation(RadioBox):
794 values = {'horizontal': 'horizontal', 'vertical': 'vertical'}
795 seulav = {'horizontal': 'horizontal', 'vertical': 'vertical'}
796 def __init__(self, parent, name):
797 RadioBox.__init__(self, parent, -1, choices=self.values.keys(), name=name)
798 def GetValue(self):
799 return self.values[self.GetStringSelection()]
800 def SetValue(self, value):
801 if not value: value = 'vertical'
802 self.SetStringSelection(self.seulav[value])
803
804 class ParamFile(PPanel):
805 def __init__(self, parent, name):
806 PPanel.__init__(self, parent, name)
807 self.ID_TEXT_CTRL = wx.NewId()
808 self.ID_BUTTON_BROWSE = wx.NewId()
809 sizer = wx.BoxSizer()
810 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
811 sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
812 self.button = wx.Button(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize)
813 sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
814 self.SetSizer(sizer)
815 self.textModified = False
816 wx.EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse)
817 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
818 def OnChange(self, evt):
819 PPanel.OnChange(self, evt)
820 self.textModified = True
821 def GetValue(self):
822 if self.textModified: # text has newer value
823 return self.text.GetValue()
824 return self.value
825 def SetValue(self, value):
826 self.freeze = True
827 self.value = value
828 self.text.SetValue(value) # update text ctrl
829 self.freeze = False
830 def OnButtonBrowse(self, evt):
831 if self.textModified: # text has newer value
832 self.value = self.text.GetValue()
833 dlg = wx.FileDialog(self,
834 defaultDir = os.path.abspath(os.path.dirname(self.value)),
835 defaultFile = os.path.basename(self.value))
836 if dlg.ShowModal() == wx.ID_OK:
837 # Get common part of selected path and current
838 if g.frame.dataFile:
839 curpath = os.path.abspath(g.frame.dataFile)
840 else:
841 curpath = os.path.join(os.getcwd(), '')
842 common = os.path.commonprefix([curpath, dlg.GetPath()])
843 self.SetValue(dlg.GetPath()[len(common):])
844 self.SetModified()
845 self.textModified = False
846 dlg.Destroy()
847
848 class ParamBitmap(PPanel):
849 def __init__(self, parent, name):
850 pre = wx.PrePanel()
851 g.frame.res.LoadOnPanel(pre, parent, 'PANEL_BITMAP')
852 self.PostCreate(pre)
853 self.modified = self.freeze = False
854 self.radio_std = xrc.XRCCTRL(self, 'RADIO_STD')
855 self.radio_file = xrc.XRCCTRL(self, 'RADIO_FILE')
856 self.combo = xrc.XRCCTRL(self, 'COMBO_STD')
857 self.text = xrc.XRCCTRL(self, 'TEXT_FILE')
858 self.button = xrc.XRCCTRL(self, 'BUTTON_BROWSE')
859 self.textModified = False
860 self.SetAutoLayout(True)
861 self.GetSizer().SetMinSize((260, -1))
862 self.GetSizer().Fit(self)
863 wx.EVT_RADIOBUTTON(self, xrc.XRCID('RADIO_STD'), self.OnRadioStd)
864 wx.EVT_RADIOBUTTON(self, xrc.XRCID('RADIO_FILE'), self.OnRadioFile)
865 wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_BROWSE'), self.OnButtonBrowse)
866 wx.EVT_COMBOBOX(self, xrc.XRCID('COMBO_STD'), self.OnCombo)
867 wx.EVT_TEXT(self, xrc.XRCID('COMBO_STD'), self.OnChange)
868 wx.EVT_TEXT(self, xrc.XRCID('TEXT_FILE'), self.OnChange)
869 def OnRadioStd(self, evt):
870 self.SetModified()
871 self.SetValue(['wxART_MISSING_IMAGE',''])
872 def OnRadioFile(self, evt):
873 self.SetModified()
874 self.SetValue(['',''])
875 def updateRadios(self):
876 if self.value[0]:
877 self.radio_std.SetValue(True)
878 self.radio_file.SetValue(False)
879 self.text.Enable(False)
880 self.button.Enable(False)
881 self.combo.Enable(True)
882 else:
883 self.radio_std.SetValue(False)
884 self.radio_file.SetValue(True)
885 self.text.Enable(True)
886 self.button.Enable(True)
887 self.combo.Enable(False)
888 def OnChange(self, evt):
889 PPanel.OnChange(self, evt)
890 self.textModified = True
891 def OnCombo(self, evt):
892 PPanel.OnChange(self, evt)
893 self.value[0] = self.combo.GetValue()
894 def GetValue(self):
895 if self.textModified: # text has newer value
896 return [self.combo.GetValue(), self.text.GetValue()]
897 return self.value
898 def SetValue(self, value):
899 self.freeze = True
900 if not value:
901 self.value = ['', '']
902 else:
903 self.value = value
904 self.combo.SetValue(self.value[0])
905 self.text.SetValue(self.value[1]) # update text ctrl
906 self.updateRadios()
907 self.freeze = False
908 def OnButtonBrowse(self, evt):
909 if self.textModified: # text has newer value
910 self.value[1] = self.text.GetValue()
911 dlg = wx.FileDialog(self,
912 defaultDir = os.path.abspath(os.path.dirname(self.value[1])),
913 defaultFile = os.path.basename(self.value[1]))
914 if dlg.ShowModal() == wx.ID_OK:
915 # Get common part of selected path and current
916 if g.frame.dataFile:
917 curpath = os.path.abspath(g.frame.dataFile)
918 else:
919 curpath = os.path.join(os.getcwd(), '')
920 common = os.path.commonprefix([curpath, dlg.GetPath()])
921 self.SetValue(['', dlg.GetPath()[len(common):]])
922 self.SetModified()
923 self.textModified = False
924 dlg.Destroy()
925
926 paramDict = {
927 'flag': ParamFlag,
928 'style': ParamStyle, 'exstyle': ParamExStyle,
929 'pos': ParamPosSize, 'size': ParamPosSize,
930 'cellpos': ParamPosSize, 'cellspan': ParamPosSize,
931 'border': ParamUnit, 'cols': ParamIntNN, 'rows': ParamIntNN,
932 'vgap': ParamUnit, 'hgap': ParamUnit,
933 'checkable': ParamBool, 'checked': ParamBool, 'radio': ParamBool,
934 'accel': ParamAccel,
935 'label': ParamMultilineText, 'title': ParamText, 'value': ParamText,
936 'content': ParamContent, 'selection': ParamIntNN,
937 'min': ParamInt, 'max': ParamInt,
938 'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont,
939 'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool,
940 'tooltip': ParamText, 'bitmap': ParamBitmap, 'icon': ParamBitmap,
941 'encoding': ParamEncoding, 'borders': ParamUnit,
942 'comment': ParamComment
943 }