]>
Commit | Line | Data |
---|---|---|
09f3d4e6 RD |
1 | # Name: params.py |
2 | # Purpose: Classes for parameter introduction | |
3 | # Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be> | |
4 | # Created: 22.08.2001 | |
a40b5e84 | 5 | # RCS-ID: $Id$ |
09f3d4e6 RD |
6 | |
7 | from wxPython.wx import * | |
8 | from wxPython.xrc import * | |
9 | import string | |
32ce09e2 | 10 | import os.path |
18fc9fa3 | 11 | from types import * |
09f3d4e6 RD |
12 | |
13 | # Object which is currently processed | |
14 | currentXXX = None | |
15 | def SetCurrentXXX(xxx): | |
16 | global currentXXX | |
17 | currentXXX = xxx | |
18 | ||
32ce09e2 RD |
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'] | |
09f3d4e6 | 24 | |
18fc9fa3 RD |
25 | buttonSize = (55,-1) |
26 | ||
a40b5e84 RD |
27 | # Class that can properly disable children |
28 | class PPanel(wxPanel): | |
f0c20d94 RD |
29 | def __init__(self, parent, name): |
30 | wxPanel.__init__(self, parent, -1, name=name) | |
32ce09e2 | 31 | self.modified = self.freeze = false |
a40b5e84 | 32 | def Enable(self, value): |
32ce09e2 | 33 | # Something strange is going on with enable so we make sure... |
a40b5e84 RD |
34 | for w in self.GetChildren(): |
35 | w.Enable(value) | |
32ce09e2 RD |
36 | wxPanel.Enable(self, value) |
37 | def SetModified(self): | |
38 | self.modified = true | |
92631ff2 | 39 | panel.SetModified(true) |
a40b5e84 RD |
40 | |
41 | class ParamBinaryOr(PPanel): | |
f0c20d94 RD |
42 | def __init__(self, parent, name): |
43 | PPanel.__init__(self, parent, name) | |
a40b5e84 RD |
44 | self.ID_TEXT_CTRL = wxNewId() |
45 | self.ID_BUTTON_CHOICES = wxNewId() | |
09f3d4e6 | 46 | self.SetBackgroundColour(panel.GetBackgroundColour()) |
09f3d4e6 | 47 | sizer = wxBoxSizer() |
32ce09e2 | 48 | self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1)) |
18fc9fa3 RD |
49 | sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5) |
50 | self.button = wxButton(self, self.ID_BUTTON_CHOICES, 'Edit...', size=buttonSize) | |
32ce09e2 | 51 | sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL) |
09f3d4e6 RD |
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): | |
32ce09e2 RD |
58 | if self.freeze: return |
59 | self.SetModified() | |
09f3d4e6 RD |
60 | evt.Skip() |
61 | def GetValue(self): | |
62 | return self.text.GetValue() | |
63 | def SetValue(self, value): | |
32ce09e2 | 64 | self.freeze = true |
09f3d4e6 | 65 | self.text.SetValue(value) |
32ce09e2 | 66 | self.freeze = false |
09f3d4e6 | 67 | def OnButtonChoices(self, evt): |
a40b5e84 | 68 | dlg = wxDialog(self, -1, 'Choices') |
09f3d4e6 | 69 | topSizer = wxBoxSizer(wxVERTICAL) |
a40b5e84 | 70 | listBox = wxCheckListBox(dlg, -1, choices=self.values, size=(250,200)) |
09f3d4e6 RD |
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: | |
32ce09e2 | 82 | print 'WARNING: unknown flag: %s: ignored.' % i |
09f3d4e6 RD |
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) | |
a40b5e84 | 94 | topSizer.Fit(dlg) |
09f3d4e6 | 95 | dlg.Center() |
18fc9fa3 | 96 | if dlg.ShowModal() == wxID_OK: |
32ce09e2 RD |
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) | |
f0c20d94 RD |
103 | if value: |
104 | self.SetValue(reduce(lambda a,b: a+'|'+b, value)) | |
105 | else: | |
106 | self.SetValue('') | |
32ce09e2 RD |
107 | self.SetModified() |
108 | dlg.Destroy() | |
09f3d4e6 RD |
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'} | |
f0c20d94 RD |
118 | def __init__(self, parent, name): |
119 | ParamBinaryOr.__init__(self, parent, name) | |
09f3d4e6 RD |
120 | |
121 | class ParamStyle(ParamBinaryOr): | |
122 | equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE'} | |
f0c20d94 | 123 | def __init__(self, parent, name): |
a40b5e84 | 124 | self.values = currentXXX.winStyles + genericStyles |
f0c20d94 | 125 | ParamBinaryOr.__init__(self, parent, name) |
32ce09e2 RD |
126 | |
127 | class ParamNonGenericStyle(ParamBinaryOr): | |
f0c20d94 | 128 | def __init__(self, parent, name): |
32ce09e2 | 129 | self.values = currentXXX.winStyles |
f0c20d94 | 130 | ParamBinaryOr.__init__(self, parent, name) |
09f3d4e6 | 131 | |
a40b5e84 | 132 | class ParamExStyle(ParamBinaryOr): |
f0c20d94 | 133 | def __init__(self, parent, name): |
a40b5e84 RD |
134 | if currentXXX: |
135 | self.values = currentXXX.exStyles # constant at the moment | |
136 | else: | |
137 | self.values = [] | |
f0c20d94 | 138 | ParamBinaryOr.__init__(self, parent, name) |
a40b5e84 RD |
139 | |
140 | class ParamColour(PPanel): | |
f0c20d94 RD |
141 | def __init__(self, parent, name): |
142 | PPanel.__init__(self, parent, name) | |
a40b5e84 RD |
143 | self.ID_TEXT_CTRL = wxNewId() |
144 | self.ID_BUTTON = wxNewId() | |
145 | self.SetBackgroundColour(panel.GetBackgroundColour()) | |
146 | sizer = wxBoxSizer() | |
c1beeb57 | 147 | self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=(65,-1)) |
18fc9fa3 | 148 | sizer.Add(self.text, 0, wxRIGHT, 5) |
a40b5e84 RD |
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 | |
a40b5e84 RD |
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): | |
c1beeb57 | 159 | return self.text.GetValue() |
a40b5e84 | 160 | def SetValue(self, value): |
32ce09e2 | 161 | self.freeze = true |
a40b5e84 | 162 | if not value: value = '#FFFFFF' |
a40b5e84 | 163 | self.text.SetValue(str(value)) # update text ctrl |
32ce09e2 RD |
164 | colour = wxColour(int(value[1:3], 16), int(value[3:5], 16), int(value[5:7], 16)) |
165 | self.button.SetBackgroundColour(colour) | |
a40b5e84 | 166 | self.button.Refresh() |
32ce09e2 | 167 | self.freeze = false |
a40b5e84 | 168 | def OnChange(self, evt): |
32ce09e2 RD |
169 | if self.freeze: return |
170 | self.SetModified() | |
a40b5e84 RD |
171 | evt.Skip() |
172 | def OnPaintButton(self, evt): | |
173 | dc = wxPaintDC(self.button) | |
174 | dc.SetBrush(wxTRANSPARENT_BRUSH) | |
32ce09e2 | 175 | if self.IsEnabled(): dc.SetPen(wxBLACK_PEN) |
a40b5e84 RD |
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): | |
c1beeb57 RD |
180 | data = wxColourData() |
181 | data.SetColour(self.GetValue()) | |
182 | dlg = wxColourDialog(self, data) | |
a40b5e84 RD |
183 | if dlg.ShowModal() == wxID_OK: |
184 | self.SetValue('#%02X%02X%02X' % dlg.GetColourData().GetColour().Get()) | |
32ce09e2 | 185 | self.SetModified() |
32ce09e2 | 186 | dlg.Destroy() |
a40b5e84 RD |
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): | |
f0c20d94 RD |
205 | def __init__(self, parent, name): |
206 | PPanel.__init__(self, parent, name) | |
a40b5e84 RD |
207 | self.ID_TEXT_CTRL = wxNewId() |
208 | self.ID_BUTTON_SELECT = wxNewId() | |
209 | self.SetBackgroundColour(panel.GetBackgroundColour()) | |
210 | sizer = wxBoxSizer() | |
32ce09e2 | 211 | self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1)) |
18fc9fa3 RD |
212 | sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5) |
213 | self.button = wxButton(self, self.ID_BUTTON_SELECT, 'Select...', size=buttonSize) | |
32ce09e2 | 214 | sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL) |
a40b5e84 RD |
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): | |
32ce09e2 RD |
222 | if self.freeze: return |
223 | self.SetModified() | |
a40b5e84 RD |
224 | self.textModified = true |
225 | evt.Skip() | |
f0c20d94 RD |
226 | def _defaultValue(self): |
227 | return ['12', 'default', 'normal', 'normal', '0', '', ''] | |
a40b5e84 RD |
228 | def GetValue(self): |
229 | if self.textModified: # text has newer value | |
f0c20d94 RD |
230 | try: |
231 | return eval(self.text.GetValue()) | |
232 | except SyntaxError: | |
233 | wxLogError('Syntax error in parameter value: ' + self.GetName()) | |
234 | return self._defaultValue() | |
a40b5e84 RD |
235 | return self.value |
236 | def SetValue(self, value): | |
32ce09e2 | 237 | self.freeze = true # disable other handlers |
f0c20d94 | 238 | if not value: value = self._defaultValue() |
a40b5e84 RD |
239 | self.value = value |
240 | self.text.SetValue(str(value)) # update text ctrl | |
32ce09e2 | 241 | self.freeze = false |
a40b5e84 RD |
242 | def OnButtonSelect(self, evt): |
243 | if self.textModified: # text has newer value | |
f0c20d94 RD |
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() | |
a40b5e84 | 249 | # Make initial font |
f0c20d94 RD |
250 | # Default values |
251 | size = 12 | |
252 | family = wxDEFAULT | |
253 | style = weight = wxNORMAL | |
254 | underlined = 0 | |
255 | face = '' | |
a40b5e84 | 256 | enc = wxFONTENCODING_DEFAULT |
f0c20d94 RD |
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') | |
a40b5e84 RD |
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) | |
32ce09e2 RD |
281 | if dlg.ShowModal() == wxID_OK: |
282 | font = dlg.GetFontData().GetChosenFont() | |
f0c20d94 RD |
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 | ] | |
32ce09e2 RD |
291 | # Add ignored flags |
292 | self.SetValue(value) | |
293 | self.SetModified() | |
294 | self.textModified = false | |
295 | dlg.Destroy() | |
a40b5e84 RD |
296 | |
297 | ################################################################################ | |
298 | ||
299 | class ParamInt(PPanel): | |
f0c20d94 RD |
300 | def __init__(self, parent, name): |
301 | PPanel.__init__(self, parent, name) | |
a40b5e84 | 302 | self.ID_SPIN_CTRL = wxNewId() |
09f3d4e6 | 303 | sizer = wxBoxSizer() |
32ce09e2 | 304 | self.spin = wxSpinCtrl(self, self.ID_SPIN_CTRL, size=wxSize(50,-1)) |
09f3d4e6 RD |
305 | self.SetBackgroundColour(panel.GetBackgroundColour()) |
306 | sizer.Add(self.spin) | |
307 | self.SetAutoLayout(true) | |
308 | self.SetSizer(sizer) | |
309 | sizer.Fit(self) | |
09f3d4e6 RD |
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): | |
32ce09e2 | 314 | self.freeze = true |
09f3d4e6 RD |
315 | if not value: value = 0 |
316 | self.spin.SetValue(int(value)) | |
32ce09e2 | 317 | self.freeze = false |
09f3d4e6 | 318 | def OnChange(self, evt): |
32ce09e2 RD |
319 | if self.freeze: return |
320 | self.SetModified() | |
09f3d4e6 RD |
321 | evt.Skip() |
322 | ||
32ce09e2 | 323 | class ParamText(PPanel): |
f0c20d94 RD |
324 | def __init__(self, parent, name, textWidth=200): |
325 | PPanel.__init__(self, parent, name) | |
32ce09e2 RD |
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 | |
09f3d4e6 | 342 | def OnChange(self, evt): |
32ce09e2 RD |
343 | if self.freeze: return |
344 | self.SetModified() | |
09f3d4e6 RD |
345 | evt.Skip() |
346 | ||
32ce09e2 | 347 | class ParamAccel(ParamText): |
f0c20d94 RD |
348 | def __init__(self, parent, name): |
349 | ParamText.__init__(self, parent, name, 50) | |
09f3d4e6 | 350 | |
32ce09e2 | 351 | class ParamPosSize(ParamText): |
f0c20d94 RD |
352 | def __init__(self, parent, name): |
353 | ParamText.__init__(self, parent, name, 80) | |
09f3d4e6 | 354 | |
f0c20d94 | 355 | class ContentDialog(wxDialogPtr): |
09f3d4e6 | 356 | def __init__(self, parent, value): |
f0c20d94 | 357 | # Is this normal??? |
18fc9fa3 | 358 | w = frame.res.LoadDialog(parent, 'DIALOG_CONTENT') |
f0c20d94 | 359 | wxDialogPtr.__init__(self, w.this) |
09f3d4e6 | 360 | self.thisown = 1 |
09f3d4e6 | 361 | self.Center() |
18fc9fa3 | 362 | self.list = self.FindWindowByName('LIST') |
09f3d4e6 RD |
363 | # Set list items |
364 | for v in value: | |
365 | self.list.Append(v) | |
a40b5e84 | 366 | self.SetAutoLayout(true) |
a40b5e84 | 367 | self.GetSizer().Fit(self) |
09f3d4e6 | 368 | # Callbacks |
18fc9fa3 RD |
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') | |
09f3d4e6 RD |
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: | |
a40b5e84 RD |
403 | evt.Enable(self.list.GetSelection() != -1 and \ |
404 | self.list.GetSelection() < self.list.Number() - 1) | |
09f3d4e6 | 405 | |
f0c20d94 RD |
406 | class ContentCheckListDialog(wxDialogPtr): |
407 | def __init__(self, parent, value): | |
408 | # Is this normal??? | |
18fc9fa3 | 409 | w = frame.res.LoadDialog(parent, 'DIALOG_CONTENT_CHECK_LIST') |
f0c20d94 RD |
410 | wxDialogPtr.__init__(self, w.this) |
411 | self.thisown = 1 | |
412 | self.Center() | |
18fc9fa3 | 413 | self.list = self.FindWindowByName('CHECK_LIST') |
f0c20d94 RD |
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 | |
18fc9fa3 RD |
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') | |
f0c20d94 RD |
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 | ||
a40b5e84 | 466 | class ParamContent(PPanel): |
f0c20d94 RD |
467 | def __init__(self, parent, name): |
468 | PPanel.__init__(self, parent, name) | |
a40b5e84 RD |
469 | self.ID_TEXT_CTRL = wxNewId() |
470 | self.ID_BUTTON_EDIT = wxNewId() | |
09f3d4e6 | 471 | self.SetBackgroundColour(panel.GetBackgroundColour()) |
09f3d4e6 | 472 | sizer = wxBoxSizer() |
32ce09e2 | 473 | self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1)) |
18fc9fa3 RD |
474 | sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5) |
475 | self.button = wxButton(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize) | |
32ce09e2 | 476 | sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL) |
09f3d4e6 RD |
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): | |
92631ff2 | 484 | if self.freeze: return |
32ce09e2 | 485 | self.SetModified() |
09f3d4e6 RD |
486 | self.textModified = true |
487 | evt.Skip() | |
488 | def GetValue(self): | |
489 | if self.textModified: # text has newer value | |
f0c20d94 RD |
490 | try: |
491 | return eval(self.text.GetValue()) | |
492 | except SyntaxError: | |
493 | wxLogError('Syntax error in parameter value: ' + self.GetName()) | |
494 | return [] | |
09f3d4e6 RD |
495 | return self.value |
496 | def SetValue(self, value): | |
32ce09e2 | 497 | self.freeze = true |
18fc9fa3 | 498 | if not value: value = [] |
09f3d4e6 RD |
499 | self.value = value |
500 | self.text.SetValue(str(value)) # update text ctrl | |
32ce09e2 | 501 | self.freeze = false |
09f3d4e6 RD |
502 | def OnButtonEdit(self, evt): |
503 | if self.textModified: # text has newer value | |
f0c20d94 RD |
504 | try: |
505 | self.value = eval(self.text.GetValue()) | |
506 | except SyntaxError: | |
507 | wxLogError('Syntax error in parameter value: ' + self.GetName()) | |
508 | self.value = [] | |
09f3d4e6 | 509 | dlg = ContentDialog(self, self.value) |
32ce09e2 RD |
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() | |
09f3d4e6 | 519 | |
f0c20d94 | 520 | # CheckList content |
18fc9fa3 | 521 | class ParamContentCheckList(ParamContent): |
f0c20d94 | 522 | def __init__(self, parent, name): |
18fc9fa3 RD |
523 | ParamContent.__init__(self, parent, name) |
524 | def OnButtonEdit(self, evt): | |
f0c20d94 RD |
525 | if self.textModified: # text has newer value |
526 | try: | |
18fc9fa3 | 527 | self.value = eval(self.text.GetValue()) |
f0c20d94 RD |
528 | except SyntaxError: |
529 | wxLogError('Syntax error in parameter value: ' + self.GetName()) | |
18fc9fa3 RD |
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) | |
f0c20d94 RD |
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 = [] | |
18fc9fa3 | 600 | dlg = IntListDialog(self, self.value) |
f0c20d94 RD |
601 | if dlg.ShowModal() == wxID_OK: |
602 | value = [] | |
603 | for i in range(dlg.list.Number()): | |
18fc9fa3 | 604 | value.append(int(dlg.list.GetString(i))) |
f0c20d94 RD |
605 | # Add ignored flags |
606 | self.SetValue(value) | |
607 | self.SetModified() | |
608 | self.textModified = false | |
609 | dlg.Destroy() | |
610 | ||
18fc9fa3 | 611 | # Boxless radiobox |
a40b5e84 | 612 | class RadioBox(PPanel): |
09f3d4e6 | 613 | def __init__(self, parent, id, choices, |
f0c20d94 RD |
614 | pos=wxDefaultPosition, name='radiobox'): |
615 | PPanel.__init__(self, parent, name) | |
09f3d4e6 RD |
616 | self.SetBackgroundColour(panel.GetBackgroundColour()) |
617 | self.choices = choices | |
618 | topSizer = wxBoxSizer() | |
619 | for i in choices: | |
32ce09e2 RD |
620 | button = wxRadioButton(self, -1, i, name=i) |
621 | topSizer.Add(button) | |
622 | EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice) | |
09f3d4e6 RD |
623 | self.SetAutoLayout(true) |
624 | self.SetSizer(topSizer) | |
625 | topSizer.Fit(self) | |
09f3d4e6 | 626 | def SetStringSelection(self, value): |
32ce09e2 | 627 | self.freeze = true |
09f3d4e6 | 628 | for i in self.choices: |
32ce09e2 | 629 | self.FindWindowByName(i).SetValue(i == value) |
09f3d4e6 | 630 | self.value = value |
32ce09e2 | 631 | self.freeze = false |
09f3d4e6 | 632 | def OnRadioChoice(self, evt): |
32ce09e2 RD |
633 | if self.freeze: return |
634 | if evt.GetSelection(): | |
635 | self.value = evt.GetEventObject().GetName() | |
636 | self.SetModified() | |
09f3d4e6 RD |
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'} | |
f0c20d94 RD |
643 | def __init__(self, parent, name): |
644 | RadioBox.__init__(self, parent, -1, choices = self.values.keys(), name=name) | |
09f3d4e6 RD |
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'} | |
f0c20d94 RD |
654 | def __init__(self, parent, name): |
655 | RadioBox.__init__(self, parent, -1, choices = self.values.keys(), name=name) | |
09f3d4e6 RD |
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 | ||
32ce09e2 | 662 | class ParamFile(PPanel): |
18fc9fa3 | 663 | def __init__(self, parent, name): |
f0c20d94 | 664 | PPanel.__init__(self, parent, name) |
32ce09e2 RD |
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)) | |
18fc9fa3 RD |
670 | sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5) |
671 | self.button = wxButton(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize) | |
32ce09e2 RD |
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): | |
18fc9fa3 | 680 | if self.freeze: return |
32ce09e2 RD |
681 | self.SetModified() |
682 | self.textModified = true | |
683 | evt.Skip() | |
684 | def GetValue(self): | |
685 | if self.textModified: # text has newer value | |
f0c20d94 | 686 | return self.text.GetValue() |
32ce09e2 RD |
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, | |
f0c20d94 | 697 | defaultDir = os.path.dirname(self.value), |
32ce09e2 RD |
698 | defaultFile = os.path.basename(self.value)) |
699 | if dlg.ShowModal() == wxID_OK: | |
700 | # Make relative | |
f0c20d94 RD |
701 | common = os.path.commonprefix([os.path.abspath(frame.dataFile), |
702 | dlg.GetPath()]) | |
32ce09e2 RD |
703 | self.SetValue(dlg.GetPath()[len(common):]) |
704 | self.SetModified() | |
705 | self.textModified = false | |
706 | dlg.Destroy() | |
707 | ||
09f3d4e6 RD |
708 | paramDict = { |
709 | 'flag': ParamFlag, | |
a40b5e84 | 710 | 'style': ParamStyle, 'exstyle': ParamExStyle, |
09f3d4e6 RD |
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, | |
a40b5e84 RD |
718 | 'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont, |
719 | 'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool, | |
32ce09e2 | 720 | 'tooltip': ParamText, 'bitmap': ParamFile, 'icon': ParamFile, |
09f3d4e6 | 721 | } |
a40b5e84 | 722 |