2 # Purpose: Classes for parameter introduction
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
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'
20 'wxWS_EX_VALIDATE_RECURSIVELY',
21 'wxWS_EX_BLOCK_EVENTS',
23 'wxFRAME_EX_CONTEXTHELP',
24 'wxWS_EX_PROCESS_IDLE',
25 'wxWS_EX_PROCESS_UI_UPDATES'
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
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
):
41 # Something strange is going on with enable so we make sure...
42 for w
in self
.GetChildren():
44 #wx.Panel.Enable(self, value)
45 def SetModified(self
, state
=True):
47 if state
: g
.panel
.SetModified(True)
48 # Common method to set modified state
49 def OnChange(self
, evt
):
50 if self
.freeze
: return
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()
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
)
69 return self
.text
.GetValue()
70 def SetValue(self
, value
):
72 self
.text
.SetValue(value
)
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
= []
86 listBox
.Check(self
.values
.index(i
))
89 if self
.equal
.has_key(i
):
90 listBox
.Check(self
.values
.index(self
.equal
[i
]))
92 print 'WARNING: unknown flag: %s: ignored.' % i
94 if dlg
.ShowModal() == wx
.ID_OK
:
96 for i
in range(listBox
.GetCount()):
97 if listBox
.IsChecked(i
):
98 value
.append(self
.values
[i
])
100 value
.extend(ignored
)
101 self
.SetValue('|'.join(value
))
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'
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
)
121 class ParamNonGenericStyle(ParamBinaryOr
):
122 def __init__(self
, parent
, name
):
123 self
.values
= g
.currentXXX
.winStyles
124 ParamBinaryOr
.__init
__(self
, parent
, name
)
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
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
)
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
150 listBoxSpecific
.Check(self
.valuesSpecific
.index(i
))
153 if self
.equal
.has_key(i
):
154 listBoxSpecific
.Check(self
.valuesSpecific
.index(self
.equal
[i
]))
158 # Set generic styles, collect non-standart values
161 listBoxGeneric
.Check(self
.valuesGeneric
.index(i
))
164 if self
.equal
.has_key(i
):
165 listBoxGeneric
.Check(self
.valuesGeneric
.index(self
.equal
[i
]))
167 print 'WARNING: unknown flag: %s: ignored.' % 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
))
180 class ParamExStyle(ParamBinaryOr
):
181 def __init__(self
, parent
, name
):
183 self
.values
= g
.currentXXX
.exStyles
+ genericExStyles
186 ParamBinaryOr
.__init
__(self
, parent
, name
)
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)
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
)
204 return self
.text
.GetValue()
205 def SetValue(self
, value
):
207 if not value
: value
= '#FFFFFF'
208 self
.text
.SetValue(str(value
)) # update text ctrl
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
214 self
.button
.Refresh()
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())
232 ################################################################################
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',
238 fontStylesWx2Xml
= {wx.NORMAL: 'normal', wx.SLANT: 'slant', wx.ITALIC: 'italic'}
239 fontWeightsWx2Xml
= {wx.NORMAL: 'normal', wx.LIGHT: 'light', wx.BOLD: 'bold'}
242 for k
,v
in m
.items(): rm
[v
] = k
244 fontFamiliesXml2wx
= ReverseMap(fontFamiliesWx2Xml
)
245 fontStylesXml2wx
= ReverseMap(fontStylesWx2Xml
)
246 fontWeightsXml2wx
= ReverseMap(fontWeightsWx2Xml
)
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
)
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', '', '']
268 if self
.textModified
: # text has newer value
270 return eval(self
.text
.GetValue())
272 wx
.LogError('Syntax error in parameter value: ' + self
.GetName())
273 return self
._defaultValue
()
275 def SetValue(self
, value
):
276 self
.freeze
= True # disable other handlers
277 if not value
: value
= self
._defaultValue
()
279 self
.text
.SetValue(str(value
)) # update text ctrl
281 def OnButtonSelect(self
, evt
):
282 if self
.textModified
: # text has newer value
284 self
.value
= eval(self
.text
.GetValue())
286 wx
.LogError('Syntax error in parameter value: ' + self
.GetName())
287 self
.value
= self
._defaultValue
()
290 size
= g
._sysFont
.GetPointSize()
292 style
= weight
= wx
.NORMAL
295 enc
= wx
.FONTENCODING_DEFAULT
296 # Fall back to default if exceptions
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')
312 mapper
= wx
.FontMapper()
313 if not self
.value
[6]: enc
= mapper
.CharsetToEncoding(self
.value
[6])
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
)
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
:
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(),
337 self
.textModified
= False
340 ################################################################################
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
351 wx
.EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
)
353 return str(self
.spin
.GetValue())
354 def SetValue(self
, value
):
356 if not value
: value
= 0
357 self
.spin
.SetValue(int(value
))
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
370 wx
.EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
)
372 return str(self
.spin
.GetValue())
373 def SetValue(self
, value
):
375 if not value
: value
= 0
376 self
.spin
.SetValue(int(value
))
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
)
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
)
398 return self
.text
.GetValue()
399 def SetValue(self
, value
):
401 if not value
: value
= '0'
402 self
.text
.SetValue(value
)
407 # Check if we are working with dialog units
408 value
= self
.text
.GetValue()
410 if value
[-1].upper() == 'D':
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
)
420 # !!! Strange, if I use wx.LogWarning, event is re-generated
421 print 'ERROR: incorrect unit format'
423 def OnSpinUp(self
, evt
):
426 def OnSpinDown(self
, evt
):
427 if self
.freeze
: return
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
)
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())
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
468 sizer
.Add(self
.text
, option
, wx
.ALIGN_CENTER_VERTICAL | wx
.TOP | wx
.BOTTOM
, 2)
470 wx
.EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
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
478 class ParamAccel(ParamText
):
479 def __init__(self
, parent
, name
):
480 ParamText
.__init
__(self
, parent
, name
, 100)
482 class ParamPosSize(ParamText
):
483 def __init__(self
, parent
, name
):
484 ParamText
.__init
__(self
, parent
, name
, 80)
486 class ParamLabel(ParamText
):
487 def __init__(self
, parent
, name
):
488 ParamText
.__init
__(self
, parent
, name
, 200)
490 class ParamEncoding(ParamText
):
491 def __init__(self
, parent
, name
):
492 ParamText
.__init
__(self
, parent
, name
, 100)
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
)
499 class ContentDialog(wx
.Dialog
):
500 def __init__(self
, parent
, value
):
503 g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT')
505 self
.list = xrc
.XRCCTRL(self
, 'LIST')
509 self
.SetAutoLayout(True)
510 self
.GetSizer().Fit(self
)
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
)
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
)
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)
549 class ContentCheckListDialog(wx
.Dialog
):
550 def __init__(self
, parent
, value
):
552 g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT_CHECKLIST')
554 self
.list = xrc
.XRCCTRL(self
, 'CHECK_LIST')
559 self
.list.Check(i
, ch
)
561 self
.SetAutoLayout(True)
562 self
.GetSizer().Fit(self
)
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
)
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
)
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)
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
)
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
625 if self
.textModified
: # text has newer value
627 return self
.text
.GetValue().split('|')
631 def SetValue(self
, value
):
633 if not value
: value
= []
635 repr_
= '|'.join(map(str, value
))
636 self
.text
.SetValue(repr_
) # update text ctrl
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
:
644 for i
in range(dlg
.list.GetCount()):
645 value
.append(dlg
.list.GetString(i
))
648 self
.textModified
= False
650 def SetModified(self
, state
=True):
651 PPanel
.SetModified(self
, state
)
652 self
.textModified
= False
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
:
664 for i
in range(dlg
.list.GetCount()):
665 value
.append((dlg
.list.GetString(i
), int(dlg
.list.IsChecked(i
))))
668 self
.textModified
= False
670 def SetValue(self
, value
):
672 if not value
: value
= []
674 repr_
= '|'.join(map(str,value
))
675 self
.text
.SetValue(repr_
) # update text ctrl
678 class IntListDialog(wx
.Dialog
):
679 def __init__(self
, parent
, value
):
681 g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_INTLIST')
683 self
.list = xrc
.XRCCTRL(self
, 'LIST')
687 if type(v
) != IntType
:
688 wx
.LogError('Invalid item type')
690 self
.list.Append(str(v
))
691 self
.SetAutoLayout(True)
692 self
.GetSizer().Fit(self
)
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
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
709 for i
in range(self
.list.GetCount()):
710 if int(self
.list.GetString(i
)) > v
:
713 if found
: self
.list.InsertItems([s
], i
)
714 else: self
.list.Append(s
)
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
):
721 def OnUpdateUI(self
, evt
):
722 if evt
.GetId() == self
.ID_BUTTON_REMOVE
:
723 evt
.Enable(self
.list.GetSelection() != -1)
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
732 self
.value
= map(int, self
.text
.GetValue().split('|'))
735 dlg
= IntListDialog(self
, self
.value
)
736 if dlg
.ShowModal() == wx
.ID_OK
:
738 for i
in range(dlg
.list.GetCount()):
739 value
.append(int(dlg
.list.GetString(i
)))
742 self
.textModified
= False
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()
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
):
759 for i
in self
.choices
:
760 self
.FindWindowByName(i
).SetValue(i
== value
)
763 def OnRadioChoice(self
, evt
):
764 if self
.freeze
: return
765 if evt
.GetSelection():
766 self
.value
= evt
.GetEventObject().GetName()
768 def GetStringSelection(self
):
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
)
777 return self
.values
[self
.GetStringSelection()]
778 def SetValue(self
, value
):
779 if not value
: value
= '1'
780 self
.SetStringSelection(self
.seulav
[value
])
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
)
788 return self
.values
[self
.GetStringSelection()]
789 def SetValue(self
, value
):
790 if not value
: value
= 'wxHORIZONTAL'
791 self
.SetStringSelection(self
.seulav
[value
])
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
)
799 return self
.values
[self
.GetStringSelection()]
800 def SetValue(self
, value
):
801 if not value
: value
= 'vertical'
802 self
.SetStringSelection(self
.seulav
[value
])
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
)
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
822 if self
.textModified
: # text has newer value
823 return self
.text
.GetValue()
825 def SetValue(self
, value
):
828 self
.text
.SetValue(value
) # update text ctrl
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
839 curpath
= os
.path
.abspath(g
.frame
.dataFile
)
841 curpath
= os
.path
.join(os
.getcwd(), '')
842 common
= os
.path
.commonprefix([curpath
, dlg
.GetPath()])
843 self
.SetValue(dlg
.GetPath()[len(common
):])
845 self
.textModified
= False
848 class ParamBitmap(PPanel
):
849 def __init__(self
, parent
, name
):
851 g
.frame
.res
.LoadOnPanel(pre
, parent
, 'PANEL_BITMAP')
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
):
871 self
.SetValue(['wxART_MISSING_IMAGE',''])
872 def OnRadioFile(self
, evt
):
874 self
.SetValue(['',''])
875 def updateRadios(self
):
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)
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()
895 if self
.textModified
: # text has newer value
896 return [self
.combo
.GetValue(), self
.text
.GetValue()]
898 def SetValue(self
, value
):
901 self
.value
= ['', '']
904 self
.combo
.SetValue(self
.value
[0])
905 self
.text
.SetValue(self
.value
[1]) # update text ctrl
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
917 curpath
= os
.path
.abspath(g
.frame
.dataFile
)
919 curpath
= os
.path
.join(os
.getcwd(), '')
920 common
= os
.path
.commonprefix([curpath
, dlg
.GetPath()])
921 self
.SetValue(['', dlg
.GetPath()[len(common
):]])
923 self
.textModified
= False
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
,
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