1 import os, shutil, sys |
|
2 base_folder = os.path.split(sys.path[0])[0] |
|
3 sys.path.append(os.path.join(base_folder, "wxsvg", "SVGUIEditor")) |
|
4 sys.path.append(os.path.join(base_folder, "plcopeneditor", "graphics")) |
|
5 |
|
6 import wx, subprocess |
|
7 |
|
8 from SVGUIGenerator import * |
|
9 from SVGUIControler import * |
|
10 from SVGUIEditor import * |
|
11 from FBD_Objects import * |
|
12 from PLCGenerator import PLCGenException |
|
13 |
|
14 from wxPopen import ProcessLogger |
|
15 from wx.wxsvg import SVGDocument |
|
16 from docutils import * |
|
17 |
|
18 [ID_SVGUIEDITORFBDPANEL, |
|
19 ] = [wx.NewId() for _init_ctrls in range(1)] |
|
20 |
|
21 SVGUIFB_Types = {ITEM_CONTAINER : "Container", |
|
22 ITEM_BUTTON : "Button", |
|
23 ITEM_TEXT : "TextCtrl", |
|
24 ITEM_SCROLLBAR : "ScrollBar", |
|
25 ITEM_ROTATING : "RotatingCtrl", |
|
26 ITEM_NOTEBOOK : "NoteBook", |
|
27 ITEM_TRANSFORM : "Transform"} |
|
28 |
|
29 class _SVGUIEditor(SVGUIEditor): |
|
30 """ |
|
31 This Class add IEC specific features to the SVGUIEditor : |
|
32 - FDB preview |
|
33 - FBD begin drag |
|
34 """ |
|
35 |
|
36 def _init_coll_EditorGridSizer_Items(self, parent): |
|
37 SVGUIEditor._init_coll_EditorGridSizer_Items(self, parent) |
|
38 parent.AddWindow(self.FBDPanel, 0, border=0, flag=wx.GROW) |
|
39 |
|
40 def _init_ctrls(self, prnt): |
|
41 SVGUIEditor._init_ctrls(self, prnt, False) |
|
42 |
|
43 self.FBDPanel = wx.Panel(id=ID_SVGUIEDITORFBDPANEL, |
|
44 name='FBDPanel', parent=self.EditorPanel, pos=wx.Point(0, 0), |
|
45 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) |
|
46 self.FBDPanel.SetBackgroundColour(wx.WHITE) |
|
47 self.FBDPanel.Bind(wx.EVT_LEFT_DOWN, self.OnFBDPanelClick) |
|
48 self.FBDPanel.Bind(wx.EVT_PAINT, self.OnPaintFBDPanel) |
|
49 |
|
50 setattr(self.FBDPanel, "GetScaling", lambda: None) |
|
51 setattr(self.FBDPanel, "IsOfType", self.IsOfType) |
|
52 setattr(self.FBDPanel, "GetBlockType", self.GetBlockType) |
|
53 |
|
54 self._init_sizers() |
|
55 |
|
56 def __init__(self, parent, controler = None, fileOpen = None): |
|
57 SVGUIEditor.__init__(self, parent, controler, fileOpen) |
|
58 |
|
59 self.FBDBlock = None |
|
60 |
|
61 def IsOfType(self, type, reference): |
|
62 return self.Controler.GetPlugRoot().IsOfType(type, reference) |
|
63 |
|
64 def GetBlockType(self, type, inputs = None): |
|
65 return self.Controler.GetPlugRoot().GetBlockType(type, inputs) |
|
66 |
|
67 def RefreshView(self, select_id = None): |
|
68 SVGUIEditor.RefreshView(self, select_id) |
|
69 self.FBDPanel.Refresh() |
|
70 |
|
71 def OnPaintFBDPanel(self,event): |
|
72 dc = wx.ClientDC(self.FBDPanel) |
|
73 dc.Clear() |
|
74 selected = self.GetSelected() |
|
75 if selected is not None: |
|
76 selected_type = self.Controler.GetElementType(selected) |
|
77 if selected_type is not None: |
|
78 self.FBDBlock = FBD_Block(parent=self.FBDPanel,type=SVGUIFB_Types[selected_type],name=self.Controler.GetElementName(selected)) |
|
79 width, height = self.FBDBlock.GetMinSize() |
|
80 self.FBDBlock.SetSize(width,height) |
|
81 clientsize = self.FBDPanel.GetClientSize() |
|
82 x = (clientsize.width - width) / 2 |
|
83 y = (clientsize.height - height) / 2 |
|
84 self.FBDBlock.SetPosition(x, y) |
|
85 self.FBDBlock.Draw(dc) |
|
86 else: |
|
87 self.FBDBlock = None |
|
88 event.Skip() |
|
89 |
|
90 def OnFBDPanelClick(self, event): |
|
91 if self.FBDBlock: |
|
92 data = wx.TextDataObject(str((self.FBDBlock.GetType(), "functionBlock", self.FBDBlock.GetName()))) |
|
93 DropSrc = wx.DropSource(self.FBDPanel) |
|
94 DropSrc.SetData(data) |
|
95 DropSrc.DoDragDrop() |
|
96 event.Skip() |
|
97 |
|
98 def OnInterfaceTreeItemSelected(self, event): |
|
99 self.FBDPanel.Refresh() |
|
100 SVGUIEditor.OnInterfaceTreeItemSelected(self, event) |
|
101 |
|
102 def OnGenerate(self,event): |
|
103 self.SaveProject() |
|
104 self.Controler.PlugGenerate_C(sys.path[0],(0,0,4,5),None) |
|
105 event.Skip() |
|
106 |
|
107 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L", |
|
108 "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L", |
|
109 "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"} |
|
110 |
|
111 CTYPECONVERSION = {"BOOL" : "IEC_BOOL", "UINT" : "IEC_UINT", "STRING" : "IEC_STRING", "REAL" : "IEC_REAL"} |
|
112 CPRINTTYPECONVERSION = {"BOOL" : "d", "UINT" : "d", "STRING" : "s", "REAL" : "f"} |
|
113 |
|
114 class RootClass(SVGUIControler): |
|
115 |
|
116 def __init__(self): |
|
117 SVGUIControler.__init__(self) |
|
118 filepath = os.path.join(self.PlugPath(), "gui.xml") |
|
119 |
|
120 if os.path.isfile(filepath): |
|
121 svgfile = os.path.join(self.PlugPath(), "gui.svg") |
|
122 if os.path.isfile(svgfile): |
|
123 self.SvgFilepath = svgfile |
|
124 self.OpenXMLFile(filepath) |
|
125 else: |
|
126 self.CreateNewInterface() |
|
127 self.SetFilePath(filepath) |
|
128 |
|
129 def GetElementIdFromName(self, name): |
|
130 element = self.GetElementByName(name) |
|
131 if element is not None: |
|
132 return element.getid() |
|
133 return None |
|
134 |
|
135 _View = None |
|
136 def _OpenView(self): |
|
137 if not self._View: |
|
138 def _onclose(): |
|
139 self._View = None |
|
140 def _onsave(): |
|
141 self.GetPlugRoot().SaveProject() |
|
142 self._View = _SVGUIEditor(self.GetPlugRoot().AppFrame, self) |
|
143 self._View._onclose = _onclose |
|
144 self._View._onsave = _onsave |
|
145 self._View.Show() |
|
146 |
|
147 def _ImportSVG(self): |
|
148 if not self._View: |
|
149 dialog = wx.FileDialog(self.GetPlugRoot().AppFrame, "Choose a SVG file", os.getcwd(), "", "SVG files (*.svg)|*.svg|All files|*.*", wx.OPEN) |
|
150 if dialog.ShowModal() == wx.ID_OK: |
|
151 svgpath = dialog.GetPath() |
|
152 if os.path.isfile(svgpath): |
|
153 shutil.copy(svgpath, os.path.join(self.PlugPath(), "gui.svg")) |
|
154 else: |
|
155 self.logger.write_error("No such SVG file: %s\n"%svgpath) |
|
156 dialog.Destroy() |
|
157 |
|
158 def _ImportXML(self): |
|
159 if not self._View: |
|
160 dialog = wx.FileDialog(self.GetPlugRoot().AppFrame, "Choose a XML file", os.getcwd(), "", "XML files (*.xml)|*.xml|All files|*.*", wx.OPEN) |
|
161 if dialog.ShowModal() == wx.ID_OK: |
|
162 xmlpath = dialog.GetPath() |
|
163 if os.path.isfile(xmlpath): |
|
164 shutil.copy(xmlpath, os.path.join(self.PlugPath(), "gui.xml")) |
|
165 else: |
|
166 self.logger.write_error("No such XML file: %s\n"%xmlpath) |
|
167 dialog.Destroy() |
|
168 |
|
169 def _StartInkscape(self): |
|
170 svgfile = os.path.join(self.PlugPath(), "gui.svg") |
|
171 if not os.path.isfile(svgfile): |
|
172 svgfile = None |
|
173 open_svg(svgfile) |
|
174 |
|
175 PluginMethods = [ |
|
176 {"bitmap" : os.path.join("images","HMIEditor"), |
|
177 "name" : "HMI Editor", |
|
178 "tooltip" : "HMI Editor", |
|
179 "method" : "_OpenView"}, |
|
180 {"bitmap" : os.path.join("images","ImportSVG"), |
|
181 "name" : "Import SVG", |
|
182 "tooltip" : "Import SVG", |
|
183 "method" : "_ImportSVG"}, |
|
184 {"bitmap" : os.path.join("images","ImportDEF"), |
|
185 "name" : "Import XML", |
|
186 "tooltip" : "Import XML", |
|
187 "method" : "_ImportXML"}, |
|
188 {"bitmap" : os.path.join("images","ImportSVG"), |
|
189 "name" : "Inkscape", |
|
190 "tooltip" : "Create HMI", |
|
191 "method" : "_StartInkscape"}, |
|
192 ] |
|
193 |
|
194 def OnPlugSave(self): |
|
195 self.SaveXMLFile(os.path.join(self.PlugPath(), "gui.xml")) |
|
196 return True |
|
197 |
|
198 def PlugGenerate_C(self, buildpath, locations): |
|
199 progname = "SVGUI_%s"%"_".join(map(str, self.GetCurrentLocation())) |
|
200 |
|
201 doc = SVGDocument(self.GetSVGFilePath()) |
|
202 root_element = doc.GetRootElement() |
|
203 window_size = (int(float(root_element.GetAttribute("width"))), |
|
204 int(float(root_element.GetAttribute("height")))) |
|
205 |
|
206 # svgfilepath = self.GetSVGFilePath() |
|
207 # xmlfilepath = self.GetFilePath() |
|
208 # shutil.copy(svgfilepath, buildpath) |
|
209 # shutil.copy(xmlfilepath, buildpath) |
|
210 |
|
211 SVGFilePath = self.GetSVGFilePath() |
|
212 SVGFileBaseName = os.path.split(SVGFilePath)[1] |
|
213 FilePath = self.GetFilePath() |
|
214 FileBaseName = os.path.split(FilePath)[1] |
|
215 |
|
216 generator = _SVGUICGenerator(self, self.GetElementsByType(), |
|
217 os.path.split(self.GetSVGFilePath())[1], |
|
218 os.path.split(self.GetFilePath())[1], |
|
219 self.GetCurrentLocation()) |
|
220 generator.GenerateProgram(window_size, buildpath, progname) |
|
221 Gen_C_file = os.path.join(buildpath, progname+".cpp" ) |
|
222 |
|
223 if wx.Platform == '__WXMSW__': |
|
224 cxx_flags = "-I..\\lib\\wx\\include\\msw-unicode-release-2.8 -I..\\include\\wx-2.8 -I..\\..\\matiec\\lib -DWXUSINGDLL -D__WXMSW__ -mthreads" |
|
225 libs = "\"..\\lib\\libwxsvg.a\" \"..\\lib\\libwxsvg_agg.a\" \"..\\lib\\libagg.a\" \"..\\lib\\libaggplatformwin32.a\" \"..\\lib\\libaggfontwin32tt.a\" -L..\\lib -mwindows -mthreads -Wl,--subsystem,windows -mwindows -lwx_mswu_richtext-2.8 -lwx_mswu_aui-2.8 -lwx_mswu_xrc-2.8 -lwx_mswu_qa-2.8 -lwx_mswu_html-2.8 -lwx_mswu_adv-2.8 -lwx_mswu_core-2.8 -lwx_baseu_xml-2.8 -lwx_baseu_net-2.8 -lwx_baseu-2.8" |
|
226 else: |
|
227 status, result, err_result = ProcessLogger(self.logger, "wx-config --cxxflags", no_stdout=True).spin() |
|
228 if status: |
|
229 self.logger.write_error("Unable to get wx cxxflags\n") |
|
230 cxx_flags = result.strip() + " -I../matiec/lib" |
|
231 |
|
232 status, result, err_result = ProcessLogger(self.logger, "wx-config --libs", no_stdout=True).spin() |
|
233 if status: |
|
234 self.logger.write_error("Unable to get wx libs\n") |
|
235 libs = result.strip() + " -lwxsvg" |
|
236 |
|
237 return [(Gen_C_file, cxx_flags)],libs,True,(SVGFileBaseName, file(SVGFilePath, "rb")), (FileBaseName, file(FilePath, "rb")) |
|
238 |
|
239 def BlockTypesFactory(self): |
|
240 |
|
241 SVGUIBlock_Types = [] |
|
242 |
|
243 def GetSVGUIBlockType(type): |
|
244 for category in SVGUIBlock_Types: |
|
245 for blocktype in category["list"]: |
|
246 if blocktype["name"] == type: |
|
247 return blocktype |
|
248 setattr(self, "GetSVGUIBlockType", GetSVGUIBlockType) |
|
249 |
|
250 def generate_svgui_block(generator, block, body, link, order=False): |
|
251 name = block.getinstanceName() |
|
252 block_id = self.GetElementIdFromName(name) |
|
253 if block_id == None: |
|
254 raise PLCGenException, "Undefined SVGUI Block \"%s\""%name |
|
255 type = block.gettypeName() |
|
256 block_infos = GetSVGUIBlockType(type) |
|
257 current_location = ".".join(map(str, self.GetCurrentLocation())) |
|
258 if not generator.ComputedBlocks.get(block, False) and not order: |
|
259 generator.ComputedBlocks[block] = True |
|
260 for num, variable in enumerate(block.inputVariables.getvariable()): |
|
261 connections = variable.connectionPointIn.getconnections() |
|
262 if connections is not None: |
|
263 input_info = (generator.TagName, "block", block.getlocalId(), "input", num) |
|
264 parameter = "%sQ%s%s.%d.%d"%("%", TYPECONVERSION[block_infos["inputs"][num][1]], current_location, block_id, num+1) |
|
265 value = generator.ComputeExpression(body, connections) |
|
266 generator.Program += [(generator.CurrentIndent, ()), |
|
267 (parameter, input_info), |
|
268 (" := ", ())] |
|
269 generator.Program += generator.ExtractModifier(variable, value, input_info) |
|
270 generator.Program += [(";\n", ())] |
|
271 if link: |
|
272 connectionPoint = link.getposition()[-1] |
|
273 for num, variable in enumerate(block.outputVariables.getvariable()): |
|
274 blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY() |
|
275 output_info = (generator.TagName, "block", block.getlocalId(), "output", num) |
|
276 parameter = "%sI%s%s.%d.%d"%("%", TYPECONVERSION[block_infos["outputs"][num][1]], current_location, block_id, num+1) |
|
277 if block.getx() + blockPointx == connectionPoint.getx() and block.gety() + blockPointy == connectionPoint.gety(): |
|
278 return generator.ExtractModifier(variable, [(parameter, output_info)], output_info) |
|
279 raise PLCGenException, "No corresponding output variable found on SVGUI Block \"%s\""%name |
|
280 else: |
|
281 return None |
|
282 |
|
283 def initialise_block(type, name, block = None): |
|
284 block_id = self.GetElementIdFromName(name) |
|
285 if block_id == None: |
|
286 raise PLCGenException, "Undefined SVGUI Block \"%s\""%name |
|
287 block_infos = GetSVGUIBlockType(type) |
|
288 current_location = ".".join(map(str, self.GetCurrentLocation())) |
|
289 variables = [] |
|
290 if block is not None: |
|
291 input_variables = block.inputVariables.getvariable() |
|
292 output_variables = block.outputVariables.getvariable() |
|
293 else: |
|
294 input_variables = None |
|
295 output_variables = None |
|
296 for num, (input_name, input_type, input_modifier) in enumerate(block_infos["inputs"]): |
|
297 if input_variables is not None and num < len(input_variables): |
|
298 connections = input_variables[num].connectionPointIn.getconnections() |
|
299 if input_variables is None or connections and len(connections) == 1: |
|
300 variables.append((input_type, None, "%sQ%s%s.%d.%d"%("%", TYPECONVERSION[input_type], current_location, block_id, num+1), None)) |
|
301 for num, (output_name, output_type, output_modifier) in enumerate(block_infos["outputs"]): |
|
302 variables.append((output_type, None, "%sI%s%s.%d.%d"%("%", TYPECONVERSION[input_type], current_location, block_id, num+1), None)) |
|
303 return variables |
|
304 |
|
305 SVGUIBlock_Types.extend([{"name" : "SVGUI function blocks", "list" : |
|
306 [{"name" : "Container", "type" : "functionBlock", "extensible" : False, |
|
307 "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none")], |
|
308 "outputs" : [], |
|
309 "comment" : "SVGUI Container", |
|
310 "generate" : generate_svgui_block, "initialise" : initialise_block}, |
|
311 {"name" : "Button", "type" : "functionBlock", "extensible" : False, |
|
312 "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("Value","BOOL","none")], |
|
313 "outputs" : [("State","BOOL","none")], |
|
314 "comment" : "SVGUI Button", |
|
315 "generate" : generate_svgui_block, "initialise" : initialise_block}, |
|
316 {"name" : "TextCtrl", "type" : "functionBlock", "extensible" : False, |
|
317 "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetText","STRING","none")], |
|
318 "outputs" : [("Text","STRING","none")], |
|
319 "comment" : "SVGUI Text Control", |
|
320 "generate" : generate_svgui_block, "initialise" : initialise_block}, |
|
321 {"name" : "ScrollBar", "type" : "functionBlock", "extensible" : False, |
|
322 "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetThumb","UINT","none"),("SetRange","UINT","none"),("SetPosition","UINT","none")], |
|
323 "outputs" : [("Position","UINT","none")], |
|
324 "comment" : "SVGUI ScrollBar", |
|
325 "generate" : generate_svgui_block, "initialise" : initialise_block}, |
|
326 {"name" : "NoteBook", "type" : "functionBlock", "extensible" : False, |
|
327 "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetSelected","BOOL","none")], |
|
328 "outputs" : [("Selected","UINT","none")], |
|
329 "comment" : "SVGUI Notebook", |
|
330 "generate" : generate_svgui_block, "initialise" : initialise_block}, |
|
331 {"name" : "RotatingCtrl", "type" : "functionBlock", "extensible" : False, |
|
332 "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetAngle","REAL","none")], |
|
333 "outputs" : [("Angle","REAL","none")], |
|
334 "comment" : "SVGUI Rotating Control", |
|
335 "generate" : generate_svgui_block, "initialise" : initialise_block}, |
|
336 {"name" : "Transform", "type" : "functionBlock", "extensible" : False, |
|
337 "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetX","REAL","none"),("SetY","REAL","none"),("SetXScale","REAL","none"),("SetYScale","REAL","none"),("SetAngle","REAL","none")], |
|
338 "outputs" : [("X","REAL","none"),("Y","REAL","none")], |
|
339 "comment" : "SVGUI Transform", |
|
340 "generate" : generate_svgui_block, "initialise" : initialise_block}, |
|
341 ]} |
|
342 ]) |
|
343 |
|
344 return SVGUIBlock_Types |
|
345 |
|
346 |
|
347 class _SVGUICGenerator(SVGUICGenerator): |
|
348 |
|
349 def __init__(self, controler, elements, svgfile, xmlfile, current_location): |
|
350 SVGUICGenerator.__init__(self, elements, svgfile, xmlfile) |
|
351 |
|
352 self.CurrentLocation = current_location |
|
353 self.Controler = controler |
|
354 |
|
355 def GenerateProgramHeadersPublicVars(self): |
|
356 text = """ |
|
357 void OnPlcOutEvent(wxEvent& event); |
|
358 |
|
359 void Retrieve(); |
|
360 void Publish(); |
|
361 void Initialize(); |
|
362 """ |
|
363 # text += " void Print();\n" |
|
364 return text |
|
365 |
|
366 def GenerateIECVars(self): |
|
367 text = "" |
|
368 for element in self.Elements: |
|
369 text += "STATE_TYPE out_state_%d;\n"%element.getid() |
|
370 text += "STATE_TYPE in_state_%d;\n"%element.getid() |
|
371 text +="\n" |
|
372 current_location = "_".join(map(str, self.CurrentLocation)) |
|
373 #Declaration des variables |
|
374 for element in self.Elements: |
|
375 block_infos = self.Controler.GetSVGUIBlockType(SVGUIFB_Types[GetElementType(element)]) |
|
376 block_id = element.getid() |
|
377 for i, input in enumerate(block_infos["inputs"]): |
|
378 element_c_type = CTYPECONVERSION[input[1]] |
|
379 variable = "__Q%s%s_%d_%d"%(TYPECONVERSION[input[1]], current_location, block_id, i + 1) |
|
380 text += "%s beremiz%s;\n"%(element_c_type, variable) |
|
381 text += "%s* %s = &beremiz%s;\n"%(element_c_type, variable, variable) |
|
382 text += "%s _copy%s;\n"%(element_c_type, variable) |
|
383 for i, output in enumerate(block_infos["outputs"]): |
|
384 element_c_type = CTYPECONVERSION[output[1]] |
|
385 variable = "__I%s%s_%d_%d"%(TYPECONVERSION[output[1]], current_location, block_id, i + 1) |
|
386 text += "%s beremiz%s;\n"%(element_c_type, variable) |
|
387 text += "%s* %s = &beremiz%s;\n"%(element_c_type, variable, variable) |
|
388 text += "%s _copy%s;\n"%(element_c_type, variable) |
|
389 text +="\n" |
|
390 return text |
|
391 |
|
392 def GenerateGlobalVarsAndFuncs(self, size): |
|
393 text = """#include "iec_types.h" |
|
394 #ifdef __WXMSW__ |
|
395 #define COMPARE_AND_SWAP_VAL(Destination, comparand, exchange) InterlockedCompareExchange(Destination, exchange, comparand) |
|
396 #define THREAD_RETURN_TYPE DWORD WINAPI |
|
397 #define STATE_TYPE long int |
|
398 #else |
|
399 #define COMPARE_AND_SWAP_VAL(Destination, comparand, exchange) __sync_val_compare_and_swap(Destination, comparand, exchange) |
|
400 #define THREAD_RETURN_TYPE void* |
|
401 #define STATE_TYPE volatile int |
|
402 #endif |
|
403 |
|
404 """ |
|
405 |
|
406 text += self.GenerateIECVars() |
|
407 |
|
408 text += """IMPLEMENT_APP_NO_MAIN(SVGViewApp); |
|
409 SVGViewApp *myapp = NULL; |
|
410 wxSemaphore MyInitSem; |
|
411 |
|
412 #ifdef __WXMSW__ |
|
413 HANDLE wxMainLoop; |
|
414 DWORD wxMainLoopId; |
|
415 #else |
|
416 pthread_t wxMainLoop; |
|
417 #endif |
|
418 |
|
419 """ |
|
420 |
|
421 text += """int myargc = 0; |
|
422 char** myargv = NULL; |
|
423 |
|
424 #define UNCHANGED 1 |
|
425 #define PLC_BUSY 2 |
|
426 #define CHANGED 3 |
|
427 #define GUI_BUSY 4 |
|
428 #ifdef __WXMSW__ |
|
429 #else |
|
430 #endif |
|
431 |
|
432 bool refresh = false; |
|
433 bool refreshing = false; |
|
434 |
|
435 THREAD_RETURN_TYPE InitWxEntry(void* args) |
|
436 { |
|
437 wxEntry(myargc,myargv); |
|
438 myapp = NULL; |
|
439 MyInitSem.Post(); |
|
440 return 0; |
|
441 } |
|
442 |
|
443 """ |
|
444 |
|
445 text += """ |
|
446 bool SVGViewApp::OnInit() |
|
447 { |
|
448 #ifndef __WXMSW__ |
|
449 setlocale(LC_NUMERIC, "C"); |
|
450 #endif |
|
451 """ |
|
452 |
|
453 text += """ frame = new MainFrame(NULL, wxT("Program"),wxDefaultPosition, wxSize(%d, %d)); |
|
454 frame->Show(); |
|
455 myapp = this; |
|
456 """%size |
|
457 text += """ return true; |
|
458 } |
|
459 |
|
460 extern "C" { |
|
461 |
|
462 int __init_%(location)s(int argc, char** argv) |
|
463 { |
|
464 myargc = argc; |
|
465 myargv = argv; |
|
466 #ifdef __WXMSW__ |
|
467 wxMainLoop = CreateThread(NULL, 0, InitWxEntry, 0, 0, &wxMainLoopId); |
|
468 #else |
|
469 pthread_create(&wxMainLoop, NULL, InitWxEntry, NULL); |
|
470 #endif |
|
471 MyInitSem.Wait(); |
|
472 return 0; |
|
473 } |
|
474 |
|
475 void __cleanup_%(location)s() |
|
476 { |
|
477 if(myapp){ |
|
478 wxCloseEvent event(wxEVT_CLOSE_WINDOW); |
|
479 myapp->frame->AddPendingEvent(event); |
|
480 myapp = NULL; |
|
481 } |
|
482 MyInitSem.Wait(); |
|
483 } |
|
484 |
|
485 void __retrieve_%(location)s() |
|
486 { |
|
487 if(myapp){ |
|
488 myapp->frame->m_svgCtrl->Retrieve(); |
|
489 } |
|
490 } |
|
491 |
|
492 void __publish_%(location)s() |
|
493 { |
|
494 if(myapp){ |
|
495 myapp->frame->m_svgCtrl->Publish(); |
|
496 } |
|
497 } |
|
498 |
|
499 } |
|
500 |
|
501 IEC_STRING wxStringToIEC_STRING(wxString s) |
|
502 { |
|
503 IEC_STRING res = {0,""}; |
|
504 int i; |
|
505 for(i = 0; i<s.Length() && i<STR_MAX_LEN; i++) |
|
506 res.body[i] = s.GetChar(i); |
|
507 res.len = i; |
|
508 return res; |
|
509 } |
|
510 |
|
511 """%{"location" : "_".join(map(str, self.CurrentLocation))} |
|
512 |
|
513 return text |
|
514 |
|
515 def GenerateProgramEventTable(self): |
|
516 text = """BEGIN_DECLARE_EVENT_TYPES() |
|
517 DECLARE_LOCAL_EVENT_TYPE( EVT_PLC, wxNewEventType() ) |
|
518 END_DECLARE_EVENT_TYPES() |
|
519 |
|
520 DEFINE_LOCAL_EVENT_TYPE( EVT_PLC ) |
|
521 |
|
522 """ |
|
523 #Event Table Declaration |
|
524 text += "BEGIN_EVENT_TABLE(Program, SVGUIWindow)\n" |
|
525 for element in self.Elements: |
|
526 element_type = GetElementType(element) |
|
527 element_name = element.getname() |
|
528 if element_type == ITEM_BUTTON: |
|
529 text += " EVT_BUTTON (SVGUIID(\"%s\"), Program::On%sClick)\n"%(element_name, element_name) |
|
530 elif element_type in [ITEM_SCROLLBAR, ITEM_ROTATING, ITEM_TRANSFORM]: |
|
531 text += " EVT_COMMAND_SCROLL_THUMBTRACK (SVGUIID(\"%s\"), Program::On%sChanging)\n"%(element_name, element_name) |
|
532 elif element_type == ITEM_NOTEBOOK: |
|
533 text += " EVT_NOTEBOOK_PAGE_CHANGED (SVGUIID(\"%s\"), Program::On%sTabChanged)\n"%(element_name, element_name) |
|
534 text += " EVT_CUSTOM(EVT_PLC, wxID_ANY, Program::OnPlcOutEvent)\n" |
|
535 text += "END_EVENT_TABLE()\n\n" |
|
536 return text |
|
537 |
|
538 def GenerateProgramInitFrame(self): |
|
539 text = """MainFrame::MainFrame(wxWindow *parent, const wxString& title, const wxPoint& pos,const wxSize& size, long style): wxFrame(parent, wxID_ANY, title, pos, size, style) |
|
540 { |
|
541 wxFileName svgfilepath(wxTheApp->argv[1], wxT("%s")); |
|
542 wxFileName xmlfilepath(wxTheApp->argv[1], wxT("%s")); |
|
543 |
|
544 m_svgCtrl = new Program(this); |
|
545 if (m_svgCtrl->LoadFiles(svgfilepath.GetFullPath(), xmlfilepath.GetFullPath())) |
|
546 { |
|
547 Show(true); |
|
548 m_svgCtrl->SetFocus(); |
|
549 m_svgCtrl->SetFitToFrame(true); |
|
550 m_svgCtrl->InitScrollBars(); |
|
551 m_svgCtrl->Initialize(); |
|
552 m_svgCtrl->Update(); |
|
553 } |
|
554 else |
|
555 { |
|
556 printf("Error while opening SVGUI files\\n"); |
|
557 } |
|
558 } |
|
559 |
|
560 |
|
561 """%(self.SVGFilePath, self.XMLFilePath) |
|
562 |
|
563 return text |
|
564 |
|
565 def GenerateProgramInitProgram(self): |
|
566 text = "Program::Program(wxWindow* parent):SVGUIWindow(parent)\n{\n" |
|
567 for element in self.Elements: |
|
568 text += " out_state_%d = UNCHANGED;\n"%element.getid() |
|
569 text += " in_state_%d = UNCHANGED;\n"%element.getid() |
|
570 text += "}\n\n" |
|
571 return text |
|
572 |
|
573 def GenerateProgramEventFunctions(self): |
|
574 text = "" |
|
575 current_location = "_".join(map(str, self.CurrentLocation)) |
|
576 for element in self.Elements: |
|
577 element_type = GetElementType(element) |
|
578 element_lock = """ |
|
579 if (COMPARE_AND_SWAP_VAL(&in_state_%d, CHANGED, GUI_BUSY) == CHANGED || |
|
580 COMPARE_AND_SWAP_VAL(&in_state_%d, UNCHANGED, GUI_BUSY) == UNCHANGED) { |
|
581 """%(element.getid(), element.getid()) |
|
582 element_unlock = """ |
|
583 COMPARE_AND_SWAP_VAL(&in_state_%d, GUI_BUSY, CHANGED); |
|
584 event.Skip(); |
|
585 }else{ |
|
586 /* re post event for idle */ |
|
587 AddPendingEvent(event); |
|
588 } |
|
589 } |
|
590 |
|
591 """%element.getid() |
|
592 element_name = element.getname() |
|
593 |
|
594 if element_type == ITEM_BUTTON: |
|
595 text += """void Program::On%sClick(wxCommandEvent& event) |
|
596 { |
|
597 SVGUIButton* button = (SVGUIButton*)GetElementByName(wxT("%s"));\n"""%(element_name, element_name) |
|
598 text += element_lock |
|
599 text += " _copy__IX%s_%d_1 = button->GetToggle();\n"%(current_location, element.getid()) |
|
600 text += element_unlock |
|
601 elif element_type == ITEM_ROTATING: |
|
602 text += """void Program::On%sChanging(wxScrollEvent& event) |
|
603 { |
|
604 SVGUIRotatingCtrl* rotating = (SVGUIRotatingCtrl*)GetElementByName(wxT("%s")); |
|
605 """%(element_name, element_name) |
|
606 text += element_lock |
|
607 text += " _copy__ID%s_%d_1 = rotating->GetAngle();\n"%(current_location, element.getid()) |
|
608 text += element_unlock |
|
609 elif element_type == ITEM_NOTEBOOK: |
|
610 text += """void Program::On%sTabChanged(wxNotebookEvent& event) |
|
611 { |
|
612 SVGUINoteBook* notebook = (SVGUINoteBook*)GetElementByName(wxT("%s")); |
|
613 """%(element_name, element_name) |
|
614 text += element_lock |
|
615 text += " _copy__IB%s_%d_1 = notebook->GetCurrentPage();\n"%(current_location, element.getid()) |
|
616 text += element_unlock |
|
617 elif element_type == ITEM_TRANSFORM: |
|
618 text += """void Program::On%sChanging(wxScrollEvent& event) |
|
619 { |
|
620 SVGUITransform* transform = (SVGUITransform*)GetElementByName(wxT("%s")); |
|
621 """%(element_name, element_name) |
|
622 text += element_lock |
|
623 text += " _copy__ID%s_%d_1 = transform->GetX();\n"%(current_location, element.getid()) |
|
624 text += " _copy__ID%s_%d_2 = transform->GetY();\n"%(current_location, element.getid()) |
|
625 text += element_unlock |
|
626 |
|
627 text += "/* OnPlcOutEvent update GUI with provided IEC __Q* PLC output variables */\n" |
|
628 text += """void Program::OnPlcOutEvent(wxEvent& event) |
|
629 { |
|
630 SVGUIElement* element; |
|
631 |
|
632 refreshing = true; |
|
633 |
|
634 |
|
635 """ |
|
636 for element in self.Elements: |
|
637 element_type = GetElementType(element) |
|
638 texts = {"location" : current_location, "id" : element.getid()} |
|
639 |
|
640 text += """ if (COMPARE_AND_SWAP_VAL(&out_state_%(id)d, CHANGED, GUI_BUSY) == CHANGED) |
|
641 { |
|
642 element = (SVGUIElement*)GetElementById(wxT("%(id)d")); |
|
643 |
|
644 if (_copy__QX%(location)s_%(id)d_1 != element->IsVisible()) { |
|
645 if (_copy__QX%(location)s_%(id)d_1) |
|
646 element->Show(); |
|
647 else |
|
648 element->Hide(); |
|
649 } |
|
650 if (_copy__QX%(location)s_%(id)d_2 != element->IsEnabled()) { |
|
651 if (_copy__QX%(location)s_%(id)d_2) |
|
652 element->Enable(); |
|
653 else |
|
654 element->Disable(); |
|
655 } |
|
656 """%texts |
|
657 if element_type == ITEM_BUTTON: |
|
658 text += """ if (_copy__QX%(location)s_%(id)d_3 != ((SVGUIButton*)element)->GetToggle()) |
|
659 ((SVGUIButton*)element)->SetToggle(_copy__QX%(location)s_%(id)d_3); |
|
660 """%texts |
|
661 elif element_type == ITEM_TEXT: |
|
662 text += """ if (((SVGUITextCtrl*)element)->GetValue().compare(_copy__QX%(location)s_%(id)d_3)) |
|
663 { |
|
664 wxString str = wxString::FromAscii(_copy__QB%(location)s_%(id)d_3); |
|
665 ((SVGUITextCtrl*)element)->SetText(str); |
|
666 } |
|
667 """%texts |
|
668 elif element_type == ITEM_SCROLLBAR: |
|
669 text += """ if (_copy__QW%(location)s_%(id)d_3 != ((SVGUIScrollBar*)element)->GetThumbPosition() || |
|
670 _copy__QW%(location)s_%(id)d_4 != ((SVGUIScrollBar*)element)->GetThumbSize() || |
|
671 _copy__QW%(location)s_%(id)d_5 != ((SVGUIScrollBar*)element)->GetRange()) |
|
672 ((SVGUIScrollBar*)element)->Init_ScrollBar(_copy__QW%(location)s_%(id)d_3, _copy__QW%(location)s_%(id)d_4, _copy__QW%(location)s_%(id)d_5); |
|
673 """%texts |
|
674 elif element_type == ITEM_ROTATING: |
|
675 text += """ if (_copy__QD%(location)s_%(id)d_3 != ((SVGUIRotatingCtrl*)element)->GetAngle()) |
|
676 ((SVGUIRotatingCtrl*)element)->SetAngle(_copy__QD%(location)s_%(id)d_3); |
|
677 """%texts |
|
678 elif element_type == ITEM_NOTEBOOK: |
|
679 text += """ if (_copy__QB%(location)s_%(id)d_3 != ((SVGUINoteBook*)element)->GetCurrentPage()) |
|
680 ((SVGUINoteBook*)element)->SetCurrentPage(_copy__QB%(location)s_%(id)d_3); |
|
681 """%texts |
|
682 elif element_type == ITEM_TRANSFORM: |
|
683 text += """ if (_copy__QD%(location)s_%(id)d_3 != ((SVGUITransform*)element)->GetX() || |
|
684 _copy__QD%(location)s_%(id)d_4 != ((SVGUITransform*)element)->GetY()) |
|
685 ((SVGUITransform*)element)->Move(_copy__QD%(location)s_%(id)d_3, _copy__QD%(location)s_%(id)d_4); |
|
686 if (_copy__QD%(location)s_%(id)d_5 != ((SVGUITransform*)element)->GetXScale() || |
|
687 _copy__QD%(location)s_%(id)d_6 != ((SVGUITransform*)element)->GetYScale()) |
|
688 ((SVGUITransform*)element)->Scale(_copy__QD%(location)s_%(id)d_5, _copy__QD%(location)s_%(id)d_6); |
|
689 if (_copy__QD%(location)s_%(id)d_7 != ((SVGUITransform*)element)->GetAngle()) |
|
690 ((SVGUITransform*)element)->Rotate(_copy__QD%(location)s_%(id)d_7); |
|
691 """%texts |
|
692 text += " COMPARE_AND_SWAP_VAL(&out_state_%(id)d, GUI_BUSY, UNCHANGED);\n }\n"%texts |
|
693 |
|
694 text += """ |
|
695 |
|
696 refreshing = false; |
|
697 |
|
698 event.Skip(); |
|
699 } |
|
700 |
|
701 """ |
|
702 return text |
|
703 |
|
704 def GenerateProgramPrivateFunctions(self): |
|
705 current_location = "_".join(map(str, self.CurrentLocation)) |
|
706 |
|
707 text = "void Program::Retrieve()\n{\n" |
|
708 for element in self.Elements: |
|
709 element_type = GetElementType(element) |
|
710 texts = {"location" : current_location, "id" : element.getid()} |
|
711 block_infos = self.Controler.GetSVGUIBlockType(SVGUIFB_Types[GetElementType(element)]) |
|
712 if len(block_infos["outputs"]) > 0: |
|
713 text += """ if (COMPARE_AND_SWAP_VAL(&in_state_%(id)d, CHANGED, PLC_BUSY) == CHANGED) { |
|
714 """%texts |
|
715 for i, output in enumerate(block_infos["outputs"]): |
|
716 texts["type"] = TYPECONVERSION[output[1]] |
|
717 texts["pin"] = i + 1 |
|
718 |
|
719 variable = "__I%(type)s%(location)s_%(id)d_%(pin)d"%texts |
|
720 text +=" beremiz%s = _copy%s;\n"%(variable, variable) |
|
721 |
|
722 text += """ COMPARE_AND_SWAP_VAL(&in_state_%(id)d, PLC_BUSY, UNCHANGED); |
|
723 } |
|
724 """%texts |
|
725 text += "}\n\n" |
|
726 |
|
727 text += "void Program::Publish()\n{\n STATE_TYPE new_state;\n\n" |
|
728 for element in self.Elements: |
|
729 element_type = GetElementType(element) |
|
730 texts = {"location" : current_location, "id" : element.getid()} |
|
731 block_infos = self.Controler.GetSVGUIBlockType(SVGUIFB_Types[GetElementType(element)]) |
|
732 |
|
733 text += """ if ((new_state = COMPARE_AND_SWAP_VAL(&out_state_%(id)d, UNCHANGED, PLC_BUSY)) == UNCHANGED || |
|
734 (new_state = COMPARE_AND_SWAP_VAL(&out_state_%(id)d, CHANGED, PLC_BUSY)) == CHANGED) { |
|
735 """%texts |
|
736 for i, input in enumerate(block_infos["inputs"]): |
|
737 texts["type"] = TYPECONVERSION[input[1]] |
|
738 texts["pin"] = i + 1 |
|
739 variable = "__Q%(type)s%(location)s_%(id)d_%(pin)d"%texts |
|
740 text += " if (_copy%s != beremiz%s) {\n"%(variable, variable) |
|
741 text += " _copy%s = beremiz%s;\n"%(variable, variable) |
|
742 text += " new_state = CHANGED;\n }\n"%texts |
|
743 text += """ COMPARE_AND_SWAP_VAL(&out_state_%(id)d, PLC_BUSY, new_state); |
|
744 refresh |= new_state == CHANGED; |
|
745 } |
|
746 """%texts |
|
747 |
|
748 text += """ /* Replace this with determinist signal if called from RT */ |
|
749 if (refresh && !refreshing) { |
|
750 wxCommandEvent event( EVT_PLC ); |
|
751 AddPendingEvent(event); |
|
752 refresh = false; |
|
753 } |
|
754 }; |
|
755 |
|
756 """ |
|
757 |
|
758 text += """void Program::Initialize() |
|
759 { |
|
760 SVGUIElement* element; |
|
761 """ |
|
762 for element in self.Elements: |
|
763 element_type = GetElementType(element) |
|
764 texts = {"location" : current_location, "id" : element.getid()} |
|
765 |
|
766 text += """ |
|
767 element = (SVGUIElement*)GetElementById(wxT("%(id)d")); |
|
768 beremiz__QX%(location)s_%(id)d_1 = _copy__QX%(location)s_%(id)d_1 = element->IsVisible(); |
|
769 beremiz__QX%(location)s_%(id)d_2 = _copy__QX%(location)s_%(id)d_2 = element->IsEnabled(); |
|
770 """%texts |
|
771 if element_type == ITEM_BUTTON: |
|
772 text += " beremiz__QX%(location)s_%(id)d_3 = _copy__QX%(location)s_%(id)d_3 = ((SVGUIButton*)element)->GetToggle();\n"%texts |
|
773 text += " beremiz__IX%(location)s_%(id)d_1 = _copy__IX%(location)s_%(id)d_1 = ((SVGUIButton*)element)->GetToggle();\n"%texts |
|
774 elif element_type == ITEM_TEXT: |
|
775 text += " beremiz__QB%(location)s_%(id)d_3 = _copy__QB%(location)s_%(id)d_3 = ((SVGUITextCtrl*)element)->GetValue();\n"%texts |
|
776 text += " beremiz__IB%(location)s_%(id)d_1 = _copy__IB%(location)s_%(id)d_1 = ((SVGUITextCtrl*)element)->GetValue();\n"%texts |
|
777 elif element_type == ITEM_SCROLLBAR: |
|
778 text += " beremiz__QW%(location)s_%(id)d_3 = _copy__QW%(location)s_%(id)d_3 = ((SVGUIScrollBar*)element)->GetThumbSize();\n"%texts |
|
779 text += " beremiz__QW%(location)s_%(id)d_4 = _copy__QW%(location)s_%(id)d_4 = ((SVGUIScrollBar*)element)->GetRange();\n"%texts |
|
780 text += " beremiz__QW%(location)s_%(id)d_5 = _copy__QW%(location)s_%(id)d_5 = ((SVGUIScrollBar*)element)->GetThumbPosition();\n"%texts |
|
781 text += " beremiz__IW%(location)s_%(id)d_1 = _copy__IW%(location)s_%(id)d_1 = ((SVGUIScrollBar*)element)->GetThumbPosition();\n"%texts |
|
782 elif element_type == ITEM_ROTATING: |
|
783 text += " beremiz__QD%(location)s_%(id)d_3 = _copy__QD%(location)s_%(id)d_3 = ((SVGUIRotatingCtrl*)element)->GetAngle();\n"%texts |
|
784 text += " beremiz__ID%(location)s_%(id)d_1 = _copy__ID%(location)s_%(id)d_1 = ((SVGUIRotatingCtrl*)element)->GetAngle();\n"%texts |
|
785 elif element_type == ITEM_NOTEBOOK: |
|
786 text += " beremiz__QB%(location)s_%(id)d_3 = _copy__QB%(location)s_%(id)d_3 = ((SVGUINoteBook*)element)->GetCurrentPage();\n"%texts |
|
787 text += " beremiz__IB%(location)s_%(id)d_1 = _copy__IB%(location)s_%(id)d_1 = ((SVGUINoteBook*)element)->GetCurrentPage();\n"%texts |
|
788 elif element_type == ITEM_TRANSFORM: |
|
789 text += " beremiz__QD%(location)s_%(id)d_3 = _copy__QD%(location)s_%(id)d_3 = ((SVGUITransform*)element)->GetX();\n"%texts |
|
790 text += " beremiz__QD%(location)s_%(id)d_4 = _copy__QD%(location)s_%(id)d_4 = ((SVGUITransform*)element)->GetY();\n"%texts |
|
791 text += " beremiz__QD%(location)s_%(id)d_5 = _copy__QD%(location)s_%(id)d_5 = ((SVGUITransform*)element)->GetXScale();\n"%texts |
|
792 text += " beremiz__QD%(location)s_%(id)d_6 = _copy__QD%(location)s_%(id)d_6 = ((SVGUITransform*)element)->GetYScale();\n"%texts |
|
793 text += " beremiz__QD%(location)s_%(id)d_7 = _copy__QD%(location)s_%(id)d_7 = ((SVGUITransform*)element)->GetAngle();\n"%texts |
|
794 text += " beremiz__ID%(location)s_%(id)d_1 = _copy__ID%(location)s_%(id)d_1 = ((SVGUITransform*)element)->GetX();\n"%texts |
|
795 text += " beremiz__ID%(location)s_%(id)d_2 = _copy__ID%(location)s_%(id)d_2 = ((SVGUITransform*)element)->GetY();\n"%texts |
|
796 |
|
797 text += "\n MyInitSem.Post();\n}\n\n" |
|
798 return text |
|