2 # Purpose: Classes for parameter introduction
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
11 from wxPython
.xrc
import *
14 'wxSIMPLE_BORDER', 'wxDOUBLE_BORDER', 'wxSUNKEN_BORDER',
15 'wxRAISED_BORDER', 'wxSTATIC_BORDER', 'wxNO_BORDER',
16 'wxTRANSPARENT_WINDOW', 'wxTAB_TRAVERSAL',
18 'wxNO_FULL_REPAINT_ON_RESIZE',
19 'wxVSCROLL', 'wxHSCROLL', 'wxALWAYS_SHOW_SB',
21 'wxFULL_REPAINT_ON_RESIZE'
25 'wxWS_EX_VALIDATE_RECURSIVELY',
26 'wxWS_EX_BLOCK_EVENTS',
28 'wxFRAME_EX_CONTEXTHELP',
29 'wxWS_EX_PROCESS_IDLE',
30 'wxWS_EX_PROCESS_UI_UPDATES'
33 buttonSize
= (35,-1) # in dialog units, transformed to pixels in panel ctor
35 # Class that can properly disable children
36 class PPanel(wxPanel
):
37 def __init__(self
, parent
, name
):
38 wxPanel
.__init
__(self
, parent
, -1, name
=name
)
39 self
.modified
= self
.freeze
= False
40 def Enable(self
, value
):
41 # Something strange is going on with enable so we make sure...
42 for w
in self
.GetChildren():
44 wxPanel
.Enable(self
, value
)
45 def SetModified(self
):
47 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
= wxNewId()
58 self
.ID_BUTTON_CHOICES
= wxNewId()
60 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1))
61 sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5)
62 self
.button
= wxButton(self
, self
.ID_BUTTON_CHOICES
, 'Edit...', size
=buttonSize
)
63 sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
)
64 self
.SetAutoLayout(True)
67 EVT_BUTTON(self
, self
.ID_BUTTON_CHOICES
, self
.OnButtonChoices
)
68 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
70 return self
.text
.GetValue()
71 def SetValue(self
, value
):
73 self
.text
.SetValue(value
)
75 def OnButtonChoices(self
, evt
):
76 dlg
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_CHOICES')
77 if self
.GetName() == 'flag': dlg
.SetTitle('Sizer item flags')
78 elif self
.GetName() == 'style': dlg
.SetTitle('Window styles')
79 elif self
.GetName() == 'exstyle': dlg
.SetTitle('Extended window styles')
80 listBox
= XRCCTRL(dlg
, 'CHECKLIST')
81 listBox
.InsertItems(self
.values
, 0)
82 value
= map(string
.strip
, self
.text
.GetValue().split('|'))
83 if value
== ['']: value
= []
87 listBox
.Check(self
.values
.index(i
))
90 if self
.equal
.has_key(i
):
91 listBox
.Check(self
.values
.index(self
.equal
[i
]))
93 print 'WARNING: unknown flag: %s: ignored.' % i
95 if dlg
.ShowModal() == wxID_OK
:
97 for i
in range(listBox
.GetCount()):
98 if listBox
.IsChecked(i
):
99 value
.append(self
.values
[i
])
101 value
.extend(ignored
)
103 self
.SetValue(reduce(lambda a
,b
: a
+'|'+b
, value
))
109 class ParamFlag(ParamBinaryOr
):
110 values
= ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL',
111 'wxEXPAND', 'wxGROW', 'wxSHAPED', 'wxALIGN_CENTRE', 'wxALIGN_RIGHT',
113 'wxALIGN_BOTTOM', 'wxALIGN_CENTRE_VERTICAL',
114 'wxALIGN_CENTRE_HORIZONTAL',
116 equal
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE',
117 'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL',
118 'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL'}
119 def __init__(self
, parent
, name
):
120 ParamBinaryOr
.__init
__(self
, parent
, name
)
122 class ParamNonGenericStyle(ParamBinaryOr
):
123 def __init__(self
, parent
, name
):
124 self
.values
= g
.currentXXX
.winStyles
125 ParamBinaryOr
.__init
__(self
, parent
, name
)
127 class ParamStyle(ParamBinaryOr
):
128 equal
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
129 def __init__(self
, parent
, name
):
130 ParamBinaryOr
.__init
__(self
, parent
, name
)
131 self
.valuesSpecific
= g
.currentXXX
.winStyles
132 if self
.valuesSpecific
: # override if using specific styles
134 self
.valuesGeneric
= [s
for s
in genericStyles
135 if s
not in self
.valuesSpecific
]
136 EVT_BUTTON(self
, self
.ID_BUTTON_CHOICES
, self
.OnButtonChoicesBoth
)
138 self
.values
= genericStyles
139 def OnButtonChoicesBoth(self
, evt
):
140 dlg
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_STYLES')
141 listBoxSpecific
= XRCCTRL(dlg
, 'CHECKLIST_SPECIFIC')
142 listBoxSpecific
.InsertItems(self
.valuesSpecific
, 0)
143 listBoxGeneric
= XRCCTRL(dlg
, 'CHECKLIST_GENERIC')
144 listBoxGeneric
.InsertItems(self
.valuesGeneric
, 0)
145 value
= map(string
.strip
, self
.text
.GetValue().split('|'))
146 if value
== ['']: value
= []
147 # Set specific styles
148 value2
= [] # collect generic and ignored here
151 listBoxSpecific
.Check(self
.valuesSpecific
.index(i
))
154 if self
.equal
.has_key(i
):
155 listBoxSpecific
.Check(self
.valuesSpecific
.index(self
.equal
[i
]))
159 # Set generic styles, collect non-standart values
162 listBoxGeneric
.Check(self
.valuesGeneric
.index(i
))
165 if self
.equal
.has_key(i
):
166 listBoxGeneric
.Check(self
.valuesGeneric
.index(self
.equal
[i
]))
168 print 'WARNING: unknown flag: %s: ignored.' % i
170 if dlg
.ShowModal() == wxID_OK
:
171 value
= [self
.valuesSpecific
[i
]
172 for i
in range(listBoxSpecific
.GetCount())
173 if listBoxSpecific
.IsChecked(i
)] + \
174 [self
.valuesGeneric
[i
]
175 for i
in range(listBoxGeneric
.GetCount())
176 if listBoxGeneric
.IsChecked(i
)] + ignored
178 self
.SetValue(reduce(lambda a
,b
: a
+'|'+b
, value
))
184 class ParamExStyle(ParamBinaryOr
):
185 def __init__(self
, parent
, name
):
187 self
.values
= g
.currentXXX
.exStyles
+ genericExStyles
190 ParamBinaryOr
.__init
__(self
, parent
, name
)
191 self
.SetTitle('Extended window styles')
193 class ParamColour(PPanel
):
194 def __init__(self
, parent
, name
):
195 PPanel
.__init
__(self
, parent
, name
)
196 self
.ID_TEXT_CTRL
= wxNewId()
197 self
.ID_BUTTON
= wxNewId()
199 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(65,-1))
200 sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5)
201 self
.button
= wxPanel(self
, self
.ID_BUTTON
, wxDefaultPosition
, wxSize(20, 1))
202 sizer
.Add(self
.button
, 0, wxGROW | wxALIGN_CENTER_VERTICAL
)
203 self
.SetAutoLayout(True)
206 self
.textModified
= False
207 EVT_PAINT(self
.button
, self
.OnPaintButton
)
208 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
209 EVT_LEFT_DOWN(self
.button
, self
.OnLeftDown
)
211 return self
.text
.GetValue()
212 def SetValue(self
, value
):
214 if not value
: value
= '#FFFFFF'
215 self
.text
.SetValue(str(value
)) # update text ctrl
216 colour
= wxColour(int(value
[1:3], 16), int(value
[3:5], 16), int(value
[5:7], 16))
217 self
.button
.SetBackgroundColour(colour
)
218 self
.button
.Refresh()
220 def OnPaintButton(self
, evt
):
221 dc
= wxPaintDC(self
.button
)
222 dc
.SetBrush(wxTRANSPARENT_BRUSH
)
223 if self
.IsEnabled(): dc
.SetPen(wxBLACK_PEN
)
224 else: dc
.SetPen(wxGREY_PEN
)
225 size
= self
.button
.GetSize()
226 dc
.DrawRectangle(0, 0, size
.width
, size
.height
)
227 def OnLeftDown(self
, evt
):
228 data
= wxColourData()
229 data
.SetColour(self
.GetValue())
230 dlg
= wxColourDialog(self
, data
)
231 if dlg
.ShowModal() == wxID_OK
:
232 self
.SetValue('#%02X%02X%02X' % dlg
.GetColourData().GetColour().Get())
236 ################################################################################
238 # Mapping from wx constants ro XML strings
239 fontFamiliesWx2Xml
= {wxDEFAULT
: 'default', wxDECORATIVE
: 'decorative',
240 wxROMAN
: 'roman', wxSCRIPT
: 'script', wxSWISS
: 'swiss',
242 fontStylesWx2Xml
= {wxNORMAL: 'normal', wxSLANT: 'slant', wxITALIC: 'italic'}
243 fontWeightsWx2Xml
= {wxNORMAL: 'normal', wxLIGHT: 'light', wxBOLD: 'bold'}
246 for k
,v
in m
.items(): rm
[v
] = k
248 fontFamiliesXml2wx
= ReverseMap(fontFamiliesWx2Xml
)
249 fontStylesXml2wx
= ReverseMap(fontStylesWx2Xml
)
250 fontWeightsXml2wx
= ReverseMap(fontWeightsWx2Xml
)
252 class ParamFont(PPanel
):
253 def __init__(self
, parent
, name
):
254 PPanel
.__init
__(self
, parent
, name
)
255 self
.ID_TEXT_CTRL
= wxNewId()
256 self
.ID_BUTTON_SELECT
= wxNewId()
258 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(200,-1))
259 sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5)
260 self
.button
= wxButton(self
, self
.ID_BUTTON_SELECT
, 'Select...', size
=buttonSize
)
261 sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
)
262 self
.SetAutoLayout(True)
265 self
.textModified
= False
266 EVT_BUTTON(self
, self
.ID_BUTTON_SELECT
, self
.OnButtonSelect
)
267 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
268 def OnChange(self
, evt
):
269 PPanel
.OnChange(self
, evt
)
270 self
.textModified
= True
271 def _defaultValue(self
):
272 return ['12', 'default', 'normal', 'normal', '0', '', '']
274 if self
.textModified
: # text has newer value
276 return eval(self
.text
.GetValue())
278 wxLogError('Syntax error in parameter value: ' + self
.GetName())
279 return self
._defaultValue
()
281 def SetValue(self
, value
):
282 self
.freeze
= True # disable other handlers
283 if not value
: value
= self
._defaultValue
()
285 self
.text
.SetValue(str(value
)) # update text ctrl
287 def OnButtonSelect(self
, evt
):
288 if self
.textModified
: # text has newer value
290 self
.value
= eval(self
.text
.GetValue())
292 wxLogError('Syntax error in parameter value: ' + self
.GetName())
293 self
.value
= self
._defaultValue
()
298 style
= weight
= wxNORMAL
301 enc
= wxFONTENCODING_DEFAULT
302 # Fall back to default if exceptions
305 try: size
= int(self
.value
[0])
306 except ValueError: error
= True; wxLogError('Invalid size specification')
307 try: family
= fontFamiliesXml2wx
[self
.value
[1]]
308 except KeyError: error
= True; wxLogError('Invalid family specification')
309 try: style
= fontStylesXml2wx
[self
.value
[2]]
310 except KeyError: error
= True; wxLogError('Invalid style specification')
311 try: weight
= fontWeightsXml2wx
[self
.value
[3]]
312 except KeyError: error
= True; wxLogError('Invalid weight specification')
313 try: underlined
= bool(self
.value
[4])
314 except ValueError: error
= True; wxLogError('Invalid underlined flag specification')
318 mapper
= wxFontMapper()
319 if not self
.value
[6]: enc
= mapper
.CharsetToEncoding(self
.value
[6])
321 if error
: wxLogError('Invalid font specification')
322 if enc
== wxFONTENCODING_DEFAULT
: enc
= wxFONTENCODING_SYSTEM
323 font
= wxFont(size
, family
, style
, weight
, underlined
, face
, enc
)
325 data
.SetInitialFont(font
)
326 dlg
= wxFontDialog(self
, data
)
327 if dlg
.ShowModal() == wxID_OK
:
328 font
= dlg
.GetFontData().GetChosenFont()
329 print font
.GetEncoding()
330 if font
.GetEncoding() == wxFONTENCODING_SYSTEM
:
333 encName
= wxFontMapper_GetEncodingName(font
.GetEncoding()).encode()
334 value
= [str(font
.GetPointSize()),
335 fontFamiliesWx2Xml
.get(font
.GetFamily(), "default"),
336 fontStylesWx2Xml
.get(font
.GetStyle(), "normal"),
337 fontWeightsWx2Xml
.get(font
.GetWeight(), "normal"),
338 str(int(font
.GetUnderlined())),
339 font
.GetFaceName().encode(),
344 self
.textModified
= False
347 ################################################################################
349 class ParamInt(PPanel
):
350 def __init__(self
, parent
, name
):
351 PPanel
.__init
__(self
, parent
, name
)
352 self
.ID_SPIN_CTRL
= wxNewId()
354 self
.spin
= wxSpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=(60,-1))
355 self
.spin
.SetRange(-2147483648, 2147483647) # min/max integers
357 self
.SetAutoLayout(True)
360 EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
)
362 return str(self
.spin
.GetValue())
363 def SetValue(self
, value
):
365 if not value
: value
= 0
366 self
.spin
.SetValue(int(value
))
369 # Non-negative number
370 class ParamIntNN(PPanel
):
371 def __init__(self
, parent
, name
):
372 PPanel
.__init
__(self
, parent
, name
)
373 self
.ID_SPIN_CTRL
= wxNewId()
375 self
.spin
= wxSpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=(60,-1))
376 self
.spin
.SetRange(0, 10000) # min/max integers
378 self
.SetAutoLayout(True)
381 EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
)
383 return str(self
.spin
.GetValue())
384 def SetValue(self
, value
):
386 if not value
: value
= 0
387 self
.spin
.SetValue(int(value
))
390 # Same as int but allows dialog units (XXXd)
391 class ParamUnit(PPanel
):
392 def __init__(self
, parent
, name
):
393 PPanel
.__init
__(self
, parent
, name
)
394 self
.ID_TEXT_CTRL
= wxNewId()
395 self
.ID_SPIN_BUTTON
= wxNewId()
396 sizer
= wxBoxSizer(wxHORIZONTAL
)
397 self
.spin
= wxSpinButton(self
, self
.ID_SPIN_BUTTON
, style
= wxSP_VERTICAL
, size
=(-1,1))
398 textW
= 60 - self
.spin
.GetSize()[0]
399 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=(textW
,-1))
400 self
.spin
.SetRange(-10000, 10000)
401 sizer
.Add(self
.text
, 0, wxEXPAND
)
402 sizer
.Add(self
.spin
, 0, wxEXPAND
)
403 #sizer.SetMinSize((50,-1))
404 self
.SetAutoLayout(True)
407 EVT_SPIN_UP(self
, self
.ID_SPIN_BUTTON
, self
.OnSpinUp
)
408 EVT_SPIN_DOWN(self
, self
.ID_SPIN_BUTTON
, self
.OnSpinDown
)
410 return self
.text
.GetValue()
411 def SetValue(self
, value
):
413 if not value
: value
= '0'
414 self
.text
.SetValue(value
)
417 # Check if we are working with dialog units
418 value
= self
.text
.GetValue()
420 if value
[-1].upper() == 'D':
424 intValue
= int(value
) + x
425 self
.spin
.SetValue(intValue
)
426 self
.text
.SetValue(str(intValue
) + units
)
429 # !!! Strange, if I use wxLogWarning, event is re-generated
430 print 'incorrect unit format'
431 def OnSpinUp(self
, evt
):
433 def OnSpinDown(self
, evt
):
436 class ParamMultilineText(PPanel
):
437 def __init__(self
, parent
, name
, textWidth
=-1):
438 PPanel
.__init
__(self
, parent
, name
)
439 self
.ID_TEXT_CTRL
= wxNewId()
440 self
.ID_BUTTON_EDIT
= wxNewId()
442 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1))
443 sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5)
444 self
.button
= wxButton(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
)
445 sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
)
446 self
.SetAutoLayout(True)
449 EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
)
450 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
452 return self
.text
.GetValue()
453 def SetValue(self
, value
):
454 self
.freeze
= True # disable other handlers
455 self
.text
.SetValue(value
)
456 self
.freeze
= False # disable other handlers
457 def OnButtonEdit(self
, evt
):
458 dlg
= g
.frame
.res
.LoadDialog(self
, 'DIALOG_TEXT')
459 textCtrl
= XRCCTRL(dlg
, 'TEXT')
460 textCtrl
.SetValue(self
.text
.GetValue())
461 if dlg
.ShowModal() == wxID_OK
:
462 self
.text
.SetValue(textCtrl
.GetValue())
466 class ParamText(PPanel
):
467 def __init__(self
, parent
, name
, textWidth
=-1):
468 PPanel
.__init
__(self
, parent
, name
)
469 self
.ID_TEXT_CTRL
= wxNewId()
470 # We use sizer even here to have the same size of text control
472 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(textWidth
,-1))
473 if textWidth
== -1: option
= 1
475 sizer
.Add(self
.text
, option
, wxALIGN_CENTER_VERTICAL
)
476 self
.SetAutoLayout(True)
479 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
481 return self
.text
.GetValue()
482 def SetValue(self
, value
):
483 self
.freeze
= True # disable other handlers
484 self
.text
.SetValue(value
)
485 self
.freeze
= False # disable other handlers
487 class ParamAccel(ParamText
):
488 def __init__(self
, parent
, name
):
489 ParamText
.__init
__(self
, parent
, name
, 100)
491 class ParamPosSize(ParamText
):
492 def __init__(self
, parent
, name
):
493 ParamText
.__init
__(self
, parent
, name
, 80)
495 class ParamLabel(ParamText
):
496 def __init__(self
, parent
, name
):
497 ParamText
.__init
__(self
, parent
, name
, 200)
499 class ParamEncoding(ParamText
):
500 def __init__(self
, parent
, name
):
501 ParamText
.__init
__(self
, parent
, name
, 100)
503 class ContentDialog(wxDialog
):
504 def __init__(self
, parent
, value
):
507 g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT')
509 self
._setOORInfo
(self
)
510 self
.list = XRCCTRL(self
, 'LIST')
514 self
.SetAutoLayout(True)
515 self
.GetSizer().Fit(self
)
517 self
.ID_BUTTON_APPEND
= XRCID('BUTTON_APPEND')
518 self
.ID_BUTTON_REMOVE
= XRCID('BUTTON_REMOVE')
519 self
.ID_BUTTON_UP
= XRCID('BUTTON_UP')
520 self
.ID_BUTTON_DOWN
= XRCID('BUTTON_DOWN')
521 EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
)
522 EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
)
523 EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
)
524 EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
)
525 EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
)
526 EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
)
527 EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
)
528 def OnButtonUp(self
, evt
):
529 i
= self
.list.GetSelection()
530 str = self
.list.GetString(i
)
532 self
.list.InsertItems([str], i
-1)
533 self
.list.SetSelection(i
-1)
534 def OnButtonDown(self
, evt
):
535 i
= self
.list.GetSelection()
536 str = self
.list.GetString(i
)
538 self
.list.InsertItems([str], i
+1)
539 self
.list.SetSelection(i
+1)
540 def OnButtonAppend(self
, evt
):
541 str = wxGetTextFromUser('Enter new item:', 'Append', '', self
)
542 self
.list.Append(str)
543 def OnButtonRemove(self
, evt
):
544 self
.list.Delete(self
.list.GetSelection())
545 def OnUpdateUI(self
, evt
):
546 if evt
.GetId() == self
.ID_BUTTON_REMOVE
:
547 evt
.Enable(self
.list.GetSelection() != -1)
548 elif evt
.GetId() == self
.ID_BUTTON_UP
:
549 evt
.Enable(self
.list.GetSelection() > 0)
550 elif evt
.GetId() == self
.ID_BUTTON_DOWN
:
551 evt
.Enable(self
.list.GetSelection() != -1 and \
552 self
.list.GetSelection() < self
.list.GetCount() - 1)
554 class ContentCheckListDialog(wxDialog
):
555 def __init__(self
, parent
, value
):
557 g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_CONTENT_CHECKLIST')
559 self
._setOORInfo
(self
)
560 self
.list = XRCCTRL(self
, 'CHECKLIST')
565 self
.list.Check(i
, ch
)
567 self
.SetAutoLayout(True)
568 self
.GetSizer().Fit(self
)
570 self
.ID_BUTTON_APPEND
= XRCID('BUTTON_APPEND')
571 self
.ID_BUTTON_REMOVE
= XRCID('BUTTON_REMOVE')
572 self
.ID_BUTTON_UP
= XRCID('BUTTON_UP')
573 self
.ID_BUTTON_DOWN
= XRCID('BUTTON_DOWN')
574 EVT_CHECKLISTBOX(self
, self
.list.GetId(), self
.OnCheck
)
575 EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
)
576 EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
)
577 EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
)
578 EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
)
579 EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
)
580 EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
)
581 EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
)
582 def OnCheck(self
, evt
):
583 # !!! Wrong wxGTK (wxMSW?) behavior: toggling selection if checking
584 self
.list.Deselect(evt
.GetSelection())
585 def OnButtonUp(self
, evt
):
586 i
= self
.list.GetSelection()
587 str, ch
= self
.list.GetString(i
), self
.list.IsChecked(i
)
589 self
.list.InsertItems([str], i
-1)
590 self
.list.Check(i
-1, ch
)
591 self
.list.SetSelection(i
-1)
592 def OnButtonDown(self
, evt
):
593 i
= self
.list.GetSelection()
594 str, ch
= self
.list.GetString(i
), self
.list.IsChecked(i
)
596 self
.list.InsertItems([str], i
+1)
597 self
.list.Check(i
+1, ch
)
598 self
.list.SetSelection(i
+1)
599 def OnButtonAppend(self
, evt
):
600 str = wxGetTextFromUser('Enter new item:', 'Append', '', self
)
601 self
.list.Append(str)
602 def OnButtonRemove(self
, evt
):
603 self
.list.Delete(self
.list.GetSelection())
604 def OnUpdateUI(self
, evt
):
605 if evt
.GetId() == self
.ID_BUTTON_REMOVE
:
606 evt
.Enable(self
.list.GetSelection() != -1)
607 elif evt
.GetId() == self
.ID_BUTTON_UP
:
608 evt
.Enable(self
.list.GetSelection() > 0)
609 elif evt
.GetId() == self
.ID_BUTTON_DOWN
:
610 evt
.Enable(self
.list.GetSelection() != -1 and \
611 self
.list.GetSelection() < self
.list.GetCount() - 1)
613 class ParamContent(PPanel
):
614 def __init__(self
, parent
, name
):
615 PPanel
.__init
__(self
, parent
, name
)
616 self
.ID_TEXT_CTRL
= wxNewId()
617 self
.ID_BUTTON_EDIT
= wxNewId()
619 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1))
620 sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5)
621 self
.button
= wxButton(self
, self
.ID_BUTTON_EDIT
, 'Edit...', size
=buttonSize
)
622 sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
)
623 self
.SetAutoLayout(True)
626 self
.textModified
= False
627 EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
)
628 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
629 def OnChange(self
, evt
):
630 PPanel
.OnChange(self
, evt
)
631 self
.textModified
= True
633 if self
.textModified
: # text has newer value
635 return eval(self
.text
.GetValue())
637 wxLogError('Syntax error in parameter value: ' + self
.GetName())
640 def SetValue(self
, value
):
642 if not value
: value
= []
644 self
.text
.SetValue(str(value
)) # update text ctrl
646 def OnButtonEdit(self
, evt
):
647 if self
.textModified
: # text has newer value
649 self
.value
= eval(self
.text
.GetValue())
651 wxLogError('Syntax error in parameter value: ' + self
.GetName())
653 dlg
= ContentDialog(self
, self
.value
)
654 if dlg
.ShowModal() == wxID_OK
:
656 for i
in range(dlg
.list.GetCount()):
657 value
.append(dlg
.list.GetString(i
))
660 self
.textModified
= False
664 class ParamContentCheckList(ParamContent
):
665 def __init__(self
, parent
, name
):
666 ParamContent
.__init
__(self
, parent
, name
)
667 def OnButtonEdit(self
, evt
):
668 if self
.textModified
: # text has newer value
670 self
.value
= eval(self
.text
.GetValue())
672 wxLogError('Syntax error in parameter value: ' + self
.GetName())
674 dlg
= ContentCheckListDialog(self
, self
.value
)
675 if dlg
.ShowModal() == wxID_OK
:
677 for i
in range(dlg
.list.GetCount()):
678 value
.append((dlg
.list.GetString(i
), int(dlg
.list.IsChecked(i
))))
681 self
.textModified
= False
684 class IntListDialog(wxDialog
):
685 def __init__(self
, parent
, value
):
687 g
.frame
.res
.LoadOnDialog(pre
, parent
, 'DIALOG_INTLIST')
689 self
._setOORInfo
(self
)
690 self
.list = XRCCTRL(self
, 'LIST')
694 if type(v
) != IntType
:
695 wxLogError('Invalid item type')
697 self
.list.Append(str(v
))
698 self
.SetAutoLayout(True)
699 self
.GetSizer().Fit(self
)
701 self
.spinCtrl
= XRCCTRL(self
, 'SPIN')
702 EVT_BUTTON(self
, XRCID('BUTTON_ADD'), self
.OnButtonAdd
)
703 self
.ID_BUTTON_REMOVE
= XRCID('BUTTON_REMOVE')
704 EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
)
705 EVT_BUTTON(self
, XRCID('BUTTON_CLEAR'), self
.OnButtonClear
)
706 EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
)
707 def OnButtonAdd(self
, evt
):
708 # Check that it's unique
710 v
= self
.spinCtrl
.GetValue()
711 s
= str(v
) # to be sure
712 i
= self
.list.FindString(s
)
713 if i
== -1: # ignore non-unique
714 # Find place to insert
716 for i
in range(self
.list.GetCount()):
717 if int(self
.list.GetString(i
)) > v
:
720 if found
: self
.list.InsertItems([s
], i
)
721 else: self
.list.Append(s
)
723 wxLogError('List item is not an int!')
724 def OnButtonRemove(self
, evt
):
725 self
.list.Delete(self
.list.GetSelection())
726 def OnButtonClear(self
, evt
):
728 def OnUpdateUI(self
, evt
):
729 if evt
.GetId() == self
.ID_BUTTON_REMOVE
:
730 evt
.Enable(self
.list.GetSelection() != -1)
733 class ParamIntList(ParamContent
):
734 def __init__(self
, parent
, name
):
735 ParamContent
.__init
__(self
, parent
, name
)
736 def OnButtonEdit(self
, evt
):
737 if self
.textModified
: # text has newer value
739 self
.value
= eval(self
.text
.GetValue())
741 wxLogError('Syntax error in parameter value: ' + self
.GetName())
743 dlg
= IntListDialog(self
, self
.value
)
744 if dlg
.ShowModal() == wxID_OK
:
746 for i
in range(dlg
.list.GetCount()):
747 value
.append(int(dlg
.list.GetString(i
)))
750 self
.textModified
= False
754 class RadioBox(PPanel
):
755 def __init__(self
, parent
, id, choices
,
756 pos
=wxDefaultPosition
, name
='radiobox'):
757 PPanel
.__init
__(self
, parent
, name
)
758 self
.choices
= choices
759 topSizer
= wxBoxSizer()
761 button
= wxRadioButton(self
, -1, i
, size
=(-1,buttonSize
[1]), name
=i
)
762 topSizer
.Add(button
, 0, wxRIGHT
, 5)
763 EVT_RADIOBUTTON(self
, button
.GetId(), self
.OnRadioChoice
)
764 self
.SetAutoLayout(True)
765 self
.SetSizer(topSizer
)
767 def SetStringSelection(self
, value
):
769 for i
in self
.choices
:
770 self
.FindWindowByName(i
).SetValue(i
== value
)
773 def OnRadioChoice(self
, evt
):
774 if self
.freeze
: return
775 if evt
.GetSelection():
776 self
.value
= evt
.GetEventObject().GetName()
778 def GetStringSelection(self
):
781 class ParamBool(RadioBox
):
782 values
= {'yes': '1', 'no': '0'}
783 seulav
= {'1': 'yes', '0': 'no'}
784 def __init__(self
, parent
, name
):
785 RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
)
787 return self
.values
[self
.GetStringSelection()]
788 def SetValue(self
, value
):
789 if not value
: value
= '1'
790 self
.SetStringSelection(self
.seulav
[value
])
792 class ParamOrient(RadioBox
):
793 values
= {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
794 seulav
= {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
795 def __init__(self
, parent
, name
):
796 RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
)
798 return self
.values
[self
.GetStringSelection()]
799 def SetValue(self
, value
):
800 if not value
: value
= 'wxHORIZONTAL'
801 self
.SetStringSelection(self
.seulav
[value
])
803 class ParamOrientation(RadioBox
):
804 values
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
805 seulav
= {'horizontal': 'horizontal', 'vertical': 'vertical'}
806 def __init__(self
, parent
, name
):
807 RadioBox
.__init
__(self
, parent
, -1, choices
=self
.values
.keys(), name
=name
)
809 return self
.values
[self
.GetStringSelection()]
810 def SetValue(self
, value
):
811 if not value
: value
= 'vertical'
812 self
.SetStringSelection(self
.seulav
[value
])
814 class ParamFile(PPanel
):
815 def __init__(self
, parent
, name
):
816 PPanel
.__init
__(self
, parent
, name
)
817 self
.ID_TEXT_CTRL
= wxNewId()
818 self
.ID_BUTTON_BROWSE
= wxNewId()
820 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1))
821 sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 5)
822 self
.button
= wxButton(self
, self
.ID_BUTTON_BROWSE
, 'Browse...',size
=buttonSize
)
823 sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
)
824 self
.SetAutoLayout(True)
827 self
.textModified
= False
828 EVT_BUTTON(self
, self
.ID_BUTTON_BROWSE
, self
.OnButtonBrowse
)
829 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
830 def OnChange(self
, evt
):
831 PPanel
.OnChange(self
, evt
)
832 self
.textModified
= True
834 if self
.textModified
: # text has newer value
835 return self
.text
.GetValue()
837 def SetValue(self
, value
):
840 self
.text
.SetValue(value
) # update text ctrl
842 def OnButtonBrowse(self
, evt
):
843 if self
.textModified
: # text has newer value
844 self
.value
= self
.text
.GetValue()
845 dlg
= wxFileDialog(self
,
846 defaultDir
= os
.path
.abspath(os
.path
.dirname(self
.value
)),
847 defaultFile
= os
.path
.basename(self
.value
))
848 if dlg
.ShowModal() == wxID_OK
:
849 # Get common part of selected path and current
851 curpath
= os
.path
.abspath(g
.frame
.dataFile
)
853 curpath
= os
.path
.join(os
.getcwd(), '')
854 common
= os
.path
.commonprefix([curpath
, dlg
.GetPath()])
855 self
.SetValue(dlg
.GetPath()[len(common
):])
857 self
.textModified
= False
860 class ParamBitmap(PPanel
):
861 def __init__(self
, parent
, name
):
863 g
.frame
.res
.LoadOnPanel(pre
, parent
, 'PANEL_BITMAP')
865 self
._setOORInfo
(self
)
866 self
.modified
= self
.freeze
= False
867 self
.radio_std
= XRCCTRL(self
, 'RADIO_STD')
868 self
.radio_file
= XRCCTRL(self
, 'RADIO_FILE')
869 self
.combo
= XRCCTRL(self
, 'COMBO_STD')
870 self
.text
= XRCCTRL(self
, 'TEXT_FILE')
871 self
.button
= XRCCTRL(self
, 'BUTTON_BROWSE')
872 self
.textModified
= False
873 self
.SetAutoLayout(True)
874 self
.GetSizer().SetMinSize((260, -1))
875 self
.GetSizer().Fit(self
)
876 EVT_RADIOBUTTON(self
, XRCID('RADIO_STD'), self
.OnRadioStd
)
877 EVT_RADIOBUTTON(self
, XRCID('RADIO_FILE'), self
.OnRadioFile
)
878 EVT_BUTTON(self
, XRCID('BUTTON_BROWSE'), self
.OnButtonBrowse
)
879 EVT_COMBOBOX(self
, XRCID('COMBO_STD'), self
.OnCombo
)
880 EVT_TEXT(self
, XRCID('COMBO_STD'), self
.OnChange
)
881 EVT_TEXT(self
, XRCID('TEXT_FILE'), self
.OnChange
)
882 def OnRadioStd(self
, evt
):
884 self
.SetValue(['wxART_MISSING_IMAGE',''])
885 def OnRadioFile(self
, evt
):
887 self
.SetValue(['',''])
888 def updateRadios(self
):
890 self
.radio_std
.SetValue(True)
891 self
.radio_file
.SetValue(False)
892 self
.text
.Enable(False)
893 self
.button
.Enable(False)
894 self
.combo
.Enable(True)
896 self
.radio_std
.SetValue(False)
897 self
.radio_file
.SetValue(True)
898 self
.text
.Enable(True)
899 self
.button
.Enable(True)
900 self
.combo
.Enable(False)
901 def OnChange(self
, evt
):
902 PPanel
.OnChange(self
, evt
)
903 self
.textModified
= True
904 def OnCombo(self
, evt
):
905 PPanel
.OnChange(self
, evt
)
906 self
.value
[0] = self
.combo
.GetValue()
908 if self
.textModified
: # text has newer value
909 return [self
.combo
.GetValue(), self
.text
.GetValue()]
911 def SetValue(self
, value
):
914 self
.value
= ['', '']
917 self
.combo
.SetValue(self
.value
[0])
918 self
.text
.SetValue(self
.value
[1]) # update text ctrl
921 def OnButtonBrowse(self
, evt
):
922 if self
.textModified
: # text has newer value
923 self
.value
[1] = self
.text
.GetValue()
924 dlg
= wxFileDialog(self
,
925 defaultDir
= os
.path
.abspath(os
.path
.dirname(self
.value
[1])),
926 defaultFile
= os
.path
.basename(self
.value
[1]))
927 if dlg
.ShowModal() == wxID_OK
:
928 # Get common part of selected path and current
930 curpath
= os
.path
.abspath(g
.frame
.dataFile
)
932 curpath
= os
.path
.join(os
.getcwd(), '')
933 common
= os
.path
.commonprefix([curpath
, dlg
.GetPath()])
934 self
.SetValue(['', dlg
.GetPath()[len(common
):]])
936 self
.textModified
= False
941 'style': ParamStyle
, 'exstyle': ParamExStyle
,
942 'pos': ParamPosSize
, 'size': ParamPosSize
,
943 'cellpos': ParamPosSize
, 'cellspan': ParamPosSize
,
944 'border': ParamUnit
, 'cols': ParamIntNN
, 'rows': ParamIntNN
,
945 'vgap': ParamUnit
, 'hgap': ParamUnit
,
946 'checkable': ParamBool
, 'checked': ParamBool
, 'radio': ParamBool
,
948 'label': ParamMultilineText
, 'title': ParamText
, 'value': ParamText
,
949 'content': ParamContent
, 'selection': ParamIntNN
,
950 'min': ParamInt
, 'max': ParamInt
,
951 'fg': ParamColour
, 'bg': ParamColour
, 'font': ParamFont
,
952 'enabled': ParamBool
, 'focused': ParamBool
, 'hidden': ParamBool
,
953 'tooltip': ParamText
, 'bitmap': ParamBitmap
, 'icon': ParamBitmap
,
954 'encoding': ParamEncoding