2 # Purpose: Classes for parameter introduction
3 # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
7 from wxPython
.wx
import *
8 from wxPython
.xrc
import *
12 # Object which is currently processed
14 def SetCurrentXXX(xxx
):
18 genericStyles
= ['wxSIMPLE_BORDER', 'wxDOUBLE_BORDER',
19 'wxSUNKEN_BORDER', 'wxRAISED_BORDER',
20 'wxSTATIC_BORDER', 'wxNO_BORDER',
21 'wxTRANSPARENT_WINDOW', 'wxWANTS_CHARS',
22 'wxNO_FULL_REPAINT_ON_RESIZE']
24 # Class that can properly disable children
25 class PPanel(wxPanel
):
26 def __init__(self
, parent
, id, name
):
27 wxPanel
.__init
__(self
, parent
, id, name
=name
)
28 self
.modified
= self
.freeze
= false
29 def Enable(self
, value
):
30 # Something strange is going on with enable so we make sure...
31 for w
in self
.GetChildren():
33 wxPanel
.Enable(self
, value
)
34 def SetModified(self
):
36 panel
.SetModified(true
)
38 class ParamBinaryOr(PPanel
):
39 def __init__(self
, parent
, id, size
, name
):
40 PPanel
.__init
__(self
, parent
, id, name
)
41 self
.ID_TEXT_CTRL
= wxNewId()
42 self
.ID_BUTTON_CHOICES
= wxNewId()
43 self
.SetBackgroundColour(panel
.GetBackgroundColour())
45 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1))
46 sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 10)
47 self
.button
= wxButton(self
, self
.ID_BUTTON_CHOICES
, 'Edit...')
48 sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
)
49 self
.SetAutoLayout(true
)
52 EVT_BUTTON(self
, self
.ID_BUTTON_CHOICES
, self
.OnButtonChoices
)
53 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
54 def OnChange(self
, evt
):
55 if self
.freeze
: return
59 return self
.text
.GetValue()
60 def SetValue(self
, value
):
62 self
.text
.SetValue(value
)
64 def OnButtonChoices(self
, evt
):
65 dlg
= wxDialog(self
, -1, 'Choices')
66 topSizer
= wxBoxSizer(wxVERTICAL
)
67 listBox
= wxCheckListBox(dlg
, -1, choices
=self
.values
, size
=(250,200))
68 value
= map(string
.strip
, string
.split(self
.text
.GetValue(), '|'))
69 if value
== ['']: value
= []
73 listBox
.Check(self
.values
.index(i
))
76 if self
.equal
.has_key(i
):
77 listBox
.Check(self
.values
.index(self
.equal
[i
]))
79 print 'WARNING: unknown flag: %s: ignored.' % i
81 topSizer
.Add(listBox
, 1, wxEXPAND
)
83 buttonOk
= wxButton(dlg
, wxID_OK
, 'OK')
85 sizer
.Add(buttonOk
, 0, wxRIGHT
, 10)
87 sizer
.Add(wxButton(dlg
, wxID_CANCEL
, 'Cancel'))
88 topSizer
.Add(sizer
, 0, wxALL | wxEXPAND
, 10)
89 dlg
.SetAutoLayout(true
)
90 dlg
.SetSizer(topSizer
)
93 if dlg
.ShowModal() == wxID_OK
:
95 for i
in range(listBox
.Number()):
96 if listBox
.IsChecked(i
):
97 value
.append(self
.values
[i
])
100 self
.SetValue(reduce(lambda a
,b
: a
+'|'+b
, value
))
104 class ParamFlag(ParamBinaryOr
):
105 values
= ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL',
106 'wxEXPAND', 'wxSHAPED', 'wxALIGN_CENTRE', 'wxALIGN_RIGHT',
107 'wxALIGN_BOTTOM', 'wxALIGN_CENTRE_VERTICAL',
108 'wxALIGN_CENTRE_HORIZONTAL']
109 equal
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE',
110 'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL',
111 'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL'}
112 def __init__(self
, parent
, id, size
, name
):
113 ParamBinaryOr
.__init
__(self
, parent
, id, size
, name
)
115 class ParamStyle(ParamBinaryOr
):
116 equal
= {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
117 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
118 self
.values
= currentXXX
.winStyles
+ genericStyles
119 ParamBinaryOr
.__init
__(self
, parent
, id, size
, name
)
121 class ParamNonGenericStyle(ParamBinaryOr
):
122 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
123 self
.values
= currentXXX
.winStyles
124 ParamBinaryOr
.__init
__(self
, parent
, id, size
, name
)
126 class ParamExStyle(ParamBinaryOr
):
127 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
129 self
.values
= currentXXX
.exStyles
# constant at the moment
132 ParamBinaryOr
.__init
__(self
, parent
, id, size
, name
)
134 class ParamColour(PPanel
):
135 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
136 PPanel
.__init
__(self
, parent
, id, name
)
137 self
.ID_TEXT_CTRL
= wxNewId()
138 self
.ID_BUTTON
= wxNewId()
139 self
.SetBackgroundColour(panel
.GetBackgroundColour())
141 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(60,-1))
142 sizer
.Add(self
.text
, 0, wxRIGHT
, 10)
143 self
.button
= wxPanel(self
, self
.ID_BUTTON
, wxDefaultPosition
, wxSize(40, -1))
144 sizer
.Add(self
.button
, 0, wxGROW
)
145 self
.SetAutoLayout(true
)
148 self
.textModified
= false
149 EVT_PAINT(self
.button
, self
.OnPaintButton
)
150 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
151 EVT_LEFT_DOWN(self
.button
, self
.OnLeftDown
)
154 def SetValue(self
, value
):
156 value
= string
.strip(value
)
157 if not value
: value
= '#FFFFFF'
159 self
.text
.SetValue(str(value
)) # update text ctrl
160 colour
= wxColour(int(value
[1:3], 16), int(value
[3:5], 16), int(value
[5:7], 16))
161 self
.button
.SetBackgroundColour(colour
)
162 self
.button
.Refresh()
164 def OnChange(self
, evt
):
165 if self
.freeze
: return
167 self
.textModified
= true
169 def OnPaintButton(self
, evt
):
170 dc
= wxPaintDC(self
.button
)
171 dc
.SetBrush(wxTRANSPARENT_BRUSH
)
172 if self
.IsEnabled(): dc
.SetPen(wxBLACK_PEN
)
173 else: dc
.SetPen(wxGREY_PEN
)
174 size
= self
.button
.GetSize()
175 dc
.DrawRectangle(0, 0, size
.x
, size
.y
)
176 def OnLeftDown(self
, evt
):
177 dlg
= wxColourDialog(self
)
178 if dlg
.ShowModal() == wxID_OK
:
179 self
.SetValue('#%02X%02X%02X' % dlg
.GetColourData().GetColour().Get())
181 self
.textModified
= false
184 ################################################################################
186 # Mapping from wx constants ro XML strings
187 fontFamiliesWx2Xml
= {wxDEFAULT
: 'default', wxDECORATIVE
: 'decorative',
188 wxROMAN
: 'roman', wxSCRIPT
: 'script', wxSWISS
: 'swiss',
190 fontStylesWx2Xml
= {wxNORMAL: 'normal', wxSLANT: 'slant', wxITALIC: 'italic'}
191 fontWeightsWx2Xml
= {wxNORMAL: 'normal', wxLIGHT: 'light', wxBOLD: 'bold'}
194 for k
,v
in m
.items(): rm
[v
] = k
196 fontFamiliesXml2wx
= ReverseMap(fontFamiliesWx2Xml
)
197 fontStylesXml2wx
= ReverseMap(fontStylesWx2Xml
)
198 fontWeightsXml2wx
= ReverseMap(fontWeightsWx2Xml
)
200 class ParamFont(PPanel
):
201 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
202 PPanel
.__init
__(self
, parent
, id, name
)
203 self
.ID_TEXT_CTRL
= wxNewId()
204 self
.ID_BUTTON_SELECT
= wxNewId()
205 self
.SetBackgroundColour(panel
.GetBackgroundColour())
207 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1))
208 sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 10)
209 self
.button
= wxButton(self
, self
.ID_BUTTON_SELECT
, 'Select...')
210 sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
)
211 self
.SetAutoLayout(true
)
214 self
.textModified
= false
215 EVT_BUTTON(self
, self
.ID_BUTTON_SELECT
, self
.OnButtonSelect
)
216 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
217 def OnChange(self
, evt
):
218 if self
.freeze
: return
220 self
.textModified
= true
223 if self
.textModified
: # text has newer value
224 return eval(self
.text
.GetValue())
226 def SetValue(self
, value
):
227 self
.freeze
= true
# disable other handlers
228 if not value
: value
= [''] * 7
230 self
.text
.SetValue(str(value
)) # update text ctrl
232 def OnButtonSelect(self
, evt
):
233 if self
.textModified
: # text has newer value
234 self
.value
= eval(self
.text
.GetValue())
236 try: size
= int(self
.value
[0])
237 except ValueError: size
= 12
238 try: family
= fontFamiliesXml2wx
[self
.value
[1]]
239 except KeyError: family
= wxDEFAULT
240 try: style
= fontStylesXml2wx
[self
.value
[2]]
241 except KeyError: style
= wxNORMAL
242 try: weight
= fontWeightsXml2wx
[self
.value
[3]]
243 except KeyError: weight
= wxNORMAL
244 try: underlined
= int(self
.value
[4])
245 except ValueError: underlined
= 0
247 mapper
= wxFontMapper()
248 enc
= wxFONTENCODING_DEFAULT
249 if not self
.value
[6]: enc
= mapper
.CharsetToEncoding(self
.value
[6])
250 if enc
== wxFONTENCODING_DEFAULT
: enc
= wxFONTENCODING_SYSTEM
251 font
= wxFont(size
, family
, style
, weight
, underlined
, face
, enc
)
253 data
.SetInitialFont(font
)
254 dlg
= wxFontDialog(self
, data
)
255 if dlg
.ShowModal() == wxID_OK
:
256 font
= dlg
.GetFontData().GetChosenFont()
257 value
= [str(font
.GetPointSize()), fontFamiliesWx2Xml
[font
.GetFamily()],
258 fontStylesWx2Xml
[font
.GetStyle()],
259 fontWeightsWx2Xml
[font
.GetWeight()],
260 str(font
.GetUnderlined()), font
.GetFaceName(),
261 wxFontMapper_GetEncodingName(font
.GetEncoding())]
265 self
.textModified
= false
268 ################################################################################
270 class ParamInt(PPanel
):
271 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
272 PPanel
.__init
__(self
, parent
, id, name
)
273 self
.ID_SPIN_CTRL
= wxNewId()
275 self
.spin
= wxSpinCtrl(self
, self
.ID_SPIN_CTRL
, size
=wxSize(50,-1))
276 self
.SetBackgroundColour(panel
.GetBackgroundColour())
278 self
.SetAutoLayout(true
)
281 EVT_SPINCTRL(self
, self
.ID_SPIN_CTRL
, self
.OnChange
)
283 return str(self
.spin
.GetValue())
284 def SetValue(self
, value
):
286 value
= string
.strip(value
)
287 if not value
: value
= 0
288 self
.spin
.SetValue(int(value
))
290 def OnChange(self
, evt
):
291 if self
.freeze
: return
295 class ParamText(PPanel
):
296 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= '', textWidth
=200):
297 PPanel
.__init
__(self
, parent
, id, name
)
298 self
.ID_TEXT_CTRL
= wxNewId()
299 # We use sizer even here to have the same size of text control
301 self
.SetBackgroundColour(panel
.GetBackgroundColour())
302 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(textWidth
,-1))
303 sizer
.Add(self
.text
, 0, wxALIGN_CENTER_VERTICAL
)
304 self
.SetAutoLayout(true
)
307 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
309 return self
.text
.GetValue()
310 def SetValue(self
, value
):
311 self
.freeze
= true
# disable other handlers
312 self
.text
.SetValue(value
)
313 self
.freeze
= false
# disable other handlers
314 def OnChange(self
, evt
):
315 if self
.freeze
: return
319 class ParamAccel(ParamText
):
320 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
321 ParamText
.__init
__(self
, parent
, id, size
, name
, 50)
323 class ParamPosSize(ParamText
):
324 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
325 ParamText
.__init
__(self
, parent
, id, size
, name
, 80)
327 class ContentDialog(wxDialog
):
328 def __init__(self
, parent
, value
):
330 # Use another constructor
331 w
= frame
.res
.LoadDialog(parent
, 'ID_DIALOG_CONTENT')
335 #frame.res.LoadOnDialog(self, parent, 'ID_DIALOG_CONTENT')
337 self
.list = self
.FindWindowByName('ID_LIST')
341 self
.SetAutoLayout(true
)
342 # !!! self.SetSizer(sizer)
343 self
.GetSizer().Fit(self
)
345 self
.ID_BUTTON_APPEND
= XMLID('ID_BUTTON_APPEND')
346 self
.ID_BUTTON_REMOVE
= XMLID('ID_BUTTON_REMOVE')
347 self
.ID_BUTTON_UP
= XMLID('ID_BUTTON_UP')
348 self
.ID_BUTTON_DOWN
= XMLID('ID_BUTTON_DOWN')
349 EVT_BUTTON(self
, self
.ID_BUTTON_UP
, self
.OnButtonUp
)
350 EVT_BUTTON(self
, self
.ID_BUTTON_DOWN
, self
.OnButtonDown
)
351 EVT_BUTTON(self
, self
.ID_BUTTON_APPEND
, self
.OnButtonAppend
)
352 EVT_BUTTON(self
, self
.ID_BUTTON_REMOVE
, self
.OnButtonRemove
)
353 EVT_UPDATE_UI(self
, self
.ID_BUTTON_UP
, self
.OnUpdateUI
)
354 EVT_UPDATE_UI(self
, self
.ID_BUTTON_DOWN
, self
.OnUpdateUI
)
355 EVT_UPDATE_UI(self
, self
.ID_BUTTON_REMOVE
, self
.OnUpdateUI
)
356 def OnButtonUp(self
, evt
):
357 i
= self
.list.GetSelection()
358 str = self
.list.GetString(i
)
360 self
.list.InsertItems([str], i
-1)
361 self
.list.SetSelection(i
-1)
362 def OnButtonDown(self
, evt
):
363 i
= self
.list.GetSelection()
364 str = self
.list.GetString(i
)
366 self
.list.InsertItems([str], i
+1)
367 self
.list.SetSelection(i
+1)
368 def OnButtonAppend(self
, evt
):
369 str = wxGetTextFromUser('Enter new item:', 'Append', '', self
)
370 self
.list.Append(str)
371 def OnButtonRemove(self
, evt
):
372 self
.list.Delete(self
.list.GetSelection())
373 def OnUpdateUI(self
, evt
):
374 if evt
.GetId() == self
.ID_BUTTON_REMOVE
:
375 evt
.Enable(self
.list.GetSelection() != -1)
376 elif evt
.GetId() == self
.ID_BUTTON_UP
:
377 evt
.Enable(self
.list.GetSelection() > 0)
378 elif evt
.GetId() == self
.ID_BUTTON_DOWN
:
379 evt
.Enable(self
.list.GetSelection() != -1 and \
380 self
.list.GetSelection() < self
.list.Number() - 1)
382 class ParamContent(PPanel
):
383 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
384 PPanel
.__init
__(self
, parent
, id, name
)
385 self
.ID_TEXT_CTRL
= wxNewId()
386 self
.ID_BUTTON_EDIT
= wxNewId()
387 self
.SetBackgroundColour(panel
.GetBackgroundColour())
389 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1))
390 sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 10)
391 self
.button
= wxButton(self
, self
.ID_BUTTON_EDIT
, 'Edit...')
392 sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
)
393 self
.SetAutoLayout(true
)
396 self
.textModified
= false
397 EVT_BUTTON(self
, self
.ID_BUTTON_EDIT
, self
.OnButtonEdit
)
398 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
399 def OnChange(self
, evt
):
400 if self
.freeze
: return
402 self
.textModified
= true
405 if self
.textModified
: # text has newer value
406 return eval(self
.text
.GetValue())
408 def SetValue(self
, value
):
411 self
.text
.SetValue(str(value
)) # update text ctrl
413 def OnButtonEdit(self
, evt
):
414 if self
.textModified
: # text has newer value
415 self
.value
= eval(self
.text
.GetValue())
416 dlg
= ContentDialog(self
, self
.value
)
417 if dlg
.ShowModal() == wxID_OK
:
419 for i
in range(dlg
.list.Number()):
420 value
.append(dlg
.list.GetString(i
))
424 self
.textModified
= false
428 class RadioBox(PPanel
):
429 def __init__(self
, parent
, id, choices
,
430 pos
=wxDefaultPosition
, size
=wxDefaultSize
, name
='radiobox'):
431 PPanel
.__init
__(self
, parent
, id, name
)
432 self
.SetBackgroundColour(panel
.GetBackgroundColour())
433 self
.choices
= choices
434 topSizer
= wxBoxSizer()
436 button
= wxRadioButton(self
, -1, i
, name
=i
)
438 EVT_RADIOBUTTON(self
, button
.GetId(), self
.OnRadioChoice
)
439 self
.SetAutoLayout(true
)
440 self
.SetSizer(topSizer
)
442 def SetStringSelection(self
, value
):
444 for i
in self
.choices
:
445 self
.FindWindowByName(i
).SetValue(i
== value
)
448 def OnRadioChoice(self
, evt
):
449 if self
.freeze
: return
450 if evt
.GetSelection():
451 self
.value
= evt
.GetEventObject().GetName()
453 def GetStringSelection(self
):
456 class ParamBool(RadioBox
):
457 values
= {'yes': '1', 'no': '0'}
458 seulav
= {'1': 'yes', '0': 'no'}
459 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
460 RadioBox
.__init
__(self
, parent
, id, choices
= self
.values
.keys(), name
=name
)
462 return self
.values
[self
.GetStringSelection()]
463 def SetValue(self
, value
):
464 if not value
: value
= '1'
465 self
.SetStringSelection(self
.seulav
[value
])
467 class ParamOrient(RadioBox
):
468 values
= {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
469 seulav
= {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
470 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
471 RadioBox
.__init
__(self
, parent
, id, choices
= self
.values
.keys(), name
=name
)
473 return self
.values
[self
.GetStringSelection()]
474 def SetValue(self
, value
):
475 if not value
: value
= 'wxHORIZONTAL'
476 self
.SetStringSelection(self
.seulav
[value
])
478 class ParamFile(PPanel
):
479 def __init__(self
, parent
, id = -1, size
= wxDefaultSize
, name
= ''):
480 PPanel
.__init
__(self
, parent
, id, name
)
481 self
.ID_TEXT_CTRL
= wxNewId()
482 self
.ID_BUTTON_BROWSE
= wxNewId()
483 self
.SetBackgroundColour(panel
.GetBackgroundColour())
485 self
.text
= wxTextCtrl(self
, self
.ID_TEXT_CTRL
, size
=wxSize(200,-1))
486 sizer
.Add(self
.text
, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL
, 10)
487 self
.button
= wxButton(self
, self
.ID_BUTTON_BROWSE
, 'Browse...')
488 sizer
.Add(self
.button
, 0, wxALIGN_CENTER_VERTICAL
)
489 self
.SetAutoLayout(true
)
492 self
.textModified
= false
493 EVT_BUTTON(self
, self
.ID_BUTTON_BROWSE
, self
.OnButtonBrowse
)
494 EVT_TEXT(self
, self
.ID_TEXT_CTRL
, self
.OnChange
)
495 def OnChange(self
, evt
):
496 if self
.freeze
: return
498 self
.textModified
= true
501 if self
.textModified
: # text has newer value
502 return eval(self
.text
.GetValue())
504 def SetValue(self
, value
):
507 self
.text
.SetValue(value
) # update text ctrl
509 def OnButtonBrowse(self
, evt
):
510 if self
.textModified
: # text has newer value
511 self
.value
= self
.text
.GetValue()
512 dlg
= wxFileDialog(self
,
513 defaultDir
= os
.path
.abspath(os
.path
.dirname(self
.value
)),
514 defaultFile
= os
.path
.basename(self
.value
))
515 if dlg
.ShowModal() == wxID_OK
:
517 common
= os
.path
.commonprefix([frame
.dataFile
, dlg
.GetPath()])
518 self
.SetValue(dlg
.GetPath()[len(common
):])
520 self
.textModified
= false
525 'style': ParamStyle
, 'exstyle': ParamExStyle
,
526 'pos': ParamPosSize
, 'size': ParamPosSize
,
527 'border': ParamInt
, 'cols': ParamInt
, 'rows': ParamInt
,
528 'vgap': ParamInt
, 'hgap': ParamInt
,
529 'checkable': ParamBool
, 'accel': ParamAccel
,
530 'label': ParamText
, 'title': ParamText
, 'value': ParamText
,
531 'content': ParamContent
, 'selection': ParamInt
,
532 'min': ParamInt
, 'max': ParamInt
,
533 'fg': ParamColour
, 'bg': ParamColour
, 'font': ParamFont
,
534 'enabled': ParamBool
, 'focused': ParamBool
, 'hidden': ParamBool
,
535 'tooltip': ParamText
, 'bitmap': ParamFile
, 'icon': ParamFile
,