738
|
1 |
|
|
2 |
import os
|
|
3 |
import types
|
|
4 |
|
|
5 |
import wx
|
|
6 |
import wx.lib.buttons
|
|
7 |
|
|
8 |
from controls import EditorPanel
|
|
9 |
|
|
10 |
from PLCOpenEditor import TITLE, FILEMENU, PROJECTTREE, PAGETITLES
|
|
11 |
|
|
12 |
from util import opjimg
|
|
13 |
from util.TextCtrlAutoComplete import TextCtrlAutoComplete
|
|
14 |
from util.BrowseValuesLibraryDialog import BrowseValuesLibraryDialog
|
|
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 |
bitmappath = Bpath( "images", bitmapname)
|
|
128 |
if os.path.isfile(bitmappath):
|
|
129 |
bitmap = wx.Bitmap(bitmappath)
|
|
130 |
else:
|
|
131 |
bitmap = None
|
|
132 |
wx.lib.statbmp.GenStaticBitmap.__init__(self, parent, ID, bitmap,
|
|
133 |
pos, size,
|
|
134 |
style,
|
|
135 |
name)
|
|
136 |
|
|
137 |
def OnPaint(self, event):
|
|
138 |
dc = wx.PaintDC(self)
|
|
139 |
colour = self.GetParent().GetBackgroundColour()
|
|
140 |
dc.SetPen(wx.Pen(colour))
|
|
141 |
dc.SetBrush(wx.Brush(colour ))
|
|
142 |
dc.DrawRectangle(0, 0, *dc.GetSizeTuple())
|
|
143 |
if self._bitmap:
|
|
144 |
dc.DrawBitmap(self._bitmap, 0, 0, True)
|
|
145 |
|
|
146 |
class ConfTreeNodeEditor(EditorPanel):
|
|
147 |
|
|
148 |
HAS_BASE_PARAMS = True
|
|
149 |
|
|
150 |
def _init_ConfNodeEditor(self, prnt):
|
|
151 |
self.ConfNodeEditor = None
|
|
152 |
|
|
153 |
def _init_Editor(self, prnt):
|
|
154 |
self.Editor = wx.SplitterWindow(id=self.ID, name='EditorSplitter', parent=prnt,
|
|
155 |
size=wx.Size(0, 0), style=wx.SUNKEN_BORDER|wx.SP_3D)
|
|
156 |
self.SetNeedUpdating(True)
|
|
157 |
self.SetMinimumPaneSize(1)
|
|
158 |
|
|
159 |
self.ParamsEditor = wx.ScrolledWindow(self.Editor, -1, size=wx.Size(-1, -1),
|
|
160 |
style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL)
|
|
161 |
self.ParamsEditor.SetBackgroundColour(WINDOW_COLOUR)
|
|
162 |
self.ParamsEditor.Bind(wx.EVT_SIZE, self.OnWindowResize)
|
|
163 |
self.ParamsEditor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
|
|
164 |
|
|
165 |
# Variable allowing disabling of ParamsEditor scroll when Popup shown
|
|
166 |
self.ScrollingEnabled = True
|
|
167 |
|
|
168 |
self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
|
|
169 |
self.ParamsEditorSizer.AddGrowableCol(0)
|
|
170 |
self.ParamsEditorSizer.AddGrowableRow(1)
|
|
171 |
|
|
172 |
self.ParamsEditor.SetSizer(self.ParamsEditorSizer)
|
|
173 |
|
|
174 |
baseparamseditor_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
175 |
self.ParamsEditorSizer.AddSizer(baseparamseditor_sizer, 0, border=5,
|
|
176 |
flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP)
|
|
177 |
|
|
178 |
self.FullIECChannel = wx.StaticText(self.ParamsEditor, -1)
|
|
179 |
self.FullIECChannel.SetFont(
|
|
180 |
wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL,
|
|
181 |
wx.BOLD, faceName = faces["helv"]))
|
|
182 |
baseparamseditor_sizer.AddWindow(self.FullIECChannel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL)
|
|
183 |
|
|
184 |
updownsizer = wx.BoxSizer(wx.VERTICAL)
|
|
185 |
baseparamseditor_sizer.AddSizer(updownsizer, 0, border=5,
|
|
186 |
flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL)
|
|
187 |
|
|
188 |
ieccdownbutton_id = wx.NewId()
|
|
189 |
self.IECCDownButton = wx.lib.buttons.GenBitmapButton(
|
|
190 |
id=ieccdownbutton_id, bitmap=wx.Bitmap(opjimg('IECCDown')),
|
|
191 |
name='IECDownButton', parent=self.ParamsEditor, pos=wx.Point(0, 0),
|
|
192 |
size=wx.Size(16, 16), style=wx.NO_BORDER)
|
|
193 |
self.IECCDownButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(-1),
|
|
194 |
id=ieccdownbutton_id)
|
|
195 |
updownsizer.AddWindow(self.IECCDownButton, 0, border=0, flag=wx.ALIGN_LEFT)
|
|
196 |
|
|
197 |
ieccupbutton_id = wx.NewId()
|
|
198 |
self.IECCUpButton = wx.lib.buttons.GenBitmapTextButton(
|
|
199 |
id=ieccupbutton_id, bitmap=wx.Bitmap(opjimg('IECCUp')),
|
|
200 |
name='IECUpButton', parent=self.ParamsEditor, pos=wx.Point(0, 0),
|
|
201 |
size=wx.Size(16, 16), style=wx.NO_BORDER)
|
|
202 |
self.IECCUpButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(1),
|
|
203 |
id=ieccupbutton_id)
|
|
204 |
updownsizer.AddWindow(self.IECCUpButton, 0, border=0, flag=wx.ALIGN_LEFT)
|
|
205 |
|
|
206 |
self.RefreshIECChannelControlsState()
|
|
207 |
|
|
208 |
confnodename_id = wx.NewId()
|
|
209 |
self.ConfNodeName = wx.TextCtrl(
|
|
210 |
self.ParamsEditor, confnodename_id,
|
|
211 |
size=wx.Size(150, 25), style=wx.NO_BORDER)
|
|
212 |
self.ConfNodeName.SetFont(
|
|
213 |
wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL,
|
|
214 |
wx.BOLD, faceName = faces["helv"]))
|
|
215 |
self.ConfNodeName.ChangeValue(self.Controler.MandatoryParams[1].getName())
|
|
216 |
self.ConfNodeName.Bind(wx.EVT_TEXT,
|
|
217 |
self.GetTextCtrlCallBackFunction(self.ConfNodeName, "BaseParams.Name"),
|
|
218 |
id=confnodename_id)
|
|
219 |
baseparamseditor_sizer.AddWindow(self.ConfNodeName, 0, border=5, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
|
|
220 |
|
|
221 |
buttons_sizer = self.GenerateMethodButtonSizer()
|
|
222 |
baseparamseditor_sizer.AddSizer(buttons_sizer, 0, border=0, flag=wx.ALIGN_CENTER)
|
|
223 |
|
|
224 |
self.ConfNodeParamsSizer = wx.BoxSizer(wx.VERTICAL)
|
|
225 |
self.ParamsEditorSizer.AddSizer(self.ConfNodeParamsSizer, 0, border=5,
|
|
226 |
flag=wx.LEFT|wx.RIGHT|wx.BOTTOM)
|
|
227 |
|
|
228 |
self.RefreshConfNodeParamsSizer()
|
|
229 |
|
|
230 |
self._init_ConfNodeEditor(self.Editor)
|
|
231 |
|
|
232 |
if self.ConfNodeEditor is not None:
|
|
233 |
min_size = self.ParamsEditorSizer.GetMinSize()
|
|
234 |
self.Editor.SplitHorizontally(self.ParamsEditor,
|
|
235 |
self.ConfNodeEditor,
|
|
236 |
min(min_size.height, 200))
|
|
237 |
else:
|
|
238 |
self.Editor.Initialize(self.ParamsEditor)
|
|
239 |
|
|
240 |
def __init__(self, parent, tagname, controler, window):
|
|
241 |
EditorPanel.__init__(self, parent, tagname, window, controler)
|
|
242 |
|
|
243 |
self.SetIcon(wx.Bitmap(self.Controler.GetIconPath(), wx.BITMAP_TYPE_PNG))
|
|
244 |
|
|
245 |
def __del__(self):
|
|
246 |
self.Controler.OnCloseEditor(self)
|
|
247 |
|
|
248 |
def GetTagName(self):
|
|
249 |
return self.Controler.CTNFullName()
|
|
250 |
|
|
251 |
def GetTitle(self):
|
|
252 |
fullname = self.Controler.CTNFullName()
|
|
253 |
if self.Controler.CTNTestModified():
|
|
254 |
return "~%s~" % fullname
|
|
255 |
return fullname
|
|
256 |
|
|
257 |
def HasNoModel(self):
|
|
258 |
return False
|
|
259 |
|
|
260 |
def EnableScrolling(self, enable):
|
|
261 |
self.ScrollingEnabled = enable
|
|
262 |
|
|
263 |
def RefreshIECChannelControlsState(self):
|
|
264 |
self.FullIECChannel.SetLabel(self.Controler.GetFullIEC_Channel())
|
|
265 |
self.IECCDownButton.Enable(self.Controler.BaseParams.getIEC_Channel() > 0)
|
|
266 |
|
|
267 |
def RefreshConfNodeParamsSizer(self):
|
|
268 |
self.Freeze()
|
|
269 |
self.ConfNodeParamsSizer.Clear(True)
|
|
270 |
|
|
271 |
confnode_infos = self.Controler.GetParamsAttributes()
|
|
272 |
if len(confnode_infos) > 0:
|
|
273 |
self.GenerateSizerElements(self.ConfNodeParamsSizer, confnode_infos, None, False)
|
|
274 |
|
|
275 |
self.ParamsEditorSizer.Layout()
|
|
276 |
self.Thaw()
|
|
277 |
|
|
278 |
def GenerateMethodButtonSizer(self):
|
|
279 |
normal_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"])
|
|
280 |
mouseover_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, underline=True, faceName = faces["helv"])
|
|
281 |
|
|
282 |
msizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
283 |
|
|
284 |
for confnode_method in self.Controler.ConfNodeMethods:
|
|
285 |
if "method" in confnode_method and confnode_method.get("shown",True):
|
|
286 |
id = wx.NewId()
|
|
287 |
label = confnode_method["name"]
|
|
288 |
button = GenBitmapTextButton(id=id, parent=self.ParamsEditor,
|
|
289 |
bitmap=wx.Bitmap(Bpath("images", "%s.png"%confnode_method.get("bitmap", "Unknown"))), label=label,
|
|
290 |
name=label, pos=wx.DefaultPosition, style=wx.NO_BORDER)
|
|
291 |
button.SetFont(normal_bt_font)
|
|
292 |
button.SetToolTipString(confnode_method["tooltip"])
|
|
293 |
button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(confnode_method["method"]), id=id)
|
|
294 |
# a fancy underline on mouseover
|
|
295 |
def setFontStyle(b, s):
|
|
296 |
def fn(event):
|
|
297 |
b.SetFont(s)
|
|
298 |
b.Refresh()
|
|
299 |
event.Skip()
|
|
300 |
return fn
|
|
301 |
button.Bind(wx.EVT_ENTER_WINDOW, setFontStyle(button, mouseover_bt_font))
|
|
302 |
button.Bind(wx.EVT_LEAVE_WINDOW, setFontStyle(button, normal_bt_font))
|
|
303 |
#hack to force size to mini
|
|
304 |
if not confnode_method.get("enabled",True):
|
|
305 |
button.Disable()
|
|
306 |
msizer.AddWindow(button, 0, border=0, flag=wx.ALIGN_CENTER)
|
|
307 |
return msizer
|
|
308 |
|
|
309 |
def GenerateSizerElements(self, sizer, elements, path, clean = True):
|
|
310 |
if clean:
|
|
311 |
sizer.Clear(True)
|
|
312 |
first = True
|
|
313 |
for element_infos in elements:
|
|
314 |
if path:
|
|
315 |
element_path = "%s.%s"%(path, element_infos["name"])
|
|
316 |
else:
|
|
317 |
element_path = element_infos["name"]
|
|
318 |
if element_infos["type"] == "element":
|
|
319 |
label = element_infos["name"]
|
|
320 |
staticbox = wx.StaticBox(id=-1, label=_(label),
|
|
321 |
name='%s_staticbox'%element_infos["name"], parent=self.ParamsEditor,
|
|
322 |
pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0)
|
|
323 |
staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL)
|
|
324 |
if first:
|
|
325 |
sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW|wx.TOP)
|
|
326 |
else:
|
|
327 |
sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW)
|
|
328 |
self.GenerateSizerElements(staticboxsizer, element_infos["children"], element_path)
|
|
329 |
else:
|
|
330 |
boxsizer = wx.FlexGridSizer(cols=3, rows=1)
|
|
331 |
boxsizer.AddGrowableCol(1)
|
|
332 |
if first:
|
|
333 |
sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL)
|
|
334 |
else:
|
|
335 |
sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
|
|
336 |
staticbitmap = GenStaticBitmap(ID=-1, bitmapname="%s.png"%element_infos["name"],
|
|
337 |
name="%s_bitmap"%element_infos["name"], parent=self.ParamsEditor,
|
|
338 |
pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0)
|
|
339 |
boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT)
|
|
340 |
label = element_infos["name"]
|
|
341 |
statictext = wx.StaticText(id=-1, label="%s:"%_(label),
|
|
342 |
name="%s_label"%element_infos["name"], parent=self.ParamsEditor,
|
|
343 |
pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
|
|
344 |
boxsizer.AddWindow(statictext, 0, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT)
|
|
345 |
id = wx.NewId()
|
|
346 |
if isinstance(element_infos["type"], types.ListType):
|
|
347 |
if isinstance(element_infos["value"], types.TupleType):
|
|
348 |
browse_boxsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
349 |
boxsizer.AddSizer(browse_boxsizer, 0, border=0, flag=0)
|
|
350 |
|
|
351 |
textctrl = wx.TextCtrl(id=id, name=element_infos["name"], parent=self.ParamsEditor,
|
|
352 |
pos=wx.Point(0, 0), size=wx.Size(275, 25), style=wx.TE_READONLY)
|
|
353 |
if element_infos["value"] is not None:
|
|
354 |
textctrl.SetValue(element_infos["value"][0])
|
|
355 |
value_infos = element_infos["value"][1]
|
|
356 |
else:
|
|
357 |
value_infos = None
|
|
358 |
browse_boxsizer.AddWindow(textctrl, 0, border=0, flag=0)
|
|
359 |
button_id = wx.NewId()
|
|
360 |
button = wx.Button(id=button_id, name="browse_%s" % element_infos["name"], parent=self.ParamsEditor,
|
|
361 |
label="...", pos=wx.Point(0, 0), size=wx.Size(25, 25))
|
|
362 |
browse_boxsizer.AddWindow(button, 0, border=0, flag=0)
|
|
363 |
button.Bind(wx.EVT_BUTTON,
|
|
364 |
self.GetBrowseCallBackFunction(element_infos["name"], textctrl, element_infos["type"],
|
|
365 |
value_infos, element_path),
|
|
366 |
id=button_id)
|
|
367 |
else:
|
|
368 |
combobox = wx.ComboBox(id=id, name=element_infos["name"], parent=self.ParamsEditor,
|
|
369 |
pos=wx.Point(0, 0), size=wx.Size(300, 28), style=wx.CB_READONLY)
|
|
370 |
boxsizer.AddWindow(combobox, 0, border=0, flag=0)
|
|
371 |
if element_infos["use"] == "optional":
|
|
372 |
combobox.Append("")
|
|
373 |
if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], types.TupleType):
|
|
374 |
for choice, xsdclass in element_infos["type"]:
|
|
375 |
combobox.Append(choice)
|
|
376 |
name = element_infos["name"]
|
|
377 |
value = element_infos["value"]
|
|
378 |
staticbox = wx.StaticBox(id=-1, label="%s - %s"%(_(name), _(value)),
|
|
379 |
name='%s_staticbox'%element_infos["name"], parent=self.ParamsEditor,
|
|
380 |
pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0)
|
|
381 |
staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL)
|
|
382 |
sizer.AddSizer(staticboxsizer, 0, border=5, flag=wx.GROW|wx.BOTTOM)
|
|
383 |
self.GenerateSizerElements(staticboxsizer, element_infos["children"], element_path)
|
|
384 |
callback = self.GetChoiceContentCallBackFunction(combobox, staticboxsizer, element_path)
|
|
385 |
else:
|
|
386 |
for choice in element_infos["type"]:
|
|
387 |
combobox.Append(choice)
|
|
388 |
callback = self.GetChoiceCallBackFunction(combobox, element_path)
|
|
389 |
if element_infos["value"] is None:
|
|
390 |
combobox.SetStringSelection("")
|
|
391 |
else:
|
|
392 |
combobox.SetStringSelection(element_infos["value"])
|
|
393 |
combobox.Bind(wx.EVT_COMBOBOX, callback, id=id)
|
|
394 |
elif isinstance(element_infos["type"], types.DictType):
|
|
395 |
scmin = -(2**31)
|
|
396 |
scmax = 2**31-1
|
|
397 |
if "min" in element_infos["type"]:
|
|
398 |
scmin = element_infos["type"]["min"]
|
|
399 |
if "max" in element_infos["type"]:
|
|
400 |
scmax = element_infos["type"]["max"]
|
|
401 |
spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=self.ParamsEditor,
|
|
402 |
pos=wx.Point(0, 0), size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT)
|
|
403 |
spinctrl.SetRange(scmin,scmax)
|
|
404 |
boxsizer.AddWindow(spinctrl, 0, border=0, flag=0)
|
|
405 |
if element_infos["value"] is not None:
|
|
406 |
spinctrl.SetValue(element_infos["value"])
|
|
407 |
spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, element_path), id=id)
|
|
408 |
else:
|
|
409 |
if element_infos["type"] == "boolean":
|
|
410 |
checkbox = wx.CheckBox(id=id, name=element_infos["name"], parent=self.ParamsEditor,
|
|
411 |
pos=wx.Point(0, 0), size=wx.Size(17, 25), style=0)
|
|
412 |
boxsizer.AddWindow(checkbox, 0, border=0, flag=0)
|
|
413 |
if element_infos["value"] is not None:
|
|
414 |
checkbox.SetValue(element_infos["value"])
|
|
415 |
checkbox.Bind(wx.EVT_CHECKBOX, self.GetCheckBoxCallBackFunction(checkbox, element_path), id=id)
|
|
416 |
elif element_infos["type"] in ["unsignedLong", "long","integer"]:
|
|
417 |
if element_infos["type"].startswith("unsigned"):
|
|
418 |
scmin = 0
|
|
419 |
else:
|
|
420 |
scmin = -(2**31)
|
|
421 |
scmax = 2**31-1
|
|
422 |
spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=self.ParamsEditor,
|
|
423 |
pos=wx.Point(0, 0), size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT)
|
|
424 |
spinctrl.SetRange(scmin, scmax)
|
|
425 |
boxsizer.AddWindow(spinctrl, 0, border=0, flag=0)
|
|
426 |
if element_infos["value"] is not None:
|
|
427 |
spinctrl.SetValue(element_infos["value"])
|
|
428 |
spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, element_path), id=id)
|
|
429 |
else:
|
|
430 |
choices = self.ParentWindow.GetConfigEntry(element_path, [""])
|
|
431 |
textctrl = TextCtrlAutoComplete(id=id,
|
|
432 |
name=element_infos["name"],
|
|
433 |
parent=self.ParamsEditor,
|
|
434 |
appframe=self,
|
|
435 |
choices=choices,
|
|
436 |
element_path=element_path,
|
|
437 |
pos=wx.Point(0, 0),
|
|
438 |
size=wx.Size(300, 25),
|
|
439 |
style=0)
|
|
440 |
|
|
441 |
boxsizer.AddWindow(textctrl, 0, border=0, flag=0)
|
|
442 |
if element_infos["value"] is not None:
|
|
443 |
textctrl.ChangeValue(str(element_infos["value"]))
|
|
444 |
textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, element_path))
|
|
445 |
first = False
|
|
446 |
|
|
447 |
|
|
448 |
def GetItemChannelChangedFunction(self, dir):
|
|
449 |
def OnConfNodeTreeItemChannelChanged(event):
|
|
450 |
confnode_IECChannel = self.Controler.BaseParams.getIEC_Channel()
|
|
451 |
res = self.SetConfNodeParamsAttribute("BaseParams.IEC_Channel", confnode_IECChannel + dir)
|
|
452 |
wx.CallAfter(self.RefreshIECChannelControlsState)
|
|
453 |
wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE)
|
|
454 |
wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName())
|
|
455 |
event.Skip()
|
|
456 |
return OnConfNodeTreeItemChannelChanged
|
|
457 |
|
|
458 |
def SetConfNodeParamsAttribute(self, *args, **kwargs):
|
|
459 |
res, StructChanged = self.Controler.SetParamsAttribute(*args, **kwargs)
|
|
460 |
if StructChanged:
|
|
461 |
wx.CallAfter(self.RefreshConfNodeParamsSizer)
|
|
462 |
wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU)
|
|
463 |
return res
|
|
464 |
|
|
465 |
def GetButtonCallBackFunction(self, method):
|
|
466 |
""" Generate the callbackfunc for a given confnode method"""
|
|
467 |
def OnButtonClick(event):
|
|
468 |
# Disable button to prevent re-entrant call
|
|
469 |
event.GetEventObject().Disable()
|
|
470 |
# Call
|
|
471 |
getattr(self.Controler,method)()
|
|
472 |
# Re-enable button
|
|
473 |
event.GetEventObject().Enable()
|
|
474 |
|
|
475 |
event.Skip()
|
|
476 |
return OnButtonClick
|
|
477 |
|
|
478 |
def GetChoiceCallBackFunction(self, choicectrl, path):
|
|
479 |
def OnChoiceChanged(event):
|
|
480 |
res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection())
|
|
481 |
choicectrl.SetStringSelection(res)
|
|
482 |
event.Skip()
|
|
483 |
return OnChoiceChanged
|
|
484 |
|
|
485 |
def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, path):
|
|
486 |
def OnChoiceContentChanged(event):
|
|
487 |
res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection())
|
|
488 |
event.Skip()
|
|
489 |
return OnChoiceContentChanged
|
|
490 |
|
|
491 |
def GetTextCtrlCallBackFunction(self, textctrl, path):
|
|
492 |
def OnTextCtrlChanged(event):
|
|
493 |
res = self.SetConfNodeParamsAttribute(path, textctrl.GetValue())
|
|
494 |
if res != textctrl.GetValue():
|
|
495 |
textctrl.ChangeValue(res)
|
|
496 |
if textctrl == self.ConfNodeName:
|
|
497 |
wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE, PAGETITLES)
|
|
498 |
wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName())
|
|
499 |
event.Skip()
|
|
500 |
return OnTextCtrlChanged
|
|
501 |
|
|
502 |
def GetCheckBoxCallBackFunction(self, chkbx, path):
|
|
503 |
def OnCheckBoxChanged(event):
|
|
504 |
res = self.SetConfNodeParamsAttribute(path, chkbx.IsChecked())
|
|
505 |
chkbx.SetValue(res)
|
|
506 |
event.Skip()
|
|
507 |
return OnCheckBoxChanged
|
|
508 |
|
|
509 |
def GetBrowseCallBackFunction(self, name, textctrl, library, value_infos, path):
|
|
510 |
infos = [value_infos]
|
|
511 |
def OnBrowseButton(event):
|
|
512 |
dialog = BrowseValuesLibraryDialog(self, name, library, infos[0])
|
|
513 |
if dialog.ShowModal() == wx.ID_OK:
|
|
514 |
value, value_infos = self.SetConfNodeParamsAttribute(path, dialog.GetValueInfos())
|
|
515 |
textctrl.ChangeValue(value)
|
|
516 |
infos[0] = value_infos
|
|
517 |
dialog.Destroy()
|
|
518 |
event.Skip()
|
|
519 |
return OnBrowseButton
|
|
520 |
|
|
521 |
def OnWindowResize(self, event):
|
|
522 |
self.GetBestSize()
|
|
523 |
xstart, ystart = self.ParamsEditor.GetViewStart()
|
|
524 |
window_size = self.ParamsEditor.GetClientSize()
|
|
525 |
maxx, maxy = self.ParamsEditorSizer.GetMinSize()
|
|
526 |
posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
|
|
527 |
posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
|
|
528 |
self.ParamsEditor.Scroll(posx, posy)
|
|
529 |
self.ParamsEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
|
|
530 |
maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
|
|
531 |
event.Skip()
|
|
532 |
|
|
533 |
def OnMouseWheel(self, event):
|
|
534 |
if self.ScrollingEnabled:
|
|
535 |
event.Skip()
|
|
536 |
|