]>
Commit | Line | Data |
---|---|---|
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 | from wxPython.wx import * | |
8 | from wxPython.xrc import * | |
9 | import string | |
10 | import os.path | |
11 | from types import * | |
12 | ||
13 | # Object which is currently processed | |
14 | currentXXX = None | |
15 | def SetCurrentXXX(xxx): | |
16 | global currentXXX | |
17 | currentXXX = xxx | |
18 | ||
19 | genericStyles = ['wxSIMPLE_BORDER', 'wxDOUBLE_BORDER', | |
20 | 'wxSUNKEN_BORDER', 'wxRAISED_BORDER', | |
21 | 'wxSTATIC_BORDER', 'wxNO_BORDER', | |
22 | 'wxTRANSPARENT_WINDOW', 'wxWANTS_CHARS', | |
23 | 'wxNO_FULL_REPAINT_ON_RESIZE'] | |
24 | ||
25 | buttonSize = (55,-1) | |
26 | ||
27 | # Class that can properly disable children | |
28 | class PPanel(wxPanel): | |
29 | def __init__(self, parent, name): | |
30 | wxPanel.__init__(self, parent, -1, name=name) | |
31 | self.modified = self.freeze = false | |
32 | def Enable(self, value): | |
33 | # Something strange is going on with enable so we make sure... | |
34 | for w in self.GetChildren(): | |
35 | w.Enable(value) | |
36 | wxPanel.Enable(self, value) | |
37 | def SetModified(self): | |
38 | self.modified = true | |
39 | panel.SetModified(true) | |
40 | ||
41 | class ParamBinaryOr(PPanel): | |
42 | def __init__(self, parent, name): | |
43 | PPanel.__init__(self, parent, name) | |
44 | self.ID_TEXT_CTRL = wxNewId() | |
45 | self.ID_BUTTON_CHOICES = wxNewId() | |
46 | self.SetBackgroundColour(panel.GetBackgroundColour()) | |
47 | sizer = wxBoxSizer() | |
48 | self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1)) | |
49 | sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5) | |
50 | self.button = wxButton(self, self.ID_BUTTON_CHOICES, 'Edit...', size=buttonSize) | |
51 | sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL) | |
52 | self.SetAutoLayout(true) | |
53 | self.SetSizer(sizer) | |
54 | sizer.Fit(self) | |
55 | EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices) | |
56 | EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) | |
57 | def OnChange(self, evt): | |
58 | if self.freeze: return | |
59 | self.SetModified() | |
60 | evt.Skip() | |
61 | def GetValue(self): | |
62 | return self.text.GetValue() | |
63 | def SetValue(self, value): | |
64 | self.freeze = true | |
65 | self.text.SetValue(value) | |
66 | self.freeze = false | |
67 | def OnButtonChoices(self, evt): | |
68 | dlg = wxDialog(self, -1, 'Choices') | |
69 | topSizer = wxBoxSizer(wxVERTICAL) | |
70 | listBox = wxCheckListBox(dlg, -1, choices=self.values, size=(250,200)) | |
71 | value = map(string.strip, string.split(self.text.GetValue(), '|')) | |
72 | if value == ['']: value = [] | |
73 | ignored = [] | |
74 | for i in value: | |
75 | try: | |
76 | listBox.Check(self.values.index(i)) | |
77 | except ValueError: | |
78 | # Try to find equal | |
79 | if self.equal.has_key(i): | |
80 | listBox.Check(self.values.index(self.equal[i])) | |
81 | else: | |
82 | print 'WARNING: unknown flag: %s: ignored.' % i | |
83 | ignored.append(i) | |
84 | topSizer.Add(listBox, 1, wxEXPAND) | |
85 | sizer = wxBoxSizer() | |
86 | buttonOk = wxButton(dlg, wxID_OK, 'OK') | |
87 | buttonOk.SetDefault() | |
88 | sizer.Add(buttonOk, 0, wxRIGHT, 10) | |
89 | sizer.Add(0, 0, 1) | |
90 | sizer.Add(wxButton(dlg, wxID_CANCEL, 'Cancel')) | |
91 | topSizer.Add(sizer, 0, wxALL | wxEXPAND, 10) | |
92 | dlg.SetAutoLayout(true) | |
93 | dlg.SetSizer(topSizer) | |
94 | topSizer.Fit(dlg) | |
95 | dlg.Center() | |
96 | if dlg.ShowModal() == wxID_OK: | |
97 | value = [] | |
98 | for i in range(listBox.Number()): | |
99 | if listBox.IsChecked(i): | |
100 | value.append(self.values[i]) | |
101 | # Add ignored flags | |
102 | value.extend(ignored) | |
103 | if value: | |
104 | self.SetValue(reduce(lambda a,b: a+'|'+b, value)) | |
105 | else: | |
106 | self.SetValue('') | |
107 | self.SetModified() | |
108 | dlg.Destroy() | |
109 | ||
110 | class ParamFlag(ParamBinaryOr): | |
111 | values = ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL', | |
112 | 'wxEXPAND', 'wxSHAPED', 'wxALIGN_CENTRE', 'wxALIGN_RIGHT', | |
113 | 'wxALIGN_BOTTOM', 'wxALIGN_CENTRE_VERTICAL', | |
114 | 'wxALIGN_CENTRE_HORIZONTAL'] | |
115 | equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE', | |
116 | 'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL', | |
117 | 'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL'} | |
118 | def __init__(self, parent, name): | |
119 | ParamBinaryOr.__init__(self, parent, name) | |
120 | ||
121 | class ParamStyle(ParamBinaryOr): | |
122 | equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE'} | |
123 | def __init__(self, parent, name): | |
124 | self.values = currentXXX.winStyles + genericStyles | |
125 | ParamBinaryOr.__init__(self, parent, name) | |
126 | ||
127 | class ParamNonGenericStyle(ParamBinaryOr): | |
128 | def __init__(self, parent, name): | |
129 | self.values = currentXXX.winStyles | |
130 | ParamBinaryOr.__init__(self, parent, name) | |
131 | ||
132 | class ParamExStyle(ParamBinaryOr): | |
133 | def __init__(self, parent, name): | |
134 | if currentXXX: | |
135 | self.values = currentXXX.exStyles # constant at the moment | |
136 | else: | |
137 | self.values = [] | |
138 | ParamBinaryOr.__init__(self, parent, name) | |
139 | ||
140 | class ParamColour(PPanel): | |
141 | def __init__(self, parent, name): | |
142 | PPanel.__init__(self, parent, name) | |
143 | self.ID_TEXT_CTRL = wxNewId() | |
144 | self.ID_BUTTON = wxNewId() | |
145 | self.SetBackgroundColour(panel.GetBackgroundColour()) | |
146 | sizer = wxBoxSizer() | |
147 | self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=(65,-1)) | |
148 | sizer.Add(self.text, 0, wxRIGHT, 5) | |
149 | self.button = wxPanel(self, self.ID_BUTTON, wxDefaultPosition, wxSize(40, -1)) | |
150 | sizer.Add(self.button, 0, wxGROW) | |
151 | self.SetAutoLayout(true) | |
152 | self.SetSizer(sizer) | |
153 | sizer.Fit(self) | |
154 | self.textModified = false | |
155 | EVT_PAINT(self.button, self.OnPaintButton) | |
156 | EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) | |
157 | EVT_LEFT_DOWN(self.button, self.OnLeftDown) | |
158 | def GetValue(self): | |
159 | return self.text.GetValue() | |
160 | def SetValue(self, value): | |
161 | self.freeze = true | |
162 | if not value: value = '#FFFFFF' | |
163 | self.text.SetValue(str(value)) # update text ctrl | |
164 | colour = wxColour(int(value[1:3], 16), int(value[3:5], 16), int(value[5:7], 16)) | |
165 | self.button.SetBackgroundColour(colour) | |
166 | self.button.Refresh() | |
167 | self.freeze = false | |
168 | def OnChange(self, evt): | |
169 | if self.freeze: return | |
170 | self.SetModified() | |
171 | evt.Skip() | |
172 | def OnPaintButton(self, evt): | |
173 | dc = wxPaintDC(self.button) | |
174 | dc.SetBrush(wxTRANSPARENT_BRUSH) | |
175 | if self.IsEnabled(): dc.SetPen(wxBLACK_PEN) | |
176 | else: dc.SetPen(wxGREY_PEN) | |
177 | size = self.button.GetSize() | |
178 | dc.DrawRectangle(0, 0, size.x, size.y) | |
179 | def OnLeftDown(self, evt): | |
180 | data = wxColourData() | |
181 | data.SetColour(self.GetValue()) | |
182 | dlg = wxColourDialog(self, data) | |
183 | if dlg.ShowModal() == wxID_OK: | |
184 | self.SetValue('#%02X%02X%02X' % dlg.GetColourData().GetColour().Get()) | |
185 | self.SetModified() | |
186 | dlg.Destroy() | |
187 | ||
188 | ################################################################################ | |
189 | ||
190 | # Mapping from wx constants ro XML strings | |
191 | fontFamiliesWx2Xml = {wxDEFAULT: 'default', wxDECORATIVE: 'decorative', | |
192 | wxROMAN: 'roman', wxSCRIPT: 'script', wxSWISS: 'swiss', | |
193 | wxMODERN: 'modern'} | |
194 | fontStylesWx2Xml = {wxNORMAL: 'normal', wxSLANT: 'slant', wxITALIC: 'italic'} | |
195 | fontWeightsWx2Xml = {wxNORMAL: 'normal', wxLIGHT: 'light', wxBOLD: 'bold'} | |
196 | def ReverseMap(m): | |
197 | rm = {} | |
198 | for k,v in m.items(): rm[v] = k | |
199 | return rm | |
200 | fontFamiliesXml2wx = ReverseMap(fontFamiliesWx2Xml) | |
201 | fontStylesXml2wx = ReverseMap(fontStylesWx2Xml) | |
202 | fontWeightsXml2wx = ReverseMap(fontWeightsWx2Xml) | |
203 | ||
204 | class ParamFont(PPanel): | |
205 | def __init__(self, parent, name): | |
206 | PPanel.__init__(self, parent, name) | |
207 | self.ID_TEXT_CTRL = wxNewId() | |
208 | self.ID_BUTTON_SELECT = wxNewId() | |
209 | self.SetBackgroundColour(panel.GetBackgroundColour()) | |
210 | sizer = wxBoxSizer() | |
211 | self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1)) | |
212 | sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5) | |
213 | self.button = wxButton(self, self.ID_BUTTON_SELECT, 'Select...', size=buttonSize) | |
214 | sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL) | |
215 | self.SetAutoLayout(true) | |
216 | self.SetSizer(sizer) | |
217 | sizer.Fit(self) | |
218 | self.textModified = false | |
219 | EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect) | |
220 | EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) | |
221 | def OnChange(self, evt): | |
222 | if self.freeze: return | |
223 | self.SetModified() | |
224 | self.textModified = true | |
225 | evt.Skip() | |
226 | def _defaultValue(self): | |
227 | return ['12', 'default', 'normal', 'normal', '0', '', ''] | |
228 | def GetValue(self): | |
229 | if self.textModified: # text has newer value | |
230 | try: | |
231 | return eval(self.text.GetValue()) | |
232 | except SyntaxError: | |
233 | wxLogError('Syntax error in parameter value: ' + self.GetName()) | |
234 | return self._defaultValue() | |
235 | return self.value | |
236 | def SetValue(self, value): | |
237 | self.freeze = true # disable other handlers | |
238 | if not value: value = self._defaultValue() | |
239 | self.value = value | |
240 | self.text.SetValue(str(value)) # update text ctrl | |
241 | self.freeze = false | |
242 | def OnButtonSelect(self, evt): | |
243 | if self.textModified: # text has newer value | |
244 | try: | |
245 | self.value = eval(self.text.GetValue()) | |
246 | except SyntaxError: | |
247 | wxLogError('Syntax error in parameter value: ' + self.GetName()) | |
248 | self.value = self._defaultValue() | |
249 | # Make initial font | |
250 | # Default values | |
251 | size = 12 | |
252 | family = wxDEFAULT | |
253 | style = weight = wxNORMAL | |
254 | underlined = 0 | |
255 | face = '' | |
256 | enc = wxFONTENCODING_DEFAULT | |
257 | # Fall back to default if exceptions | |
258 | error = false | |
259 | try: | |
260 | try: size = int(self.value[0]) | |
261 | except ValueError: error = true | |
262 | try: family = fontFamiliesXml2wx[self.value[1]] | |
263 | except KeyError: error = true | |
264 | try: style = fontStylesXml2wx[self.value[2]] | |
265 | except KeyError: error = true | |
266 | try: weight = fontWeightsXml2wx[self.value[3]] | |
267 | except KeyError: error = true | |
268 | try: underlined = int(self.value[4]) | |
269 | except ValueError: error = true | |
270 | face = self.value[5] | |
271 | mapper = wxFontMapper() | |
272 | if not self.value[6]: enc = mapper.CharsetToEncoding(self.value[6]) | |
273 | except IndexError: | |
274 | error = true | |
275 | if error: wxLogError('Invalid font specification') | |
276 | if enc == wxFONTENCODING_DEFAULT: enc = wxFONTENCODING_SYSTEM | |
277 | font = wxFont(size, family, style, weight, underlined, face, enc) | |
278 | data = wxFontData() | |
279 | data.SetInitialFont(font) | |
280 | dlg = wxFontDialog(self, data) | |
281 | if dlg.ShowModal() == wxID_OK: | |
282 | font = dlg.GetFontData().GetChosenFont() | |
283 | value = [str(font.GetPointSize()), | |
284 | fontFamiliesWx2Xml.get(font.GetFamily(), "default"), | |
285 | fontStylesWx2Xml.get(font.GetStyle(), "normal"), | |
286 | fontWeightsWx2Xml.get(font.GetWeight(), "normal"), | |
287 | str(font.GetUnderlined()), | |
288 | font.GetFaceName(), | |
289 | wxFontMapper_GetEncodingName(font.GetEncoding()) | |
290 | ] | |
291 | # Add ignored flags | |
292 | self.SetValue(value) | |
293 | self.SetModified() | |
294 | self.textModified = false | |
295 | dlg.Destroy() | |
296 | ||
297 | ################################################################################ | |
298 | ||
299 | class ParamInt(PPanel): | |
300 | def __init__(self, parent, name): | |
301 | PPanel.__init__(self, parent, name) | |
302 | self.ID_SPIN_CTRL = wxNewId() | |
303 | sizer = wxBoxSizer() | |
304 | self.spin = wxSpinCtrl(self, self.ID_SPIN_CTRL, size=wxSize(50,-1)) | |
305 | self.SetBackgroundColour(panel.GetBackgroundColour()) | |
306 | sizer.Add(self.spin) | |
307 | self.SetAutoLayout(true) | |
308 | self.SetSizer(sizer) | |
309 | sizer.Fit(self) | |
310 | EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange) | |
311 | def GetValue(self): | |
312 | return str(self.spin.GetValue()) | |
313 | def SetValue(self, value): | |
314 | self.freeze = true | |
315 | if not value: value = 0 | |
316 | self.spin.SetValue(int(value)) | |
317 | self.freeze = false | |
318 | def OnChange(self, evt): | |
319 | if self.freeze: return | |
320 | self.SetModified() | |
321 | evt.Skip() | |
322 | ||
323 | class ParamText(PPanel): | |
324 | def __init__(self, parent, name, textWidth=200): | |
325 | PPanel.__init__(self, parent, name) | |
326 | self.ID_TEXT_CTRL = wxNewId() | |
327 | # We use sizer even here to have the same size of text control | |
328 | sizer = wxBoxSizer() | |
329 | self.SetBackgroundColour(panel.GetBackgroundColour()) | |
330 | self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(textWidth,-1)) | |
331 | sizer.Add(self.text, 0, wxALIGN_CENTER_VERTICAL) | |
332 | self.SetAutoLayout(true) | |
333 | self.SetSizer(sizer) | |
334 | sizer.Fit(self) | |
335 | EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) | |
336 | def GetValue(self): | |
337 | return self.text.GetValue() | |
338 | def SetValue(self, value): | |
339 | self.freeze = true # disable other handlers | |
340 | self.text.SetValue(value) | |
341 | self.freeze = false # disable other handlers | |
342 | def OnChange(self, evt): | |
343 | if self.freeze: return | |
344 | self.SetModified() | |
345 | evt.Skip() | |
346 | ||
347 | class ParamAccel(ParamText): | |
348 | def __init__(self, parent, name): | |
349 | ParamText.__init__(self, parent, name, 50) | |
350 | ||
351 | class ParamPosSize(ParamText): | |
352 | def __init__(self, parent, name): | |
353 | ParamText.__init__(self, parent, name, 80) | |
354 | ||
355 | class ContentDialog(wxDialogPtr): | |
356 | def __init__(self, parent, value): | |
357 | # Is this normal??? | |
358 | w = frame.res.LoadDialog(parent, 'DIALOG_CONTENT') | |
359 | wxDialogPtr.__init__(self, w.this) | |
360 | self.thisown = 1 | |
361 | self.Center() | |
362 | self.list = self.FindWindowByName('LIST') | |
363 | # Set list items | |
364 | for v in value: | |
365 | self.list.Append(v) | |
366 | self.SetAutoLayout(true) | |
367 | self.GetSizer().Fit(self) | |
368 | # Callbacks | |
369 | self.ID_BUTTON_APPEND = XMLID('BUTTON_APPEND') | |
370 | self.ID_BUTTON_REMOVE = XMLID('BUTTON_REMOVE') | |
371 | self.ID_BUTTON_UP = XMLID('BUTTON_UP') | |
372 | self.ID_BUTTON_DOWN = XMLID('BUTTON_DOWN') | |
373 | EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp) | |
374 | EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown) | |
375 | EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend) | |
376 | EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove) | |
377 | EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI) | |
378 | EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI) | |
379 | EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI) | |
380 | def OnButtonUp(self, evt): | |
381 | i = self.list.GetSelection() | |
382 | str = self.list.GetString(i) | |
383 | self.list.Delete(i) | |
384 | self.list.InsertItems([str], i-1) | |
385 | self.list.SetSelection(i-1) | |
386 | def OnButtonDown(self, evt): | |
387 | i = self.list.GetSelection() | |
388 | str = self.list.GetString(i) | |
389 | self.list.Delete(i) | |
390 | self.list.InsertItems([str], i+1) | |
391 | self.list.SetSelection(i+1) | |
392 | def OnButtonAppend(self, evt): | |
393 | str = wxGetTextFromUser('Enter new item:', 'Append', '', self) | |
394 | self.list.Append(str) | |
395 | def OnButtonRemove(self, evt): | |
396 | self.list.Delete(self.list.GetSelection()) | |
397 | def OnUpdateUI(self, evt): | |
398 | if evt.GetId() == self.ID_BUTTON_REMOVE: | |
399 | evt.Enable(self.list.GetSelection() != -1) | |
400 | elif evt.GetId() == self.ID_BUTTON_UP: | |
401 | evt.Enable(self.list.GetSelection() > 0) | |
402 | elif evt.GetId() == self.ID_BUTTON_DOWN: | |
403 | evt.Enable(self.list.GetSelection() != -1 and \ | |
404 | self.list.GetSelection() < self.list.Number() - 1) | |
405 | ||
406 | class ContentCheckListDialog(wxDialogPtr): | |
407 | def __init__(self, parent, value): | |
408 | # Is this normal??? | |
409 | w = frame.res.LoadDialog(parent, 'DIALOG_CONTENT_CHECK_LIST') | |
410 | wxDialogPtr.__init__(self, w.this) | |
411 | self.thisown = 1 | |
412 | self.Center() | |
413 | self.list = self.FindWindowByName('CHECK_LIST') | |
414 | # Set list items | |
415 | i = 0 | |
416 | for v,ch in value: | |
417 | self.list.Append(v) | |
418 | self.list.Check(i, ch) | |
419 | i += 1 | |
420 | self.SetAutoLayout(true) | |
421 | self.GetSizer().Fit(self) | |
422 | # Callbacks | |
423 | self.ID_BUTTON_APPEND = XMLID('BUTTON_APPEND') | |
424 | self.ID_BUTTON_REMOVE = XMLID('BUTTON_REMOVE') | |
425 | self.ID_BUTTON_UP = XMLID('BUTTON_UP') | |
426 | self.ID_BUTTON_DOWN = XMLID('BUTTON_DOWN') | |
427 | EVT_CHECKLISTBOX(self, self.list.GetId(), self.OnCheck) | |
428 | EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp) | |
429 | EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown) | |
430 | EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend) | |
431 | EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove) | |
432 | EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI) | |
433 | EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI) | |
434 | EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI) | |
435 | def OnCheck(self, evt): | |
436 | # !!! Wrong wxGTK (wxMSW?) behavior: toggling selection if checking | |
437 | self.list.Deselect(evt.GetSelection()) | |
438 | def OnButtonUp(self, evt): | |
439 | i = self.list.GetSelection() | |
440 | str, ch = self.list.GetString(i), self.list.IsChecked(i) | |
441 | self.list.Delete(i) | |
442 | self.list.InsertItems([str], i-1) | |
443 | self.list.Check(i-1, ch) | |
444 | self.list.SetSelection(i-1) | |
445 | def OnButtonDown(self, evt): | |
446 | i = self.list.GetSelection() | |
447 | str, ch = self.list.GetString(i), self.list.IsChecked(i) | |
448 | self.list.Delete(i) | |
449 | self.list.InsertItems([str], i+1) | |
450 | self.list.Check(i+1, ch) | |
451 | self.list.SetSelection(i+1) | |
452 | def OnButtonAppend(self, evt): | |
453 | str = wxGetTextFromUser('Enter new item:', 'Append', '', self) | |
454 | self.list.Append(str) | |
455 | def OnButtonRemove(self, evt): | |
456 | self.list.Delete(self.list.GetSelection()) | |
457 | def OnUpdateUI(self, evt): | |
458 | if evt.GetId() == self.ID_BUTTON_REMOVE: | |
459 | evt.Enable(self.list.GetSelection() != -1) | |
460 | elif evt.GetId() == self.ID_BUTTON_UP: | |
461 | evt.Enable(self.list.GetSelection() > 0) | |
462 | elif evt.GetId() == self.ID_BUTTON_DOWN: | |
463 | evt.Enable(self.list.GetSelection() != -1 and \ | |
464 | self.list.GetSelection() < self.list.Number() - 1) | |
465 | ||
466 | class ParamContent(PPanel): | |
467 | def __init__(self, parent, name): | |
468 | PPanel.__init__(self, parent, name) | |
469 | self.ID_TEXT_CTRL = wxNewId() | |
470 | self.ID_BUTTON_EDIT = wxNewId() | |
471 | self.SetBackgroundColour(panel.GetBackgroundColour()) | |
472 | sizer = wxBoxSizer() | |
473 | self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1)) | |
474 | sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5) | |
475 | self.button = wxButton(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize) | |
476 | sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL) | |
477 | self.SetAutoLayout(true) | |
478 | self.SetSizer(sizer) | |
479 | sizer.Fit(self) | |
480 | self.textModified = false | |
481 | EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit) | |
482 | EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) | |
483 | def OnChange(self, evt): | |
484 | if self.freeze: return | |
485 | self.SetModified() | |
486 | self.textModified = true | |
487 | evt.Skip() | |
488 | def GetValue(self): | |
489 | if self.textModified: # text has newer value | |
490 | try: | |
491 | return eval(self.text.GetValue()) | |
492 | except SyntaxError: | |
493 | wxLogError('Syntax error in parameter value: ' + self.GetName()) | |
494 | return [] | |
495 | return self.value | |
496 | def SetValue(self, value): | |
497 | self.freeze = true | |
498 | if not value: value = [] | |
499 | self.value = value | |
500 | self.text.SetValue(str(value)) # update text ctrl | |
501 | self.freeze = false | |
502 | def OnButtonEdit(self, evt): | |
503 | if self.textModified: # text has newer value | |
504 | try: | |
505 | self.value = eval(self.text.GetValue()) | |
506 | except SyntaxError: | |
507 | wxLogError('Syntax error in parameter value: ' + self.GetName()) | |
508 | self.value = [] | |
509 | dlg = ContentDialog(self, self.value) | |
510 | if dlg.ShowModal() == wxID_OK: | |
511 | value = [] | |
512 | for i in range(dlg.list.Number()): | |
513 | value.append(dlg.list.GetString(i)) | |
514 | # Add ignored flags | |
515 | self.SetValue(value) | |
516 | self.SetModified() | |
517 | self.textModified = false | |
518 | dlg.Destroy() | |
519 | ||
520 | # CheckList content | |
521 | class ParamContentCheckList(ParamContent): | |
522 | def __init__(self, parent, name): | |
523 | ParamContent.__init__(self, parent, name) | |
524 | def OnButtonEdit(self, evt): | |
525 | if self.textModified: # text has newer value | |
526 | try: | |
527 | self.value = eval(self.text.GetValue()) | |
528 | except SyntaxError: | |
529 | wxLogError('Syntax error in parameter value: ' + self.GetName()) | |
530 | self.value = [] | |
531 | dlg = ContentCheckListDialog(self, self.value) | |
532 | if dlg.ShowModal() == wxID_OK: | |
533 | value = [] | |
534 | for i in range(dlg.list.Number()): | |
535 | value.append((dlg.list.GetString(i), dlg.list.IsChecked(i))) | |
536 | # Add ignored flags | |
537 | self.SetValue(value) | |
538 | self.SetModified() | |
539 | self.textModified = false | |
540 | dlg.Destroy() | |
541 | ||
542 | class IntListDialog(wxDialogPtr): | |
543 | def __init__(self, parent, value): | |
544 | # Is this normal??? | |
545 | w = frame.res.LoadDialog(parent, 'DIALOG_INTLIST') | |
546 | wxDialogPtr.__init__(self, w.this) | |
547 | self.thisown = 1 | |
548 | self.Center() | |
549 | self.list = self.FindWindowByName('LIST') | |
550 | # Set list items | |
551 | value.sort() | |
552 | for v in value: | |
553 | if type(v) != IntType: | |
554 | wxLogError('Invalid item type') | |
555 | else: | |
556 | self.list.Append(str(v)) | |
557 | self.SetAutoLayout(true) | |
558 | self.GetSizer().Fit(self) | |
559 | # Callbacks | |
560 | self.ID_BUTTON_ADD = XMLID('BUTTON_ADD') | |
561 | self.ID_BUTTON_REMOVE = XMLID('BUTTON_REMOVE') | |
562 | EVT_BUTTON(self, self.ID_BUTTON_ADD, self.OnButtonAppend) | |
563 | EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove) | |
564 | EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI) | |
565 | def OnButtonAppend(self, evt): | |
566 | s = wxGetTextFromUser('Enter new number:', 'Add', '', self) | |
567 | # Check that it's unique | |
568 | try: | |
569 | v = int(s) | |
570 | s = str(v) # to be sure | |
571 | i = self.list.FindString(s) | |
572 | if i == -1: # ignore non-unique | |
573 | # Find place to insert | |
574 | found = false | |
575 | for i in range(self.list.Number()): | |
576 | if int(self.list.GetString(i)) > v: | |
577 | found = true | |
578 | break | |
579 | if found: self.list.InsertItems([s], i) | |
580 | else: self.list.Append(s) | |
581 | except ValueError: | |
582 | wxLogError('List item is not an int!') | |
583 | def OnButtonRemove(self, evt): | |
584 | self.list.Delete(self.list.GetSelection()) | |
585 | def OnUpdateUI(self, evt): | |
586 | if evt.GetId() == self.ID_BUTTON_REMOVE: | |
587 | evt.Enable(self.list.GetSelection() != -1) | |
588 | ||
589 | # For growable list | |
590 | class ParamIntList(ParamContent): | |
591 | def __init__(self, parent, name): | |
592 | ParamContent.__init__(self, parent, name) | |
593 | def OnButtonEdit(self, evt): | |
594 | if self.textModified: # text has newer value | |
595 | try: | |
596 | self.value = eval(self.text.GetValue()) | |
597 | except SyntaxError: | |
598 | wxLogError('Syntax error in parameter value: ' + self.GetName()) | |
599 | self.value = [] | |
600 | dlg = IntListDialog(self, self.value) | |
601 | if dlg.ShowModal() == wxID_OK: | |
602 | value = [] | |
603 | for i in range(dlg.list.Number()): | |
604 | value.append(int(dlg.list.GetString(i))) | |
605 | # Add ignored flags | |
606 | self.SetValue(value) | |
607 | self.SetModified() | |
608 | self.textModified = false | |
609 | dlg.Destroy() | |
610 | ||
611 | # Boxless radiobox | |
612 | class RadioBox(PPanel): | |
613 | def __init__(self, parent, id, choices, | |
614 | pos=wxDefaultPosition, name='radiobox'): | |
615 | PPanel.__init__(self, parent, name) | |
616 | self.SetBackgroundColour(panel.GetBackgroundColour()) | |
617 | self.choices = choices | |
618 | topSizer = wxBoxSizer() | |
619 | for i in choices: | |
620 | button = wxRadioButton(self, -1, i, name=i) | |
621 | topSizer.Add(button) | |
622 | EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice) | |
623 | self.SetAutoLayout(true) | |
624 | self.SetSizer(topSizer) | |
625 | topSizer.Fit(self) | |
626 | def SetStringSelection(self, value): | |
627 | self.freeze = true | |
628 | for i in self.choices: | |
629 | self.FindWindowByName(i).SetValue(i == value) | |
630 | self.value = value | |
631 | self.freeze = false | |
632 | def OnRadioChoice(self, evt): | |
633 | if self.freeze: return | |
634 | if evt.GetSelection(): | |
635 | self.value = evt.GetEventObject().GetName() | |
636 | self.SetModified() | |
637 | def GetStringSelection(self): | |
638 | return self.value | |
639 | ||
640 | class ParamBool(RadioBox): | |
641 | values = {'yes': '1', 'no': '0'} | |
642 | seulav = {'1': 'yes', '0': 'no'} | |
643 | def __init__(self, parent, name): | |
644 | RadioBox.__init__(self, parent, -1, choices = self.values.keys(), name=name) | |
645 | def GetValue(self): | |
646 | return self.values[self.GetStringSelection()] | |
647 | def SetValue(self, value): | |
648 | if not value: value = '1' | |
649 | self.SetStringSelection(self.seulav[value]) | |
650 | ||
651 | class ParamOrient(RadioBox): | |
652 | values = {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'} | |
653 | seulav = {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'} | |
654 | def __init__(self, parent, name): | |
655 | RadioBox.__init__(self, parent, -1, choices = self.values.keys(), name=name) | |
656 | def GetValue(self): | |
657 | return self.values[self.GetStringSelection()] | |
658 | def SetValue(self, value): | |
659 | if not value: value = 'wxHORIZONTAL' | |
660 | self.SetStringSelection(self.seulav[value]) | |
661 | ||
662 | class ParamFile(PPanel): | |
663 | def __init__(self, parent, name): | |
664 | PPanel.__init__(self, parent, name) | |
665 | self.ID_TEXT_CTRL = wxNewId() | |
666 | self.ID_BUTTON_BROWSE = wxNewId() | |
667 | self.SetBackgroundColour(panel.GetBackgroundColour()) | |
668 | sizer = wxBoxSizer() | |
669 | self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1)) | |
670 | sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5) | |
671 | self.button = wxButton(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize) | |
672 | sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL) | |
673 | self.SetAutoLayout(true) | |
674 | self.SetSizer(sizer) | |
675 | sizer.Fit(self) | |
676 | self.textModified = false | |
677 | EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse) | |
678 | EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange) | |
679 | def OnChange(self, evt): | |
680 | if self.freeze: return | |
681 | self.SetModified() | |
682 | self.textModified = true | |
683 | evt.Skip() | |
684 | def GetValue(self): | |
685 | if self.textModified: # text has newer value | |
686 | return self.text.GetValue() | |
687 | return self.value | |
688 | def SetValue(self, value): | |
689 | self.freeze = true | |
690 | self.value = value | |
691 | self.text.SetValue(value) # update text ctrl | |
692 | self.freeze = false | |
693 | def OnButtonBrowse(self, evt): | |
694 | if self.textModified: # text has newer value | |
695 | self.value = self.text.GetValue() | |
696 | dlg = wxFileDialog(self, | |
697 | defaultDir = os.path.dirname(self.value), | |
698 | defaultFile = os.path.basename(self.value)) | |
699 | if dlg.ShowModal() == wxID_OK: | |
700 | # Make relative | |
701 | common = os.path.commonprefix([os.path.abspath(frame.dataFile), | |
702 | dlg.GetPath()]) | |
703 | self.SetValue(dlg.GetPath()[len(common):]) | |
704 | self.SetModified() | |
705 | self.textModified = false | |
706 | dlg.Destroy() | |
707 | ||
708 | paramDict = { | |
709 | 'flag': ParamFlag, | |
710 | 'style': ParamStyle, 'exstyle': ParamExStyle, | |
711 | 'pos': ParamPosSize, 'size': ParamPosSize, | |
712 | 'border': ParamInt, 'cols': ParamInt, 'rows': ParamInt, | |
713 | 'vgap': ParamInt, 'hgap': ParamInt, | |
714 | 'checkable': ParamBool, 'accel': ParamAccel, | |
715 | 'label': ParamText, 'title': ParamText, 'value': ParamText, | |
716 | 'content': ParamContent, 'selection': ParamInt, | |
717 | 'min': ParamInt, 'max': ParamInt, | |
718 | 'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont, | |
719 | 'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool, | |
720 | 'tooltip': ParamText, 'bitmap': ParamFile, 'icon': ParamFile, | |
721 | } | |
722 |