|
1 |
|
2 import os |
|
3 import types |
|
4 |
|
5 import wx |
|
6 import wx.lib.buttons |
|
7 |
|
8 from EditorPanel import EditorPanel |
|
9 |
|
10 from IDEFrame import TITLE, FILEMENU, PROJECTTREE, PAGETITLES |
|
11 |
|
12 from controls import TextCtrlAutoComplete |
|
13 from dialogs import BrowseValuesLibraryDialog |
|
14 from util.BitmapLibrary import GetBitmap |
|
15 |
|
16 if wx.Platform == '__WXMSW__': |
|
17 faces = { 'times': 'Times New Roman', |
|
18 'mono' : 'Courier New', |
|
19 'helv' : 'Arial', |
|
20 'other': 'Comic Sans MS', |
|
21 'size' : 16, |
|
22 } |
|
23 else: |
|
24 faces = { 'times': 'Times', |
|
25 'mono' : 'Courier', |
|
26 'helv' : 'Helvetica', |
|
27 'other': 'new century schoolbook', |
|
28 'size' : 18, |
|
29 } |
|
30 |
|
31 SCROLLBAR_UNIT = 10 |
|
32 WINDOW_COLOUR = wx.Colour(240, 240, 240) |
|
33 |
|
34 CWD = os.path.split(os.path.realpath(__file__))[0] |
|
35 |
|
36 def Bpath(*args): |
|
37 return os.path.join(CWD,*args) |
|
38 |
|
39 # Some helpers to tweak GenBitmapTextButtons |
|
40 # TODO: declare customized classes instead. |
|
41 gen_mini_GetBackgroundBrush = lambda obj:lambda dc: wx.Brush(obj.GetParent().GetBackgroundColour(), wx.SOLID) |
|
42 gen_textbutton_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenButton._GetLabelSize(obj)[:-1] + (False,)) |
|
43 |
|
44 def make_genbitmaptogglebutton_flat(button): |
|
45 button.GetBackgroundBrush = gen_mini_GetBackgroundBrush(button) |
|
46 button.labelDelta = 0 |
|
47 button.SetBezelWidth(0) |
|
48 button.SetUseFocusIndicator(False) |
|
49 |
|
50 # Patch wx.lib.imageutils so that gray is supported on alpha images |
|
51 import wx.lib.imageutils |
|
52 from wx.lib.imageutils import grayOut as old_grayOut |
|
53 def grayOut(anImage): |
|
54 if anImage.HasAlpha(): |
|
55 AlphaData = anImage.GetAlphaData() |
|
56 else : |
|
57 AlphaData = None |
|
58 |
|
59 old_grayOut(anImage) |
|
60 |
|
61 if AlphaData is not None: |
|
62 anImage.SetAlphaData(AlphaData) |
|
63 |
|
64 wx.lib.imageutils.grayOut = grayOut |
|
65 |
|
66 class GenBitmapTextButton(wx.lib.buttons.GenBitmapTextButton): |
|
67 def _GetLabelSize(self): |
|
68 """ used internally """ |
|
69 w, h = self.GetTextExtent(self.GetLabel()) |
|
70 if not self.bmpLabel: |
|
71 return w, h, False # if there isn't a bitmap use the size of the text |
|
72 |
|
73 w_bmp = self.bmpLabel.GetWidth()+2 |
|
74 h_bmp = self.bmpLabel.GetHeight()+2 |
|
75 height = h + h_bmp |
|
76 if w_bmp > w: |
|
77 width = w_bmp |
|
78 else: |
|
79 width = w |
|
80 return width, height, False |
|
81 |
|
82 def DrawLabel(self, dc, width, height, dw=0, dy=0): |
|
83 bmp = self.bmpLabel |
|
84 if bmp != None: # if the bitmap is used |
|
85 if self.bmpDisabled and not self.IsEnabled(): |
|
86 bmp = self.bmpDisabled |
|
87 if self.bmpFocus and self.hasFocus: |
|
88 bmp = self.bmpFocus |
|
89 if self.bmpSelected and not self.up: |
|
90 bmp = self.bmpSelected |
|
91 bw,bh = bmp.GetWidth(), bmp.GetHeight() |
|
92 if not self.up: |
|
93 dw = dy = self.labelDelta |
|
94 hasMask = bmp.GetMask() != None |
|
95 else: |
|
96 bw = bh = 0 # no bitmap -> size is zero |
|
97 |
|
98 dc.SetFont(self.GetFont()) |
|
99 if self.IsEnabled(): |
|
100 dc.SetTextForeground(self.GetForegroundColour()) |
|
101 else: |
|
102 dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) |
|
103 |
|
104 label = self.GetLabel() |
|
105 tw, th = dc.GetTextExtent(label) # size of text |
|
106 if not self.up: |
|
107 dw = dy = self.labelDelta |
|
108 |
|
109 pos_x = (width-bw)/2+dw # adjust for bitmap and text to centre |
|
110 pos_y = (height-bh-th)/2+dy |
|
111 if bmp !=None: |
|
112 dc.DrawBitmap(bmp, pos_x, pos_y, hasMask) # draw bitmap if available |
|
113 pos_x = (width-tw)/2+dw # adjust for bitmap and text to centre |
|
114 pos_y += bh + 2 |
|
115 |
|
116 dc.DrawText(label, pos_x, pos_y) # draw the text |
|
117 |
|
118 |
|
119 class GenStaticBitmap(wx.lib.statbmp.GenStaticBitmap): |
|
120 """ Customized GenStaticBitmap, fix transparency redraw bug on wx2.8/win32, |
|
121 and accept image name as __init__ parameter, fail silently if file do not exist""" |
|
122 def __init__(self, parent, ID, bitmapname, |
|
123 pos = wx.DefaultPosition, size = wx.DefaultSize, |
|
124 style = 0, |
|
125 name = "genstatbmp"): |
|
126 |
|
127 wx.lib.statbmp.GenStaticBitmap.__init__(self, parent, ID, |
|
128 GetBitmap(bitmapname), |
|
129 pos, size, |
|
130 style, |
|
131 name) |
|
132 |
|
133 def OnPaint(self, event): |
|
134 dc = wx.PaintDC(self) |
|
135 colour = self.GetParent().GetBackgroundColour() |
|
136 dc.SetPen(wx.Pen(colour)) |
|
137 dc.SetBrush(wx.Brush(colour )) |
|
138 dc.DrawRectangle(0, 0, *dc.GetSizeTuple()) |
|
139 if self._bitmap: |
|
140 dc.DrawBitmap(self._bitmap, 0, 0, True) |
|
141 |
|
142 class ConfTreeNodeEditor(EditorPanel): |
|
143 |
|
144 SHOW_BASE_PARAMS = True |
|
145 SHOW_PARAMS = True |
|
146 CONFNODEEDITOR_TABS = [] |
|
147 |
|
148 def _init_Editor(self, parent): |
|
149 tabs_num = len(self.CONFNODEEDITOR_TABS) |
|
150 if self.SHOW_PARAMS: |
|
151 tabs_num += 1 |
|
152 |
|
153 if tabs_num > 1: |
|
154 self.Editor = wx.Panel(parent, |
|
155 style=wx.SUNKEN_BORDER|wx.SP_3D) |
|
156 |
|
157 main_sizer = wx.BoxSizer(wx.VERTICAL) |
|
158 |
|
159 self.ConfNodeNoteBook = wx.Notebook(self.Editor) |
|
160 parent = self.ConfNodeNoteBook |
|
161 main_sizer.AddWindow(self.ConfNodeNoteBook, 1, flag=wx.GROW) |
|
162 |
|
163 self.Editor.SetSizer(main_sizer) |
|
164 else: |
|
165 self.ConfNodeNoteBook = None |
|
166 self.Editor = None |
|
167 |
|
168 for title, create_func_name in self.CONFNODEEDITOR_TABS: |
|
169 editor = getattr(self, create_func_name)(parent) |
|
170 if self.ConfNodeNoteBook is not None: |
|
171 self.ConfNodeNoteBook.AddPage(editor, title) |
|
172 else: |
|
173 self.Editor = editor |
|
174 |
|
175 if self.SHOW_PARAMS: |
|
176 |
|
177 panel_style = wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL |
|
178 if self.ConfNodeNoteBook is None: |
|
179 panel_style |= wx.SUNKEN_BORDER |
|
180 self.ParamsEditor = wx.ScrolledWindow(parent, |
|
181 style=panel_style) |
|
182 self.ParamsEditor.SetBackgroundColour(WINDOW_COLOUR) |
|
183 self.ParamsEditor.Bind(wx.EVT_SIZE, self.OnWindowResize) |
|
184 self.ParamsEditor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel) |
|
185 |
|
186 # Variable allowing disabling of ParamsEditor scroll when Popup shown |
|
187 self.ScrollingEnabled = True |
|
188 |
|
189 if self.SHOW_BASE_PARAMS: |
|
190 self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) |
|
191 self.ParamsEditorSizer.AddGrowableCol(0) |
|
192 self.ParamsEditorSizer.AddGrowableRow(1) |
|
193 |
|
194 self.ParamsEditor.SetSizer(self.ParamsEditorSizer) |
|
195 |
|
196 baseparamseditor_sizer = wx.BoxSizer(wx.HORIZONTAL) |
|
197 self.ParamsEditorSizer.AddSizer(baseparamseditor_sizer, border=5, |
|
198 flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP) |
|
199 |
|
200 self.FullIECChannel = wx.StaticText(self.ParamsEditor, -1) |
|
201 self.FullIECChannel.SetFont( |
|
202 wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, |
|
203 wx.BOLD, faceName = faces["helv"])) |
|
204 baseparamseditor_sizer.AddWindow(self.FullIECChannel, |
|
205 flag=wx.ALIGN_CENTER_VERTICAL) |
|
206 |
|
207 updownsizer = wx.BoxSizer(wx.VERTICAL) |
|
208 baseparamseditor_sizer.AddSizer(updownsizer, border=5, |
|
209 flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL) |
|
210 |
|
211 self.IECCUpButton = wx.lib.buttons.GenBitmapTextButton(self.ParamsEditor, |
|
212 bitmap=GetBitmap('IECCDown'), size=wx.Size(16, 16), style=wx.NO_BORDER) |
|
213 self.IECCUpButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(1), |
|
214 self.IECCUpButton) |
|
215 updownsizer.AddWindow(self.IECCUpButton, flag=wx.ALIGN_LEFT) |
|
216 |
|
217 self.IECCDownButton = wx.lib.buttons.GenBitmapButton(self.ParamsEditor, |
|
218 bitmap=GetBitmap('IECCUp'), size=wx.Size(16, 16), style=wx.NO_BORDER) |
|
219 self.IECCDownButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(-1), |
|
220 self.IECCDownButton) |
|
221 updownsizer.AddWindow(self.IECCDownButton, flag=wx.ALIGN_LEFT) |
|
222 |
|
223 self.ConfNodeName = wx.TextCtrl(self.ParamsEditor, |
|
224 size=wx.Size(150, 25), style=wx.NO_BORDER) |
|
225 self.ConfNodeName.SetFont( |
|
226 wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, |
|
227 wx.BOLD, faceName = faces["helv"])) |
|
228 self.ConfNodeName.Bind(wx.EVT_TEXT, |
|
229 self.GetTextCtrlCallBackFunction(self.ConfNodeName, "BaseParams.Name", True), |
|
230 self.ConfNodeName) |
|
231 baseparamseditor_sizer.AddWindow(self.ConfNodeName, border=5, |
|
232 flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) |
|
233 |
|
234 buttons_sizer = self.GenerateMethodButtonSizer() |
|
235 baseparamseditor_sizer.AddSizer(buttons_sizer, flag=wx.ALIGN_CENTER) |
|
236 |
|
237 else: |
|
238 self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=5) |
|
239 self.ParamsEditorSizer.AddGrowableCol(0) |
|
240 self.ParamsEditorSizer.AddGrowableRow(0) |
|
241 |
|
242 self.ConfNodeParamsSizer = wx.BoxSizer(wx.VERTICAL) |
|
243 self.ParamsEditorSizer.AddSizer(self.ConfNodeParamsSizer, border=5, |
|
244 flag=wx.LEFT|wx.RIGHT|wx.BOTTOM) |
|
245 |
|
246 self.RefreshConfNodeParamsSizer() |
|
247 |
|
248 if self.ConfNodeNoteBook is not None: |
|
249 self.ConfNodeNoteBook.AddPage(self.ParamsEditor, _("Config")) |
|
250 else: |
|
251 self.Editor = self.ParamsEditor |
|
252 else: |
|
253 self.ParamsEditor = None |
|
254 |
|
255 def __init__(self, parent, controler, window, tagname=""): |
|
256 EditorPanel.__init__(self, parent, tagname, window, controler) |
|
257 |
|
258 icon_name = self.Controler.GetIconName() |
|
259 if icon_name is not None: |
|
260 self.SetIcon(GetBitmap(icon_name)) |
|
261 else: |
|
262 self.SetIcon(GetBitmap("Extension")) |
|
263 |
|
264 def __del__(self): |
|
265 self.Controler.OnCloseEditor(self) |
|
266 |
|
267 def GetTagName(self): |
|
268 return self.Controler.CTNFullName() |
|
269 |
|
270 def GetTitle(self): |
|
271 fullname = self.Controler.CTNFullName() |
|
272 if self.Controler.CTNTestModified(): |
|
273 return "~%s~" % fullname |
|
274 return fullname |
|
275 |
|
276 def HasNoModel(self): |
|
277 return False |
|
278 |
|
279 def GetBufferState(self): |
|
280 return False, False |
|
281 |
|
282 def Undo(self): |
|
283 pass |
|
284 |
|
285 def Redo(self): |
|
286 pass |
|
287 |
|
288 def RefreshView(self): |
|
289 EditorPanel.RefreshView(self) |
|
290 if self.ParamsEditor is not None: |
|
291 if self.SHOW_BASE_PARAMS: |
|
292 self.ConfNodeName.ChangeValue(self.Controler.MandatoryParams[1].getName()) |
|
293 self.RefreshIECChannelControlsState() |
|
294 self.RefreshConfNodeParamsSizer() |
|
295 self.RefreshScrollbars() |
|
296 |
|
297 def EnableScrolling(self, enable): |
|
298 self.ScrollingEnabled = enable |
|
299 |
|
300 def RefreshIECChannelControlsState(self): |
|
301 self.FullIECChannel.SetLabel(self.Controler.GetFullIEC_Channel()) |
|
302 self.IECCDownButton.Enable(self.Controler.BaseParams.getIEC_Channel() > 0) |
|
303 |
|
304 def RefreshConfNodeParamsSizer(self): |
|
305 self.Freeze() |
|
306 self.ConfNodeParamsSizer.Clear(True) |
|
307 |
|
308 confnode_infos = self.Controler.GetParamsAttributes() |
|
309 if len(confnode_infos) > 0: |
|
310 self.GenerateSizerElements(self.ConfNodeParamsSizer, confnode_infos, None, False) |
|
311 |
|
312 self.ParamsEditorSizer.Layout() |
|
313 self.Thaw() |
|
314 |
|
315 def GenerateMethodButtonSizer(self): |
|
316 normal_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"]) |
|
317 mouseover_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, underline=True, faceName = faces["helv"]) |
|
318 |
|
319 msizer = wx.BoxSizer(wx.HORIZONTAL) |
|
320 |
|
321 for confnode_method in self.Controler.ConfNodeMethods: |
|
322 if "method" in confnode_method and confnode_method.get("shown",True): |
|
323 button = GenBitmapTextButton(self.ParamsEditor, |
|
324 bitmap=GetBitmap(confnode_method.get("bitmap", "Unknown")), |
|
325 label=confnode_method["name"], style=wx.NO_BORDER) |
|
326 button.SetFont(normal_bt_font) |
|
327 button.SetToolTipString(confnode_method["tooltip"]) |
|
328 if confnode_method.get("push", False): |
|
329 button.Bind(wx.EVT_LEFT_DOWN, self.GetButtonCallBackFunction(confnode_method["method"], True)) |
|
330 else: |
|
331 button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(confnode_method["method"]), button) |
|
332 # a fancy underline on mouseover |
|
333 def setFontStyle(b, s): |
|
334 def fn(event): |
|
335 b.SetFont(s) |
|
336 b.Refresh() |
|
337 event.Skip() |
|
338 return fn |
|
339 button.Bind(wx.EVT_ENTER_WINDOW, setFontStyle(button, mouseover_bt_font)) |
|
340 button.Bind(wx.EVT_LEAVE_WINDOW, setFontStyle(button, normal_bt_font)) |
|
341 #hack to force size to mini |
|
342 if not confnode_method.get("enabled",True): |
|
343 button.Disable() |
|
344 msizer.AddWindow(button, flag=wx.ALIGN_CENTER) |
|
345 return msizer |
|
346 |
|
347 def GenerateSizerElements(self, sizer, elements, path, clean = True): |
|
348 if clean: |
|
349 sizer.Clear(True) |
|
350 first = True |
|
351 for element_infos in elements: |
|
352 if path: |
|
353 element_path = "%s.%s"%(path, element_infos["name"]) |
|
354 else: |
|
355 element_path = element_infos["name"] |
|
356 if element_infos["type"] == "element": |
|
357 label = element_infos["name"] |
|
358 staticbox = wx.StaticBox(self.ParamsEditor, |
|
359 label=_(label), size=wx.Size(10, 0)) |
|
360 staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) |
|
361 if first: |
|
362 sizer.AddSizer(staticboxsizer, border=5, |
|
363 flag=wx.GROW|wx.TOP|wx.BOTTOM) |
|
364 else: |
|
365 sizer.AddSizer(staticboxsizer, border=5, |
|
366 flag=wx.GROW|wx.BOTTOM) |
|
367 self.GenerateSizerElements(staticboxsizer, |
|
368 element_infos["children"], |
|
369 element_path) |
|
370 else: |
|
371 boxsizer = wx.FlexGridSizer(cols=3, rows=1) |
|
372 boxsizer.AddGrowableCol(1) |
|
373 if first: |
|
374 sizer.AddSizer(boxsizer, border=5, |
|
375 flag=wx.GROW|wx.ALL) |
|
376 else: |
|
377 sizer.AddSizer(boxsizer, border=5, |
|
378 flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) |
|
379 |
|
380 staticbitmap = GenStaticBitmap(ID=-1, bitmapname=element_infos["name"], |
|
381 name="%s_bitmap"%element_infos["name"], parent=self.ParamsEditor, |
|
382 pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) |
|
383 boxsizer.AddWindow(staticbitmap, border=5, flag=wx.RIGHT) |
|
384 |
|
385 statictext = wx.StaticText(self.ParamsEditor, |
|
386 label="%s:"%_(element_infos["name"])) |
|
387 boxsizer.AddWindow(statictext, border=5, |
|
388 flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT) |
|
389 |
|
390 if isinstance(element_infos["type"], types.ListType): |
|
391 if isinstance(element_infos["value"], types.TupleType): |
|
392 browse_boxsizer = wx.BoxSizer(wx.HORIZONTAL) |
|
393 boxsizer.AddSizer(browse_boxsizer) |
|
394 |
|
395 textctrl = wx.TextCtrl(self.ParamsEditor, |
|
396 size=wx.Size(275, -1), style=wx.TE_READONLY) |
|
397 if element_infos["value"] is not None: |
|
398 textctrl.SetValue(element_infos["value"][0]) |
|
399 value_infos = element_infos["value"][1] |
|
400 else: |
|
401 value_infos = None |
|
402 browse_boxsizer.AddWindow(textctrl) |
|
403 |
|
404 button = wx.Button(self.ParamsEditor, |
|
405 label="...", size=wx.Size(25, 25)) |
|
406 browse_boxsizer.AddWindow(button) |
|
407 button.Bind(wx.EVT_BUTTON, |
|
408 self.GetBrowseCallBackFunction(element_infos["name"], textctrl, element_infos["type"], |
|
409 value_infos, element_path), |
|
410 button) |
|
411 else: |
|
412 combobox = wx.ComboBox(self.ParamsEditor, |
|
413 size=wx.Size(300, -1), style=wx.CB_READONLY) |
|
414 boxsizer.AddWindow(combobox) |
|
415 |
|
416 if element_infos["use"] == "optional": |
|
417 combobox.Append("") |
|
418 if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], types.TupleType): |
|
419 for choice, xsdclass in element_infos["type"]: |
|
420 combobox.Append(choice) |
|
421 name = element_infos["name"] |
|
422 value = element_infos["value"] |
|
423 |
|
424 staticbox = wx.StaticBox(self.ParamsEditor, |
|
425 label="%s - %s"%(_(name), _(value)), size=wx.Size(10, 0)) |
|
426 staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) |
|
427 sizer.AddSizer(staticboxsizer, border=5, flag=wx.GROW|wx.BOTTOM) |
|
428 self.GenerateSizerElements(staticboxsizer, element_infos["children"], element_path) |
|
429 callback = self.GetChoiceContentCallBackFunction(combobox, staticboxsizer, element_path) |
|
430 else: |
|
431 for choice in element_infos["type"]: |
|
432 combobox.Append(choice) |
|
433 callback = self.GetChoiceCallBackFunction(combobox, element_path) |
|
434 if element_infos["value"] is None: |
|
435 combobox.SetStringSelection("") |
|
436 else: |
|
437 combobox.SetStringSelection(element_infos["value"]) |
|
438 combobox.Bind(wx.EVT_COMBOBOX, callback, combobox) |
|
439 |
|
440 elif isinstance(element_infos["type"], types.DictType): |
|
441 scmin = -(2**31) |
|
442 scmax = 2**31-1 |
|
443 if "min" in element_infos["type"]: |
|
444 scmin = element_infos["type"]["min"] |
|
445 if "max" in element_infos["type"]: |
|
446 scmax = element_infos["type"]["max"] |
|
447 spinctrl = wx.SpinCtrl(self.ParamsEditor, |
|
448 size=wx.Size(300, -1), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) |
|
449 spinctrl.SetRange(scmin, scmax) |
|
450 boxsizer.AddWindow(spinctrl) |
|
451 if element_infos["value"] is not None: |
|
452 spinctrl.SetValue(element_infos["value"]) |
|
453 spinctrl.Bind(wx.EVT_SPINCTRL, |
|
454 self.GetTextCtrlCallBackFunction(spinctrl, element_path), |
|
455 spinctrl) |
|
456 |
|
457 else: |
|
458 if element_infos["type"] == "boolean": |
|
459 checkbox = wx.CheckBox(self.ParamsEditor, size=wx.Size(17, 25)) |
|
460 boxsizer.AddWindow(checkbox) |
|
461 if element_infos["value"] is not None: |
|
462 checkbox.SetValue(element_infos["value"]) |
|
463 checkbox.Bind(wx.EVT_CHECKBOX, |
|
464 self.GetCheckBoxCallBackFunction(checkbox, element_path), |
|
465 checkbox) |
|
466 |
|
467 elif element_infos["type"] in ["unsignedLong", "long","integer"]: |
|
468 if element_infos["type"].startswith("unsigned"): |
|
469 scmin = 0 |
|
470 else: |
|
471 scmin = -(2**31) |
|
472 scmax = 2**31-1 |
|
473 spinctrl = wx.SpinCtrl(self.ParamsEditor, |
|
474 size=wx.Size(300, -1), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) |
|
475 spinctrl.SetRange(scmin, scmax) |
|
476 boxsizer.AddWindow(spinctrl) |
|
477 if element_infos["value"] is not None: |
|
478 spinctrl.SetValue(element_infos["value"]) |
|
479 spinctrl.Bind(wx.EVT_SPINCTRL, |
|
480 self.GetTextCtrlCallBackFunction(spinctrl, element_path), |
|
481 spinctrl) |
|
482 |
|
483 else: |
|
484 choices = self.ParentWindow.GetConfigEntry(element_path, [""]) |
|
485 textctrl = TextCtrlAutoComplete(name=element_infos["name"], |
|
486 parent=self.ParamsEditor, |
|
487 appframe=self, |
|
488 choices=choices, |
|
489 element_path=element_path, |
|
490 size=wx.Size(300, -1)) |
|
491 |
|
492 boxsizer.AddWindow(textctrl) |
|
493 if element_infos["value"] is not None: |
|
494 textctrl.ChangeValue(str(element_infos["value"])) |
|
495 textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, element_path)) |
|
496 first = False |
|
497 |
|
498 |
|
499 def GetItemChannelChangedFunction(self, dir): |
|
500 def OnConfNodeTreeItemChannelChanged(event): |
|
501 confnode_IECChannel = self.Controler.BaseParams.getIEC_Channel() |
|
502 res = self.SetConfNodeParamsAttribute("BaseParams.IEC_Channel", confnode_IECChannel + dir) |
|
503 wx.CallAfter(self.RefreshIECChannelControlsState) |
|
504 wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE) |
|
505 wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName()) |
|
506 event.Skip() |
|
507 return OnConfNodeTreeItemChannelChanged |
|
508 |
|
509 def SetConfNodeParamsAttribute(self, *args, **kwargs): |
|
510 res, StructChanged = self.Controler.SetParamsAttribute(*args, **kwargs) |
|
511 if StructChanged: |
|
512 wx.CallAfter(self.RefreshConfNodeParamsSizer) |
|
513 wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU) |
|
514 return res |
|
515 |
|
516 def GetButtonCallBackFunction(self, method, push=False): |
|
517 """ Generate the callbackfunc for a given confnode method""" |
|
518 def OnButtonClick(event): |
|
519 # Disable button to prevent re-entrant call |
|
520 event.GetEventObject().Disable() |
|
521 # Call |
|
522 getattr(self.Controler,method)() |
|
523 # Re-enable button |
|
524 event.GetEventObject().Enable() |
|
525 |
|
526 if not push: |
|
527 event.Skip() |
|
528 return OnButtonClick |
|
529 |
|
530 def GetChoiceCallBackFunction(self, choicectrl, path): |
|
531 def OnChoiceChanged(event): |
|
532 res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection()) |
|
533 choicectrl.SetStringSelection(res) |
|
534 event.Skip() |
|
535 return OnChoiceChanged |
|
536 |
|
537 def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, path): |
|
538 def OnChoiceContentChanged(event): |
|
539 res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection()) |
|
540 wx.CallAfter(self.RefreshConfNodeParamsSizer) |
|
541 event.Skip() |
|
542 return OnChoiceContentChanged |
|
543 |
|
544 def GetTextCtrlCallBackFunction(self, textctrl, path, refresh=False): |
|
545 def OnTextCtrlChanged(event): |
|
546 res = self.SetConfNodeParamsAttribute(path, textctrl.GetValue()) |
|
547 if res != textctrl.GetValue(): |
|
548 if isinstance(textctrl, wx.SpinCtrl): |
|
549 textctrl.SetValue(res) |
|
550 else: |
|
551 textctrl.ChangeValue(res) |
|
552 if refresh: |
|
553 wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE, PAGETITLES) |
|
554 wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName()) |
|
555 event.Skip() |
|
556 return OnTextCtrlChanged |
|
557 |
|
558 def GetCheckBoxCallBackFunction(self, chkbx, path): |
|
559 def OnCheckBoxChanged(event): |
|
560 res = self.SetConfNodeParamsAttribute(path, chkbx.IsChecked()) |
|
561 chkbx.SetValue(res) |
|
562 event.Skip() |
|
563 return OnCheckBoxChanged |
|
564 |
|
565 def GetBrowseCallBackFunction(self, name, textctrl, library, value_infos, path): |
|
566 infos = [value_infos] |
|
567 def OnBrowseButton(event): |
|
568 dialog = BrowseValuesLibraryDialog(self, name, library, infos[0]) |
|
569 if dialog.ShowModal() == wx.ID_OK: |
|
570 value, value_infos = self.SetConfNodeParamsAttribute(path, dialog.GetValueInfos()) |
|
571 textctrl.ChangeValue(value) |
|
572 infos[0] = value_infos |
|
573 dialog.Destroy() |
|
574 event.Skip() |
|
575 return OnBrowseButton |
|
576 |
|
577 def RefreshScrollbars(self): |
|
578 self.ParamsEditor.GetBestSize() |
|
579 xstart, ystart = self.ParamsEditor.GetViewStart() |
|
580 window_size = self.ParamsEditor.GetClientSize() |
|
581 maxx, maxy = self.ParamsEditorSizer.GetMinSize() |
|
582 posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT)) |
|
583 posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT)) |
|
584 self.ParamsEditor.Scroll(posx, posy) |
|
585 self.ParamsEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, |
|
586 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy) |
|
587 |
|
588 def OnWindowResize(self, event): |
|
589 self.RefreshScrollbars() |
|
590 event.Skip() |
|
591 |
|
592 def OnMouseWheel(self, event): |
|
593 if self.ScrollingEnabled: |
|
594 event.Skip() |
|
595 |