# HG changeset patch # User Edouard Tisserant <edouard.tisserant@gmail.com> # Date 1586858828 -7200 # Node ID 90f9d9782632a93386e1e3dc32236eaa731c8a21 # Parent 220172cbdcffd92cd5089b048fa231c276f696ae SVGHMI: Add button element to HMI:DropDown, also fix problem with computed box margins. diff -r 220172cbdcff -r 90f9d9782632 svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Tue Apr 14 10:56:45 2020 +0200 +++ b/svghmi/gen_index_xhtml.xslt Tue Apr 14 12:07:08 2020 +0200 @@ -822,7 +822,7 @@ <xsl:call-template name="defs_by_labels"> <xsl:with-param name="hmi_element" select="$hmi_element"/> <xsl:with-param name="labels"> - <xsl:text>text box</xsl:text> + <xsl:text>text box button</xsl:text> </xsl:with-param> </xsl:call-template> <xsl:text> dispatch: function(value) { @@ -833,9 +833,9 @@ </xsl:text> <xsl:text> init: function() { </xsl:text> - <xsl:text> this.element.setAttribute("onclick", "hmi_widgets['</xsl:text> + <xsl:text> this.button_elt.setAttribute("onclick", "hmi_widgets['</xsl:text> <xsl:value-of select="$hmi_element/@id"/> - <xsl:text>'].on_click()"); + <xsl:text>'].on_button_click()"); </xsl:text> <xsl:text> this.text_bbox = this.text_elt.getBBox() </xsl:text> @@ -845,11 +845,7 @@ </xsl:text> <xsl:text> tmargin = this.text_bbox.y - this.box_bbox.y; </xsl:text> - <xsl:text> rmargin = this.box_bbox.width - this.text_bbox.width - lmargin; -</xsl:text> - <xsl:text> bmargin = this.box_bbox.height - this.text_bbox.height - tmargin; -</xsl:text> - <xsl:text> this.margins = [lmargin, tmargin, rmargin, bmargin].map(x => Math.max(x,0)); + <xsl:text> this.margins = [lmargin, tmargin].map(x => Math.max(x,0)); </xsl:text> <xsl:text> this.content = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", </xsl:text> @@ -867,106 +863,102 @@ </xsl:text> <xsl:text> on_selection_click: function(selection) { </xsl:text> + <xsl:text> console.log("selected "+selection); +</xsl:text> + <xsl:text> this.close(); +</xsl:text> <xsl:text> this.set_selection(selection); </xsl:text> <xsl:text> }, </xsl:text> - <xsl:text> on_click: function() { -</xsl:text> - <xsl:text> if(this.opened){ -</xsl:text> - <xsl:text> //this.close(); -</xsl:text> - <xsl:text> }else{ -</xsl:text> - <xsl:text> this.open(); + <xsl:text> on_button_click: function() { +</xsl:text> + <xsl:text> this.open(); +</xsl:text> + <xsl:text> }, +</xsl:text> + <xsl:text> on_backward_click:function(){ +</xsl:text> + <xsl:text> this.move(false); +</xsl:text> + <xsl:text> }, +</xsl:text> + <xsl:text> on_forward_click:function(){ +</xsl:text> + <xsl:text> this.move(true); +</xsl:text> + <xsl:text> }, +</xsl:text> + <xsl:text> set_selection: function(value) { +</xsl:text> + <xsl:text> this.text_elt.firstElementChild.textContent = +</xsl:text> + <xsl:text> (value >= 0 && value < this.content.length) ? +</xsl:text> + <xsl:text> this.content[value] : "?"+String(value)+"?"; +</xsl:text> + <xsl:text> }, +</xsl:text> + <xsl:text> grow_text: function(up_to) { +</xsl:text> + <xsl:text> let count = 1; +</xsl:text> + <xsl:text> let txt = this.text_elt; +</xsl:text> + <xsl:text> let first = txt.firstElementChild; +</xsl:text> + <xsl:text> let bounds = svg_root.getBoundingClientRect(); +</xsl:text> + <xsl:text> this.lift = 0; +</xsl:text> + <xsl:text> while(count < up_to) { +</xsl:text> + <xsl:text> let next = first.cloneNode(); +</xsl:text> + <xsl:text> next.removeAttribute("y"); +</xsl:text> + <xsl:text> next.setAttribute("dy", "1.1em"); +</xsl:text> + <xsl:text> next.textContent = "..."; +</xsl:text> + <xsl:text> txt.appendChild(next); +</xsl:text> + <xsl:text> let rect = txt.getBoundingClientRect(); +</xsl:text> + <xsl:text> if(rect.bottom > bounds.bottom){ +</xsl:text> + <xsl:text> let backup = first.getAttribute("dy"); +</xsl:text> + <xsl:text> first.setAttribute("dy", "-"+String((this.lift+1)*1.1)+"em"); +</xsl:text> + <xsl:text> rect = txt.getBoundingClientRect(); +</xsl:text> + <xsl:text> if(rect.top > bounds.top){ +</xsl:text> + <xsl:text> this.lift += 1; +</xsl:text> + <xsl:text> } else { +</xsl:text> + <xsl:text> if(backup) +</xsl:text> + <xsl:text> first.setAttribute("dy", backup); +</xsl:text> + <xsl:text> else +</xsl:text> + <xsl:text> first.removeAttribute("dy"); +</xsl:text> + <xsl:text> txt.removeChild(next); +</xsl:text> + <xsl:text> return count; +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> } +</xsl:text> + <xsl:text> count++; </xsl:text> <xsl:text> } </xsl:text> - <xsl:text> }, -</xsl:text> - <xsl:text> on_backward_click:function(){ -</xsl:text> - <xsl:text> this.move(false); -</xsl:text> - <xsl:text> }, -</xsl:text> - <xsl:text> on_forward_click:function(){ -</xsl:text> - <xsl:text> this.move(true); -</xsl:text> - <xsl:text> }, -</xsl:text> - <xsl:text> set_selection: function(value) { -</xsl:text> - <xsl:text> this.text_elt.firstElementChild.textContent = -</xsl:text> - <xsl:text> (value >= 0 && value < this.content.length) ? -</xsl:text> - <xsl:text> this.content[value] : "?"+String(value)+"?"; -</xsl:text> - <xsl:text> }, -</xsl:text> - <xsl:text> grow_text: function(up_to) { -</xsl:text> - <xsl:text> let count = 1; -</xsl:text> - <xsl:text> let txt = this.text_elt; -</xsl:text> - <xsl:text> let first = txt.firstElementChild; -</xsl:text> - <xsl:text> let bounds = svg_root.getBoundingClientRect(); -</xsl:text> - <xsl:text> this.lift = 0; -</xsl:text> - <xsl:text> while(count < up_to) { -</xsl:text> - <xsl:text> let next = first.cloneNode(); -</xsl:text> - <xsl:text> next.removeAttribute("y"); -</xsl:text> - <xsl:text> next.setAttribute("dy", "1.1em"); -</xsl:text> - <xsl:text> next.textContent = "..."; -</xsl:text> - <xsl:text> txt.appendChild(next); -</xsl:text> - <xsl:text> let rect = txt.getBoundingClientRect(); -</xsl:text> - <xsl:text> if(rect.bottom > bounds.bottom){ -</xsl:text> - <xsl:text> let backup = first.getAttribute("dy"); -</xsl:text> - <xsl:text> first.setAttribute("dy", "-"+String((this.lift+1)*1.1)+"em"); -</xsl:text> - <xsl:text> rect = txt.getBoundingClientRect(); -</xsl:text> - <xsl:text> if(rect.top > bounds.top){ -</xsl:text> - <xsl:text> this.lift += 1; -</xsl:text> - <xsl:text> } else { -</xsl:text> - <xsl:text> if(backup) -</xsl:text> - <xsl:text> first.setAttribute("dy", backup); -</xsl:text> - <xsl:text> else -</xsl:text> - <xsl:text> first.removeAttribute("dy"); -</xsl:text> - <xsl:text> txt.removeChild(next); -</xsl:text> - <xsl:text> return count; -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> } -</xsl:text> - <xsl:text> count++; -</xsl:text> - <xsl:text> } -</xsl:text> <xsl:text> return count; </xsl:text> <xsl:text> }, @@ -977,6 +969,8 @@ </xsl:text> <xsl:text> this.reset_box(); </xsl:text> + <xsl:text> this.element.appendChild(this.button_elt); +</xsl:text> <xsl:text> this.opened = false; </xsl:text> <xsl:text> }, @@ -1107,6 +1101,8 @@ </xsl:text> <xsl:text> this.adjust_box_to_text(); </xsl:text> + <xsl:text> this.element.removeChild(this.button_elt); +</xsl:text> <xsl:text> /* TODO disable interaction with background */ </xsl:text> <xsl:text> this.opened = true; @@ -1149,7 +1145,7 @@ </xsl:text> <xsl:text> adjust_box_to_text: function(){ </xsl:text> - <xsl:text> let [lmargin, tmargin, rmargin, bmargin] = this.margins; + <xsl:text> let [lmargin, tmargin] = this.margins; </xsl:text> <xsl:text> let m = this.text_elt.getBBox(); </xsl:text> @@ -1159,9 +1155,9 @@ </xsl:text> <xsl:text> b.y.baseVal.value = m.y - tmargin; </xsl:text> - <xsl:text> b.width.baseVal.value = lmargin + m.width + rmargin; -</xsl:text> - <xsl:text> b.height.baseVal.value = tmargin + m.height + bmargin; + <xsl:text> b.width.baseVal.value = 2 * lmargin + m.width; +</xsl:text> + <xsl:text> b.height.baseVal.value = 2 * tmargin + m.height; </xsl:text> <xsl:text> }, </xsl:text> diff -r 220172cbdcff -r 90f9d9782632 svghmi/widget_dropdown.ysl2 --- a/svghmi/widget_dropdown.ysl2 Tue Apr 14 10:56:45 2020 +0200 +++ b/svghmi/widget_dropdown.ysl2 Tue Apr 14 12:07:08 2020 +0200 @@ -2,20 +2,18 @@ template "widget[@type='DropDown']", mode="widget_defs" { param "hmi_element"; - labels("text box"); + labels("text box button"); || dispatch: function(value) { if(!this.opened) this.set_selection(value); }, init: function() { - this.element.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_click()"); + this.button_elt.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_button_click()"); this.text_bbox = this.text_elt.getBBox() this.box_bbox = this.box_elt.getBBox() lmargin = this.text_bbox.x - this.box_bbox.x; tmargin = this.text_bbox.y - this.box_bbox.y; - rmargin = this.box_bbox.width - this.text_bbox.width - lmargin; - bmargin = this.box_bbox.height - this.text_bbox.height - tmargin; - this.margins = [lmargin, tmargin, rmargin, bmargin].map(x => Math.max(x,0)); + this.margins = [lmargin, tmargin].map(x => Math.max(x,0)); this.content = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen"]; //this.content = ["one", "two", "three", "four", "5", "6"]; @@ -24,14 +22,12 @@ this.opened = false; }, on_selection_click: function(selection) { + console.log("selected "+selection); + this.close(); this.set_selection(selection); }, - on_click: function() { - if(this.opened){ - //this.close(); - }else{ - this.open(); - } + on_button_click: function() { + this.open(); }, on_backward_click:function(){ this.move(false); @@ -79,6 +75,7 @@ close: function(){ this.reset_text(); this.reset_box(); + this.element.appendChild(this.button_elt); this.opened = false; }, set_complete_text: function(){ @@ -140,6 +137,7 @@ this.set_partial_text(); } this.adjust_box_to_text(); + this.element.removeChild(this.button_elt); /* TODO disable interaction with background */ this.opened = true; }, @@ -161,13 +159,13 @@ b.height.baseVal.value = m.height; }, adjust_box_to_text: function(){ - let [lmargin, tmargin, rmargin, bmargin] = this.margins; + let [lmargin, tmargin] = this.margins; let m = this.text_elt.getBBox(); let b = this.box_elt; b.x.baseVal.value = m.x - lmargin; b.y.baseVal.value = m.y - tmargin; - b.width.baseVal.value = lmargin + m.width + rmargin; - b.height.baseVal.value = tmargin + m.height + bmargin; + b.width.baseVal.value = 2 * lmargin + m.width; + b.height.baseVal.value = 2 * tmargin + m.height; }, || } diff -r 220172cbdcff -r 90f9d9782632 tests/svghmi/svghmi_0@svghmi/svghmi.svg --- a/tests/svghmi/svghmi_0@svghmi/svghmi.svg Tue Apr 14 10:56:45 2020 +0200 +++ b/tests/svghmi/svghmi_0@svghmi/svghmi.svg Tue Apr 14 12:07:08 2020 +0200 @@ -16,7 +16,7 @@ version="1.1" id="hmi0" sodipodi:docname="svghmi.svg" - inkscape:version="0.92.3 (2405546, 2018-03-11)"> + inkscape:version="0.92.4 (5da689c313, 2019-01-14)"> <metadata id="metadata4542"> <rdf:RDF> @@ -124,17 +124,17 @@ inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:document-units="px" - inkscape:current-layer="g2432" + inkscape:current-layer="g14237" showgrid="false" units="px" inkscape:zoom="0.35355339" inkscape:cx="-418.67433" inkscape:cy="-1206.7258" - inkscape:window-width="1800" - inkscape:window-height="836" - inkscape:window-x="0" - inkscape:window-y="27" - inkscape:window-maximized="1" + inkscape:window-width="2112" + inkscape:window-height="1367" + inkscape:window-x="2960" + inkscape:window-y="54" + inkscape:window-maximized="0" showguides="true" inkscape:guide-bbox="true" /> <rect @@ -1124,7 +1124,7 @@ </g> </g> <g - transform="matrix(0.5,0,0,0.5,828.32451,303.15679)" + transform="matrix(0.5,0,0,0.5,126.87458,546.40152)" id="g208-1-8" inkscape:label="HMI:Input@/PUMP0/STRIN" style="stroke-width:2"> @@ -2492,33 +2492,52 @@ </g> <g id="g14237" - inkscape:label="HMI:DropDown:Primes"> + inkscape:label="HMI:DropDown:Primes" + transform="translate(0,-640)"> <rect style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#53676c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" id="rect14212" - width="299.99988" - height="136.9433" - x="956.00842" - y="917.98993" + width="391.99988" + height="130.9433" + x="864.00842" + y="923.98993" rx="7" ry="7" inkscape:label="box" /> <text id="text14183" y="1011.9975" - x="1080.6298" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:80px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="881.44226" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:80px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#d42aff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve" inkscape:label="text"><tspan - style="stroke-width:1px" + style="text-align:start;text-anchor:start;fill:#d42aff;stroke-width:1px" y="1011.9975" - x="1080.6298" - id="tspan14181" - sodipodi:role="line">sel_0</tspan></text> + x="881.44226" + sodipodi:role="line" + id="tspan421">sel_0</tspan></text> + <path + sodipodi:type="star" + style="opacity:1;vector-effect:none;fill:#a7a5a6;fill-opacity:1;stroke:none;stroke-width:0.35277769;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="path424" + sodipodi:sides="3" + sodipodi:cx="1200.5" + sodipodi:cy="975" + sodipodi:r1="43.683521" + sodipodi:r2="21.841761" + sodipodi:arg1="1.5707963" + sodipodi:arg2="2.6179939" + inkscape:flatsided="false" + inkscape:rounded="0" + inkscape:randomized="0" + d="m 1200.5,1018.6835 -18.9155,-32.76262 -18.9155,-32.76264 37.831,0 37.831,0 -18.9155,32.76264 z" + inkscape:transform-center-y="10.92088" + inkscape:label="button" /> </g> <g id="g14232" - inkscape:label="HMI:ScrollbarTemplate"> + inkscape:label="HMI:ScrollbarTemplate" + transform="translate(0,-640)"> <rect ry="7" rx="7" @@ -2556,38 +2575,38 @@ </g> <text id="text14183-9" - y="845.03906" + y="205.03906" x="1493.8926" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" xml:space="preserve" inkscape:label="HMI:List:Primes"><tspan style="stroke-width:1px" - y="845.03906" + y="205.03906" x="1493.8926" id="tspan14181-1" sodipodi:role="line">one</tspan><tspan style="stroke-width:1px" - y="895.03906" + y="255.03906" x="1493.8926" sodipodi:role="line" id="tspan14257">two</tspan><tspan style="stroke-width:1px" - y="945.03906" + y="305.03906" x="1493.8926" sodipodi:role="line" id="tspan14259">three</tspan><tspan style="stroke-width:1px" - y="995.03906" + y="355.03906" x="1493.8926" sodipodi:role="line" id="tspan14261">five</tspan><tspan style="stroke-width:1px" - y="1045.0391" + y="405.03906" x="1493.8926" sodipodi:role="line" id="tspan14263">seven</tspan><tspan style="stroke-width:1px" - y="1095.0391" + y="455.03906" x="1493.8926" sodipodi:role="line" id="tspan14265">eleven</tspan></text>