# HG changeset patch
# User Edouard Tisserant
# Date 1664349547 -7200
# Node ID bb1eff4091ab2804fa4d777dce63075698eb1381
# Parent 770c613c424ffe2c8f9b3f0ebe601cbca6c49d1d
SVGHMI: add support for "reference" and "frame" rectangles to spread-out ovelapping elements.
When HMI become complicated, designer needs to spread-out ovelapping elements
in order to unclutter drawing and facilitate maintenance.
diff -r 770c613c424f -r bb1eff4091ab exemples/svghmi_references/beremiz.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/exemples/svghmi_references/beremiz.xml Wed Sep 28 09:19:07 2022 +0200
@@ -0,0 +1,5 @@
+
+
+
+
+
diff -r 770c613c424f -r bb1eff4091ab exemples/svghmi_references/plc.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/exemples/svghmi_references/plc.xml Wed Sep 28 09:19:07 2022 +0200
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ LocalVar0
+
+
+
+
+
+
+
+
+
+
+ LocalVar1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 770c613c424f -r bb1eff4091ab exemples/svghmi_references/svghmi_0@svghmi/baseconfnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/exemples/svghmi_references/svghmi_0@svghmi/baseconfnode.xml Wed Sep 28 09:19:07 2022 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 770c613c424f -r bb1eff4091ab exemples/svghmi_references/svghmi_0@svghmi/confnode.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/exemples/svghmi_references/svghmi_0@svghmi/confnode.xml Wed Sep 28 09:19:07 2022 +0200
@@ -0,0 +1,2 @@
+
+
diff -r 770c613c424f -r bb1eff4091ab exemples/svghmi_references/svghmi_0@svghmi/svghmi.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/exemples/svghmi_references/svghmi_0@svghmi/svghmi.svg Wed Sep 28 09:19:07 2022 +0200
@@ -0,0 +1,1236 @@
+
+
+
+
diff -r 770c613c424f -r bb1eff4091ab svghmi/geometry.ysl2
--- a/svghmi/geometry.ysl2 Thu Sep 22 09:42:38 2022 +0200
+++ b/svghmi/geometry.ysl2 Wed Sep 28 09:19:07 2022 +0200
@@ -145,3 +145,16 @@
result """$candidates[(@Id = $groups/@id and (func:intersect($g, .) = 9)) or
(not(@Id = $groups/@id) and (func:intersect($g, .) > 0 ))]""";
}
+
+def "func:offset" {
+ param "elt1";
+ param "elt2";
+ const "g1", "$geometry[@Id = $elt1/@id]";
+ const "g2", "$geometry[@Id = $elt2/@id]";
+ const "result" vector {
+ attrib "x" value "$g2/@x - $g1/@x";
+ attrib "y" value "$g2/@y - $g1/@y";
+ }
+ result "exsl:node-set($result)";
+}
+
diff -r 770c613c424f -r bb1eff4091ab svghmi/inline_svg.ysl2
--- a/svghmi/inline_svg.ysl2 Thu Sep 22 09:42:38 2022 +0200
+++ b/svghmi/inline_svg.ysl2 Wed Sep 28 09:19:07 2022 +0200
@@ -42,6 +42,23 @@
attrib "{name()}" > «substring(., 2)»
}
+// remove "reference" and "frame" rectangles
+svgtmpl "svg:rect[@inkscape:label='reference' or @inkscape:label='frame']", mode="inline_svg" {
+ // nothing
+}
+
+svgtmpl "svg:g[svg:rect/@inkscape:label='frame']", mode="inline_svg" {
+ const "reference_rect","(../svg:rect | ../svg:g/svg:rect)[@inkscape:label='reference']";
+ const "frame_rect","svg:rect[@inkscape:label='frame']";
+ const "offset","func:offset($frame_rect, $reference_rect)";
+
+ xsl:copy {
+ attrib "svghmi_x_offset" value "$offset/vector/@x";
+ attrib "svghmi_y_offset" value "$offset/vector/@y";
+ apply "@* | node()", mode="inline_svg";
+ }
+}
+
////// Clone unlinking
//
// svg:use (inkscape's clones) inside a widgets are
diff -r 770c613c424f -r bb1eff4091ab svghmi/svghmi.js
--- a/svghmi/svghmi.js Thu Sep 22 09:42:38 2022 +0200
+++ b/svghmi/svghmi.js Wed Sep 28 09:19:07 2022 +0200
@@ -532,8 +532,49 @@
current_visible_page = page_name;
};
+/* From https://jsfiddle.net/ibowankenobi/1mmh7rs6/6/ */
+function getAbsoluteCTM(element){
+ var height = svg_root.height.baseVal.value,
+ width = svg_root.width.baseVal.value,
+ viewBoxRect = svg_root.viewBox.baseVal,
+ vHeight = viewBoxRect.height,
+ vWidth = viewBoxRect.width;
+ if(!vWidth || !vHeight){
+ return element.getCTM();
+ }
+ var sH = height/vHeight,
+ sW = width/vWidth,
+ matrix = svg_root.createSVGMatrix();
+ matrix.a = sW;
+ matrix.d = sH
+ var realCTM = element.getCTM().multiply(matrix.inverse());
+ realCTM.e = realCTM.e/sW + viewBoxRect.x;
+ realCTM.f = realCTM.f/sH + viewBoxRect.y;
+ return realCTM;
+}
+
+function apply_reference_frames(){
+ const matches = svg_root.querySelectorAll("g[svghmi_x_offset]");
+ matches.forEach((group) => {
+ let [x,y] = ["x", "y"].map((axis) => Number(group.getAttribute("svghmi_"+axis+"_offset")));
+ let ctm = getAbsoluteCTM(group);
+ // zero translation part of CTM
+ // to only apply rotation/skewing to offset vector
+ ctm.e = 0;
+ ctm.f = 0;
+ let invctm = ctm.inverse();
+ let vect = new DOMPoint(x, y);
+ let newvect = vect.matrixTransform(invctm);
+ let transform = svg_root.createSVGTransform();
+ transform.setTranslate(newvect.x, newvect.y);
+ group.transform.baseVal.appendItem(transform);
+ ["x", "y"].forEach((axis) => group.removeAttribute("svghmi_"+axis+"_offset"));
+ });
+}
+
// Once connection established
ws.onopen = function (evt) {
+ apply_reference_frames();
init_widgets();
send_reset();
// show main page