10 import os |
10 import os |
11 import shutil |
11 import shutil |
12 from itertools import izip, imap |
12 from itertools import izip, imap |
13 from pprint import pprint, pformat |
13 from pprint import pprint, pformat |
14 import hashlib |
14 import hashlib |
|
15 import weakref |
15 |
16 |
16 import wx |
17 import wx |
|
18 import wx.dataview as dv |
|
19 |
|
20 from lxml import etree |
|
21 from lxml.etree import XSLTApplyError |
17 |
22 |
18 import util.paths as paths |
23 import util.paths as paths |
19 from POULibrary import POULibrary |
24 from POULibrary import POULibrary |
20 from docutil import open_svg, get_inkscape_path |
25 from docutil import open_svg, get_inkscape_path |
21 from lxml import etree |
|
22 |
26 |
23 from util.ProcessLogger import ProcessLogger |
27 from util.ProcessLogger import ProcessLogger |
24 from runtime.typemapping import DebugTypesSize |
28 from runtime.typemapping import DebugTypesSize |
25 import targets |
29 import targets |
|
30 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor |
|
31 from XSLTransform import XSLTransform |
26 |
32 |
27 HMI_TYPES_DESC = { |
33 HMI_TYPES_DESC = { |
28 "HMI_NODE":{}, |
34 "HMI_NODE":{}, |
29 "HMI_STRING":{}, |
35 "HMI_STRING":{}, |
30 "HMI_INT":{}, |
36 "HMI_INT":{}, |
31 "HMI_REAL":{} |
37 "HMI_REAL":{} |
32 } |
38 } |
33 |
39 |
34 HMI_TYPES = HMI_TYPES_DESC.keys() |
40 HMI_TYPES = HMI_TYPES_DESC.keys() |
35 |
41 |
36 from XSLTransform import XSLTransform |
|
37 from lxml.etree import XSLTApplyError |
|
38 |
42 |
39 ScriptDirectory = paths.AbsDir(__file__) |
43 ScriptDirectory = paths.AbsDir(__file__) |
40 |
44 |
41 class HMITreeNode(object): |
45 class HMITreeNode(object): |
42 def __init__(self, path, name, nodetype, iectype = None, vartype = None, hmiclass = None): |
46 def __init__(self, path, name, nodetype, iectype = None, vartype = None, hmiclass = None): |
125 # note: this only works because library's Generate_C is |
129 # note: this only works because library's Generate_C is |
126 # systematicaly invoked before CTN's CTNGenerate_C |
130 # systematicaly invoked before CTN's CTNGenerate_C |
127 |
131 |
128 hmi_tree_root = None |
132 hmi_tree_root = None |
129 |
133 |
|
134 hmi_tree_updated = None |
|
135 |
130 class SVGHMILibrary(POULibrary): |
136 class SVGHMILibrary(POULibrary): |
131 def GetLibraryPath(self): |
137 def GetLibraryPath(self): |
132 return paths.AbsNeighbourFile(__file__, "pous.xml") |
138 return paths.AbsNeighbourFile(__file__, "pous.xml") |
133 |
139 |
134 def Generate_C(self, buildpath, varlist, IECCFLAGS): |
140 def Generate_C(self, buildpath, varlist, IECCFLAGS): |
135 global hmi_tree_root, hmi_tree_unique_id |
141 global hmi_tree_root, hmi_tree_updated, hmi_tree_unique_id |
136 |
142 |
137 """ |
143 """ |
138 PLC Instance Tree: |
144 PLC Instance Tree: |
139 prog0 |
145 prog0 |
140 +->v1 HMI_INT |
146 +->v1 HMI_INT |
191 kwargs['hmiclass'] = path[-1] |
197 kwargs['hmiclass'] = path[-1] |
192 else: |
198 else: |
193 name = path[-1] |
199 name = path[-1] |
194 new_node = HMITreeNode(path, name, derived, v["type"], v["vartype"], **kwargs) |
200 new_node = HMITreeNode(path, name, derived, v["type"], v["vartype"], **kwargs) |
195 hmi_tree_root.place_node(new_node) |
201 hmi_tree_root.place_node(new_node) |
|
202 |
|
203 if hmi_tree_updated is not None: |
|
204 hmi_tree_updated() |
196 |
205 |
197 variable_decl_array = [] |
206 variable_decl_array = [] |
198 extern_variables_declarations = [] |
207 extern_variables_declarations = [] |
199 buf_index = 0 |
208 buf_index = 0 |
200 item_count = 0 |
209 item_count = 0 |
260 runtimefile.close() |
269 runtimefile.close() |
261 |
270 |
262 return ((["svghmi"], [(gen_svghmi_c_path, IECCFLAGS)], True), "", |
271 return ((["svghmi"], [(gen_svghmi_c_path, IECCFLAGS)], True), "", |
263 ("runtime_svghmi0.py", open(runtimefile_path, "rb"))) |
272 ("runtime_svghmi0.py", open(runtimefile_path, "rb"))) |
264 |
273 |
|
274 |
|
275 class SVGHMIEditor(ConfTreeNodeEditor): |
|
276 CONFNODEEDITOR_TABS = [ |
|
277 (_("HMI Tree"), "CreateHMITreeView")] |
|
278 |
|
279 def SVGHMIEditorUpdater(self): |
|
280 selfref = weakref.ref(self) |
|
281 def SVGHMIEditorUpdate(): |
|
282 o = selfref() |
|
283 if o is not None: |
|
284 wx.CallAfter(o.MakeTree) |
|
285 return SVGHMIEditorUpdate |
|
286 |
|
287 def CreateHMITreeView(self, parent): |
|
288 global hmi_tree_updated |
|
289 |
|
290 dvtc = dv.DataViewTreeCtrl(parent) |
|
291 isz = (16,16) |
|
292 self.ImageList = il = wx.ImageList(*isz) |
|
293 self.fldridx = il.AddIcon(wx.ArtProvider.GetIcon(wx.ART_FOLDER, wx.ART_OTHER, isz)) |
|
294 self.fldropenidx = il.AddIcon(wx.ArtProvider.GetIcon(wx.ART_FOLDER_OPEN, wx.ART_OTHER, isz)) |
|
295 self.fileidx = il.AddIcon(wx.ArtProvider.GetIcon(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz)) |
|
296 dvtc.SetImageList(il) |
|
297 |
|
298 |
|
299 self.HMITreeView = dvtc |
|
300 hmi_tree_updated = self.SVGHMIEditorUpdater() |
|
301 self.MakeTree() |
|
302 return self.HMITreeView |
|
303 |
|
304 def _recurseTree(self, current_hmitree_root, current_dvtc_root): |
|
305 dvtc = self.HMITreeView |
|
306 for c in current_hmitree_root.children: |
|
307 if hasattr(c, "children"): |
|
308 display_name = ('{} (class={})'.format(c.name, c.hmiclass)) \ |
|
309 if c.hmiclass is not None else c.name |
|
310 dvtc_child = dvtc.AppendContainer( |
|
311 current_dvtc_root, display_name, |
|
312 self.fldridx, self.fldropenidx) |
|
313 |
|
314 self._recurseTree(c,dvtc_child) |
|
315 else: |
|
316 display_name = '{} {}'.format(c.nodetype[4:], c.name) |
|
317 dvtc.AppendContainer( |
|
318 current_dvtc_root, display_name, |
|
319 self.fileidx, self.fileidx) |
|
320 |
|
321 def MakeTree(self): |
|
322 global hmi_tree_root |
|
323 |
|
324 dvtc = self.HMITreeView |
|
325 |
|
326 dvtc.Freeze() |
|
327 dvtc.DeleteAllItems() |
|
328 |
|
329 root_display_name = _("Please build to see HMI Tree") if hmi_tree_root is None else "HMI" |
|
330 root = dvtc.AppendContainer(dv.NullDataViewItem, |
|
331 root_display_name, |
|
332 self.fldridx, self.fldropenidx) |
|
333 if hmi_tree_root is not None: |
|
334 self._recurseTree(hmi_tree_root, root) |
|
335 dvtc.Thaw() |
|
336 |
265 class SVGHMI(object): |
337 class SVGHMI(object): |
266 XSD = """<?xml version="1.0" encoding="utf-8" ?> |
338 XSD = """<?xml version="1.0" encoding="utf-8" ?> |
267 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
339 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
268 <xsd:element name="SVGHMI"> |
340 <xsd:element name="SVGHMI"> |
269 <xsd:complexType> |
341 <xsd:complexType> |