]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/tools/XRCed/params.py
fixes to move-around methods related to current selection highlight
[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 if not value: value = '0'
401 self.text.SetValue(value)
402 self.Change(0)
403 def Change(self, x):
404 self.freeze = True
405 # Check if we are working with dialog units
406 value = self.text.GetValue()
407 units = ''
408 if value[-1].upper() == 'D':
409 units = value[-1]
410 value = value[:-1]
411 try:
412 intValue = int(value) + x
413 self.spin.SetValue(intValue)
414 if x: # 0 can be passed to update spin value only
415 self.text.SetValue(str(intValue) + units)
416 self.SetModified()
417 except:
418 # !!! Strange, if I use wx.LogWarning, event is re-generated
419 print 'ERROR: incorrect unit format'
420 self.freeze = False
421 def OnSpinUp(self, evt):
422 self.freeze = True
423 self.Change(1)
424 def OnSpinDown(self, evt):
425 if self.freeze: return
426 self.freeze = True
427 self.Change(-1)
428
429 class ParamMultilineText(PPanel):
430 def __init__(self, parent, name, textWidth=-1):
431 PPanel.__init__(self, parent, name)
432 self.ID_TEXT_CTRL = wx.NewId()
433 self.ID_BUTTON_EDIT = wx.NewId()
434 sizer = wx.BoxSizer()
435 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
436 sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
437 self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
438 sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
439 self.SetSizerAndFit(sizer)
440 wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
441 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
442 def GetValue(self):
443 return self.text.GetValue()
444 def SetValue(self, value):
445 self.freeze = True # disable other handlers
446 self.text.SetValue(value)
447 self.freeze = False # disable other handlers
448 def OnButtonEdit(self, evt):
449 dlg = g.frame.res.LoadDialog(self, 'DIALOG_TEXT')
450 textCtrl = xrc.XRCCTRL(dlg, 'TEXT')
451 textCtrl.SetValue(self.text.GetValue())
452 if dlg.ShowModal() == wx.ID_OK:
453 self.text.SetValue(textCtrl.GetValue())
454 self.SetModified()
455 dlg.Destroy()
456
457 class ParamText(PPanel):
458 def __init__(self, parent, name, textWidth=-1, style=0):
459 PPanel.__init__(self, parent, name)
460 self.ID_TEXT_CTRL = wx.NewId()
461 # We use sizer even here to have the same size of text control
462 sizer = wx.BoxSizer()
463 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(textWidth,-1), style=style)
464 if textWidth == -1: option = 1
465 else: option = 0
466 sizer.Add(self.text, option, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2)
467 self.SetSizer(sizer)
468 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
469 def GetValue(self):
470 return self.text.GetValue()
471 def SetValue(self, value):
472 self.freeze = True # disable other handlers
473 self.text.SetValue(value)
474 self.freeze = False # disable other handlers
475
476 class ParamAccel(ParamText):
477 def __init__(self, parent, name):
478 ParamText.__init__(self, parent, name, 100)
479
480 class ParamPosSize(ParamText):
481 def __init__(self, parent, name):
482 ParamText.__init__(self, parent, name, 80)
483
484 class ParamLabel(ParamText):
485 def __init__(self, parent, name):
486 ParamText.__init__(self, parent, name, 200)
487
488 class ParamEncoding(ParamText):
489 def __init__(self, parent, name):
490 ParamText.__init__(self, parent, name, 100)
491
492 class ParamComment(ParamText):
493 def __init__(self, parent, name):
494 ParamText.__init__(self, parent, name, 330 + buttonSize[0],
495 style=wx.TE_PROCESS_ENTER)
496
497 class ContentDialog(wx.Dialog):
498 def __init__(self, parent, value):
499 # Load from resource
500 pre = wx.PreDialog()
501 g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT')
502 self.PostCreate(pre)
503 self.list = xrc.XRCCTRL(self, 'LIST')
504 # Set list items
505 for v in value:
506 self.list.Append(v)
507 self.SetAutoLayout(True)
508 self.GetSizer().Fit(self)
509 # Callbacks
510 self.ID_BUTTON_APPEND = xrc.XRCID('BUTTON_APPEND')
511 self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
512 self.ID_BUTTON_UP = xrc.XRCID('BUTTON_UP')
513 self.ID_BUTTON_DOWN = xrc.XRCID('BUTTON_DOWN')
514 wx.EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
515 wx.EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
516 wx.EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
517 wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
518 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
519 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
520 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
521 def OnButtonUp(self, evt):
522 i = self.list.GetSelection()
523 str = self.list.GetString(i)
524 self.list.Delete(i)
525 self.list.InsertItems([str], i-1)
526 self.list.SetSelection(i-1)
527 def OnButtonDown(self, evt):
528 i = self.list.GetSelection()
529 str = self.list.GetString(i)
530 self.list.Delete(i)
531 self.list.InsertItems([str], i+1)
532 self.list.SetSelection(i+1)
533 def OnButtonAppend(self, evt):
534 str = wx.GetTextFromUser('Enter new item:', 'Append', '', self)
535 self.list.Append(str)
536 def OnButtonRemove(self, evt):
537 self.list.Delete(self.list.GetSelection())
538 def OnUpdateUI(self, evt):
539 if evt.GetId() == self.ID_BUTTON_REMOVE:
540 evt.Enable(self.list.GetSelection() != -1)
541 elif evt.GetId() == self.ID_BUTTON_UP:
542 evt.Enable(self.list.GetSelection() > 0)
543 elif evt.GetId() == self.ID_BUTTON_DOWN:
544 evt.Enable(self.list.GetSelection() != -1 and \
545 self.list.GetSelection() < self.list.GetCount() - 1)
546
547 class ContentCheckListDialog(wx.Dialog):
548 def __init__(self, parent, value):
549 pre = wx.PreDialog()
550 g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT_CHECKLIST')
551 self.PostCreate(pre)
552 self.list = xrc.XRCCTRL(self, 'CHECK_LIST')
553 # Set list items
554 i = 0
555 for v,ch in value:
556 self.list.Append(v)
557 self.list.Check(i, ch)
558 i += 1
559 self.SetAutoLayout(True)
560 self.GetSizer().Fit(self)
561 # Callbacks
562 self.ID_BUTTON_APPEND = xrc.XRCID('BUTTON_APPEND')
563 self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
564 self.ID_BUTTON_UP = xrc.XRCID('BUTTON_UP')
565 self.ID_BUTTON_DOWN = xrc.XRCID('BUTTON_DOWN')
566 wx.EVT_CHECKLISTBOX(self, self.list.GetId(), self.OnCheck)
567 wx.EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
568 wx.EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
569 wx.EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
570 wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
571 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
572 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
573 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
574 def OnCheck(self, evt):
575 # !!! Wrong wxGTK (wxMSW?) behavior: toggling selection if checking
576 self.list.Deselect(evt.GetSelection())
577 def OnButtonUp(self, evt):
578 i = self.list.GetSelection()
579 str, ch = self.list.GetString(i), self.list.IsChecked(i)
580 self.list.Delete(i)
581 self.list.InsertItems([str], i-1)
582 self.list.Check(i-1, ch)
583 self.list.SetSelection(i-1)
584 def OnButtonDown(self, evt):
585 i = self.list.GetSelection()
586 str, ch = self.list.GetString(i), self.list.IsChecked(i)
587 self.list.Delete(i)
588 self.list.InsertItems([str], i+1)
589 self.list.Check(i+1, ch)
590 self.list.SetSelection(i+1)
591 def OnButtonAppend(self, evt):
592 str = wx.GetTextFromUser('Enter new item:', 'Append', '', self)
593 self.list.Append(str)
594 def OnButtonRemove(self, evt):
595 self.list.Delete(self.list.GetSelection())
596 def OnUpdateUI(self, evt):
597 if evt.GetId() == self.ID_BUTTON_REMOVE:
598 evt.Enable(self.list.GetSelection() != -1)
599 elif evt.GetId() == self.ID_BUTTON_UP:
600 evt.Enable(self.list.GetSelection() > 0)
601 elif evt.GetId() == self.ID_BUTTON_DOWN:
602 evt.Enable(self.list.GetSelection() != -1 and \
603 self.list.GetSelection() < self.list.GetCount() - 1)
604
605 class ParamContent(PPanel):
606 def __init__(self, parent, name):
607 PPanel.__init__(self, parent, name)
608 self.ID_TEXT_CTRL = wx.NewId()
609 self.ID_BUTTON_EDIT = wx.NewId()
610 sizer = wx.BoxSizer()
611 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
612 sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
613 self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
614 sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
615 self.SetSizer(sizer)
616 self.textModified = False
617 wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
618 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
619 def OnChange(self, evt):
620 PPanel.OnChange(self, evt)
621 self.textModified = True
622 def GetValue(self):
623 if self.textModified: # text has newer value
624 try:
625 return self.text.GetValue().split('|')
626 except ValueError:
627 return []
628 return self.value
629 def SetValue(self, value):
630 self.freeze = True
631 if not value: value = []
632 self.value = value
633 repr_ = '|'.join(map(str, value))
634 self.text.SetValue(repr_) # update text ctrl
635 self.freeze = False
636 def OnButtonEdit(self, evt):
637 if self.textModified: # text has newer value
638 self.value = self.GetValue()
639 dlg = ContentDialog(self, self.value)
640 if dlg.ShowModal() == wx.ID_OK:
641 value = []
642 for i in range(dlg.list.GetCount()):
643 value.append(dlg.list.GetString(i))
644 self.SetValue(value)
645 self.SetModified()
646 self.textModified = False
647 dlg.Destroy()
648 def SetModified(self, state=True):
649 PPanel.SetModified(self, state)
650 self.textModified = False
651
652 # CheckList content
653 class ParamContentCheckList(ParamContent):
654 def __init__(self, parent, name):
655 ParamContent.__init__(self, parent, name)
656 def OnButtonEdit(self, evt):
657 if self.textModified: # text has newer value
658 self.value = self.GetValue()
659 dlg = ContentCheckListDialog(self, self.value)
660 if dlg.ShowModal() == wx.ID_OK:
661 value = []
662 for i in range(dlg.list.GetCount()):
663 value.append((dlg.list.GetString(i), int(dlg.list.IsChecked(i))))
664 self.SetValue(value)
665 self.SetModified()
666 self.textModified = False
667 dlg.Destroy()
668 def SetValue(self, value):
669 self.freeze = True
670 if not value: value = []
671 self.value = value
672 repr_ = '|'.join(map(str,value))
673 self.text.SetValue(repr_) # update text ctrl
674 self.freeze = False
675
676 class IntListDialog(wx.Dialog):
677 def __init__(self, parent, value):
678 pre = wx.PreDialog()
679 g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_INTLIST')
680 self.PostCreate(pre)
681 self.list = xrc.XRCCTRL(self, 'LIST')
682 # Set list items
683 value.sort()
684 for v in value:
685 if type(v) != IntType:
686 wx.LogError('Invalid item type')
687 else:
688 self.list.Append(str(v))
689 self.SetAutoLayout(True)
690 self.GetSizer().Fit(self)
691 # Callbacks
692 self.spinCtrl = xrc.XRCCTRL(self, 'SPIN')
693 wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_ADD'), self.OnButtonAdd)
694 self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
695 wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
696 wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_CLEAR'), self.OnButtonClear)
697 wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
698 def OnButtonAdd(self, evt):
699 # Check that it's unique
700 try:
701 v = self.spinCtrl.GetValue()
702 s = str(v) # to be sure
703 i = self.list.FindString(s)
704 if i == -1: # ignore non-unique
705 # Find place to insert
706 found = False
707 for i in range(self.list.GetCount()):
708 if int(self.list.GetString(i)) > v:
709 found = True
710 break
711 if found: self.list.InsertItems([s], i)
712 else: self.list.Append(s)
713 except ValueError:
714 wx.LogError('List item is not an int!')
715 def OnButtonRemove(self, evt):
716 self.list.Delete(self.list.GetSelection())
717 def OnButtonClear(self, evt):
718 self.list.Clear()
719 def OnUpdateUI(self, evt):
720 if evt.GetId() == self.ID_BUTTON_REMOVE:
721 evt.Enable(self.list.GetSelection() != -1)
722
723 # For growable list
724 class ParamIntList(ParamContent):
725 def __init__(self, parent, name):
726 ParamContent.__init__(self, parent, name)
727 def OnButtonEdit(self, evt):
728 if self.textModified: # text has newer value
729 try:
730 self.value = map(int, self.text.GetValue().split('|'))
731 except ValueError:
732 self.value = []
733 dlg = IntListDialog(self, self.value)
734 if dlg.ShowModal() == wx.ID_OK:
735 value = []
736 for i in range(dlg.list.GetCount()):
737 value.append(int(dlg.list.GetString(i)))
738 self.SetValue(value)
739 self.SetModified()
740 self.textModified = False
741 dlg.Destroy()
742
743 # Boxless radiobox
744 class RadioBox(PPanel):
745 def __init__(self, parent, id, choices,
746 pos=wx.DefaultPosition, name='radiobox'):
747 PPanel.__init__(self, parent, name)
748 self.choices = choices
749 topSizer = wx.BoxSizer()
750 for i in choices:
751 button = wx.RadioButton(self, -1, i, size=(-1,buttonSize[1]), name=i)
752 topSizer.Add(button, 0, wx.RIGHT, 5)
753 wx.EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice)
754 self.SetSizer(topSizer)
755 def SetStringSelection(self, value):
756 self.freeze = True
757 for i in self.choices:
758 self.FindWindowByName(i).SetValue(i == value)
759 self.value = value
760 self.freeze = False
761 def OnRadioChoice(self, evt):
762 if self.freeze: return
763 if evt.GetSelection():
764 self.value = evt.GetEventObject().GetName()
765 self.SetModified()
766 def GetStringSelection(self):
767 return self.value
768
769 class ParamBool(RadioBox):
770 values = {'yes': '1', 'no': '0'}
771 seulav = {'1': 'yes', '0': 'no'}
772 def __init__(self, parent, name):
773 RadioBox.__init__(self, parent, -1, choices=self.values.keys(), name=name)
774 def GetValue(self):
775 return self.values[self.GetStringSelection()]
776 def SetValue(self, value):
777 if not value: value = '1'
778 self.SetStringSelection(self.seulav[value])
779
780 class ParamOrient(RadioBox):
781 values = {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
782 seulav = {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
783 def __init__(self, parent, name):
784 RadioBox.__init__(self, parent, -1, choices=self.values.keys(), name=name)
785 def GetValue(self):
786 return self.values[self.GetStringSelection()]
787 def SetValue(self, value):
788 if not value: value = 'wxHORIZONTAL'
789 self.SetStringSelection(self.seulav[value])
790
791 class ParamOrientation(RadioBox):
792 values = {'horizontal': 'horizontal', 'vertical': 'vertical'}
793 seulav = {'horizontal': 'horizontal', 'vertical': 'vertical'}
794 def __init__(self, parent, name):
795 RadioBox.__init__(self, parent, -1, choices=self.values.keys(), name=name)
796 def GetValue(self):
797 return self.values[self.GetStringSelection()]
798 def SetValue(self, value):
799 if not value: value = 'vertical'
800 self.SetStringSelection(self.seulav[value])
801
802 class ParamFile(PPanel):
803 def __init__(self, parent, name):
804 PPanel.__init__(self, parent, name)
805 self.ID_TEXT_CTRL = wx.NewId()
806 self.ID_BUTTON_BROWSE = wx.NewId()
807 sizer = wx.BoxSizer()
808 self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
809 sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
810 self.button = wx.Button(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize)
811 sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
812 self.SetSizer(sizer)
813 self.textModified = False
814 wx.EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse)
815 wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
816 def OnChange(self, evt):
817 PPanel.OnChange(self, evt)
818 self.textModified = True
819 def GetValue(self):
820 if self.textModified: # text has newer value
821 return self.text.GetValue()
822 return self.value
823 def SetValue(self, value):
824 self.freeze = True
825 self.value = value
826 self.text.SetValue(value) # update text ctrl
827 self.freeze = False
828 def OnButtonBrowse(self, evt):
829 if self.textModified: # text has newer value
830 self.value = self.text.GetValue()
831 dlg = wx.FileDialog(self,
832 defaultDir = os.path.abspath(os.path.dirname(self.value)),
833 defaultFile = os.path.basename(self.value))
834 if dlg.ShowModal() == wx.ID_OK:
835 # Get common part of selected path and current
836 if g.frame.dataFile:
837 curpath = os.path.abspath(g.frame.dataFile)
838 else:
839 curpath = os.path.join(os.getcwd(), '')
840 common = os.path.commonprefix([curpath, dlg.GetPath()])
841 self.SetValue(dlg.GetPath()[len(common):])
842 self.SetModified()
843 self.textModified = False
844 dlg.Destroy()
845
846 class ParamBitmap(PPanel):
847 def __init__(self, parent, name):
848 pre = wx.PrePanel()
849 g.frame.res.LoadOnPanel(pre, parent, 'PANEL_BITMAP')
850 self.PostCreate(pre)
851 self.modified = self.freeze = False
852 self.radio_std = xrc.XRCCTRL(self, 'RADIO_STD')
853 self.radio_file = xrc.XRCCTRL(self, 'RADIO_FILE')
854 self.combo = xrc.XRCCTRL(self, 'COMBO_STD')
855 self.text = xrc.XRCCTRL(self, 'TEXT_FILE')
856 self.button = xrc.XRCCTRL(self, 'BUTTON_BROWSE')
857 self.textModified = False
858 self.SetAutoLayout(True)
859 self.GetSizer().SetMinSize((260, -1))
860 self.GetSizer().Fit(self)
861 wx.EVT_RADIOBUTTON(self, xrc.XRCID('RADIO_STD'), self.OnRadioStd)
862 wx.EVT_RADIOBUTTON(self, xrc.XRCID('RADIO_FILE'), self.OnRadioFile)
863 wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_BROWSE'), self.OnButtonBrowse)
864 wx.EVT_COMBOBOX(self, xrc.XRCID('COMBO_STD'), self.OnCombo)
865 wx.EVT_TEXT(self, xrc.XRCID('COMBO_STD'), self.OnChange)
866 wx.EVT_TEXT(self, xrc.XRCID('TEXT_FILE'), self.OnChange)
867 def OnRadioStd(self, evt):
868 self.SetModified()
869 self.SetValue(['wxART_MISSING_IMAGE',''])
870 def OnRadioFile(self, evt):
871 self.SetModified()
872 self.SetValue(['',''])
873 def updateRadios(self):
874 if self.value[0]:
875 self.radio_std.SetValue(True)
876 self.radio_file.SetValue(False)
877 self.text.Enable(False)
878 self.button.Enable(False)
879 self.combo.Enable(True)
880 else:
881 self.radio_std.SetValue(False)
882 self.radio_file.SetValue(True)
883 self.text.Enable(True)
884 self.button.Enable(True)
885 self.combo.Enable(False)
886 def OnChange(self, evt):
887 PPanel.OnChange(self, evt)
888 self.textModified = True
889 def OnCombo(self, evt):
890 PPanel.OnChange(self, evt)
891 self.value[0] = self.combo.GetValue()
892 def GetValue(self):
893 if self.textModified: # text has newer value
894 return [self.combo.GetValue(), self.text.GetValue()]
895 return self.value
896 def SetValue(self, value):
897 self.freeze = True
898 if not value:
899 self.value = ['', '']
900 else:
901 self.value = value
902 self.combo.SetValue(self.value[0])
903 self.text.SetValue(self.value[1]) # update text ctrl
904 self.updateRadios()
905 self.freeze = False
906 def OnButtonBrowse(self, evt):
907 if self.textModified: # text has newer value
908 self.value[1] = self.text.GetValue()
909 dlg = wx.FileDialog(self,
910 defaultDir = os.path.abspath(os.path.dirname(self.value[1])),
911 defaultFile = os.path.basename(self.value[1]))
912 if dlg.ShowModal() == wx.ID_OK:
913 # Get common part of selected path and current
914 if g.frame.dataFile:
915 curpath = os.path.abspath(g.frame.dataFile)
916 else:
917 curpath = os.path.join(os.getcwd(), '')
918 common = os.path.commonprefix([curpath, dlg.GetPath()])
919 self.SetValue(['', dlg.GetPath()[len(common):]])
920 self.SetModified()
921 self.textModified = False
922 dlg.Destroy()
923
924 paramDict = {
925 'flag': ParamFlag,
926 'style': ParamStyle, 'exstyle': ParamExStyle,
927 'pos': ParamPosSize, 'size': ParamPosSize,
928 'cellpos': ParamPosSize, 'cellspan': ParamPosSize,
929 'border': ParamUnit, 'cols': ParamIntNN, 'rows': ParamIntNN,
930 'vgap': ParamUnit, 'hgap': ParamUnit,
931 'checkable': ParamBool, 'checked': ParamBool, 'radio': ParamBool,
932 'accel': ParamAccel,
933 'label': ParamMultilineText, 'title': ParamText, 'value': ParamText,
934 'content': ParamContent, 'selection': ParamIntNN,
935 'min': ParamInt, 'max': ParamInt,
936 'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont,
937 'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool,
938 'tooltip': ParamText, 'bitmap': ParamBitmap, 'icon': ParamBitmap,
939 'encoding': ParamEncoding, 'borders': ParamUnit,
940 'comment': ParamComment
941 }