75 if best_child is not None and best_child.nodetype == "HMI_LABEL": |
75 if best_child is not None and best_child.nodetype == "HMI_LABEL": |
76 best_child.place_node(node) |
76 best_child.place_node(node) |
77 else: |
77 else: |
78 self.children.append(node) |
78 self.children.append(node) |
79 |
79 |
80 def etree(self): |
80 def etree(self, add_hash=False): |
81 |
81 |
82 attribs = dict(name=self.name) |
82 attribs = dict(name=self.name) |
83 if self.path is not None: |
83 if self.path is not None: |
84 attribs["path"]=".".join(self.path) |
84 attribs["path"] = ".".join(self.path) |
|
85 |
|
86 if add_hash: |
|
87 attribs["hash"] = ",".join(map(str,self.hash())) |
85 |
88 |
86 res = etree.Element(self.nodetype, **attribs) |
89 res = etree.Element(self.nodetype, **attribs) |
87 |
90 |
88 if hasattr(self, "children"): |
91 if hasattr(self, "children"): |
89 for child_etree in imap(lambda c:c.etree(), self.children): |
92 for child_etree in imap(lambda c:c.etree(), self.children): |
96 if hasattr(self, "children"): |
99 if hasattr(self, "children"): |
97 for c in self.children: |
100 for c in self.children: |
98 for yoodl in c.traverse(): |
101 for yoodl in c.traverse(): |
99 yield yoodl |
102 yield yoodl |
100 |
103 |
|
104 |
|
105 def hash(self): |
|
106 """ Produce a hash, any change in HMI tree structure change that hash """ |
|
107 s = hashlib.new('md5') |
|
108 self._hash(s) |
|
109 # limit size to HMI_HASH_SIZE as in svghmi.c |
|
110 return map(ord,s.digest())[:8] |
|
111 |
|
112 def _hash(self, s): |
|
113 s.update(str((self.name,self.nodetype))) |
|
114 if hasattr(self, "children"): |
|
115 for c in self.children: |
|
116 c._hash(s) |
|
117 |
101 # module scope for HMITree root |
118 # module scope for HMITree root |
102 # so that CTN can use HMITree deduced in Library |
119 # so that CTN can use HMITree deduced in Library |
103 # note: this only works because library's Generate_C is |
120 # note: this only works because library's Generate_C is |
104 # systematicaly invoked before CTN's CTNGenerate_C |
121 # systematicaly invoked before CTN's CTNGenerate_C |
105 |
122 |
108 class SVGHMILibrary(POULibrary): |
125 class SVGHMILibrary(POULibrary): |
109 def GetLibraryPath(self): |
126 def GetLibraryPath(self): |
110 return paths.AbsNeighbourFile(__file__, "pous.xml") |
127 return paths.AbsNeighbourFile(__file__, "pous.xml") |
111 |
128 |
112 def Generate_C(self, buildpath, varlist, IECCFLAGS): |
129 def Generate_C(self, buildpath, varlist, IECCFLAGS): |
113 global hmi_tree_root |
130 global hmi_tree_root, hmi_tree_unique_id |
114 |
131 |
115 """ |
132 """ |
116 PLC Instance Tree: |
133 PLC Instance Tree: |
117 prog0 |
134 prog0 |
118 +->v1 HMI_INT |
135 +->v1 HMI_INT |
168 variable_decl_array = [] |
185 variable_decl_array = [] |
169 extern_variables_declarations = [] |
186 extern_variables_declarations = [] |
170 buf_index = 0 |
187 buf_index = 0 |
171 item_count = 0 |
188 item_count = 0 |
172 for node in hmi_tree_root.traverse(): |
189 for node in hmi_tree_root.traverse(): |
173 if hasattr(node, "iectype"): |
190 if hasattr(node, "iectype") and \ |
|
191 node.nodetype not in ["HMI_CLASS", "HMI_LABEL"]: |
174 sz = DebugTypesSize.get(node.iectype, 0) |
192 sz = DebugTypesSize.get(node.iectype, 0) |
175 variable_decl_array += [ |
193 variable_decl_array += [ |
176 "{&(" + ".".join(node.path) + "), " + node.iectype + { |
194 "{&(" + ".".join(node.path) + "), " + node.iectype + { |
177 "EXT": "_P_ENUM", |
195 "EXT": "_P_ENUM", |
178 "IN": "_P_ENUM", |
196 "IN": "_P_ENUM", |
208 "variable_decl_array": ",\n".join(variable_decl_array), |
226 "variable_decl_array": ",\n".join(variable_decl_array), |
209 "extern_variables_declarations": "\n".join(extern_variables_declarations), |
227 "extern_variables_declarations": "\n".join(extern_variables_declarations), |
210 "buffer_size": buf_index, |
228 "buffer_size": buf_index, |
211 "item_count": item_count, |
229 "item_count": item_count, |
212 "var_access_code": targets.GetCode("var_access.c"), |
230 "var_access_code": targets.GetCode("var_access.c"), |
213 "PLC_ticktime": self.GetCTR().GetTicktime() |
231 "PLC_ticktime": self.GetCTR().GetTicktime(), |
|
232 "hmi_hash_int": ",".join(map(str,hmi_tree_root.hash())) |
214 } |
233 } |
215 |
234 |
216 gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c") |
235 gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c") |
217 gen_svghmi_c = open(gen_svghmi_c_path, 'w') |
236 gen_svghmi_c = open(gen_svghmi_c_path, 'w') |
218 gen_svghmi_c.write(svghmi_c_code) |
237 gen_svghmi_c.write(svghmi_c_code) |
256 "name": _("Inkscape"), |
276 "name": _("Inkscape"), |
257 "tooltip": _("Edit HMI"), |
277 "tooltip": _("Edit HMI"), |
258 "method": "_StartInkscape" |
278 "method": "_StartInkscape" |
259 }, |
279 }, |
260 |
280 |
|
281 # TODO : Launch POEdit button |
|
282 # PO -> SVG layers button |
|
283 # SVG layers -> PO |
|
284 |
261 # TODO : HMITree button |
285 # TODO : HMITree button |
262 # - can drag'n'drop variabes to Inkscape |
286 # - can drag'n'drop variabes to Inkscape |
263 |
287 |
264 ] |
288 ] |
265 |
289 |