# HG changeset patch # User usveticic # Date 1596633239 -7200 # Node ID 893cc309f5e245424036b514cd6bb1f4ca2f2ce9 # Parent 7c6960f09881cf522425bae75c14d1e9327e8917 Changed keyboard to show on defined position. * svghmi.js added size paramter to edit_value changed show_modal function to offset keyboard if paramter passed *widget_input.ysl2 in on_edit_click: function get position if key_pos element is defined in input widget *widget_keypad.ysl2 Reworked keypad widget to extand class widget, added support for changing keyboard position to user defined location diff -r 7c6960f09881 -r 893cc309f5e2 svghmi/svghmi.js --- a/svghmi/svghmi.js Wed Aug 05 15:04:53 2020 +0200 +++ b/svghmi/svghmi.js Wed Aug 05 15:13:59 2020 +0200 @@ -395,26 +395,31 @@ var xmlns = "http://www.w3.org/2000/svg"; var edit_callback; -function edit_value(path, valuetype, callback, initial) { +function edit_value(path, valuetype, callback, initial, size) { let [keypadid, xcoord, ycoord] = keypads[valuetype]; console.log('XXX TODO : Edit value', path, valuetype, callback, initial, keypadid); edit_callback = callback; let widget = hmi_widgets[keypadid]; - widget.start_edit(path, valuetype, callback, initial); + widget.start_edit(path, valuetype, callback, initial, size); }; var current_modal; /* TODO stack ?*/ -function show_modal() { +function show_modal(size) { let [element, parent] = detachable_elements[this.element.id]; tmpgrp = document.createElementNS(xmlns,"g"); tmpgrpattr = document.createAttribute("transform"); - let [xcoord,ycoord] = this.coordinates; let [xdest,ydest] = page_desc[current_visible_page].bbox; - tmpgrpattr.value = "translate("+String(xdest-xcoord)+","+String(ydest-ycoord)+")"; + if (typeof size === 'undefined'){ + tmpgrpattr.value = "translate("+String(xdest-xcoord)+","+String(ydest-ycoord)+")"; + } + else{ + tmpgrpattr.value = "translate("+String(xdest-xcoord+size.x)+","+String(ydest-ycoord+size.y)+")"; + } + tmpgrp.setAttributeNode(tmpgrpattr); tmpgrp.appendChild(element); diff -r 7c6960f09881 -r 893cc309f5e2 svghmi/widget_input.ysl2 --- a/svghmi/widget_input.ysl2 Wed Aug 05 15:04:53 2020 +0200 +++ b/svghmi/widget_input.ysl2 Wed Aug 05 15:13:59 2020 +0200 @@ -2,6 +2,7 @@ template "widget[@type='Input']", mode="widget_defs" { param "hmi_element"; + optional_labels("key_pos"); const "value_elt" { optional_labels("value"); } @@ -33,7 +34,8 @@ // } | }, | on_edit_click: function(opstr) { - | edit_value("«path/@value»", "«path/@type»", this, this.last_val); + | var size = (typeof this.key_pos_elt !== 'undefined') ? this.key_pos_elt.getBBox() : undefined + | edit_value("«path/@value»", "«path/@type»", this, this.last_val,size); | }, | edit_callback: function(new_val) { diff -r 7c6960f09881 -r 893cc309f5e2 svghmi/widget_keypad.ysl2 --- a/svghmi/widget_keypad.ysl2 Wed Aug 05 15:04:53 2020 +0200 +++ b/svghmi/widget_keypad.ysl2 Wed Aug 05 15:13:59 2020 +0200 @@ -13,10 +13,159 @@ | } } +template "widget[@type='Keypad']", mode="widget_class" + || + class KeypadWidget extends Widget{ + moving = undefined; + enTimer = undefined; + offset = undefined; + + on_position_click(evt) { + this.moving = true; + this.enTimer = true; + + // get click position offset from widget x,y and save it to variable + var keypad_borders = this.position_elt.getBoundingClientRect(); + var clickX = undefined; + var clickY = undefined; + if (evt.type == "touchstart"){ + clickX = Math.ceil(evt.touches[0].clientX); + clickY = Math.ceil(evt.touches[0].clientY); + } + else{ + clickX = evt.pageX; + clickY = evt.pageY; + } + this.offset=[clickX-keypad_borders.left,clickY-keypad_borders.top] + } + + off_position_click(evt) { + if(this.moving) + this.moving = false; + } + + on_move(evt) { + if(this.moving && this.enTimer){ + //get keyboard pos in html + let [eltid, tmpgrp] = current_modal; + let [xcoord,ycoord] = this.coordinates; + let [xdest,ydest,svgWidth,svgHeight] = page_desc[current_visible_page].bbox; + + //get mouse coordinates + var clickX = undefined; + var clickY = undefined; + if (evt.type == "touchmove"){ + clickX = Math.ceil(evt.touches[0].clientX); + clickY = Math.ceil(evt.touches[0].clientY); + } + else{ + clickX = evt.pageX; + clickY = evt.pageY; + } + + //translate keyboard position + let mouseX = ((clickX-this.offset[0])/window.innerWidth)*svgWidth; + let mouseY = ((clickY-this.offset[1])/window.innerHeight)*svgHeight; + tmpgrp.setAttribute("transform","translate("+String(xdest-xcoord+mouseX)+","+String(ydest-ycoord+mouseY)+")"); + + //reset timer + this.enTimer = false; + setTimeout("{hmi_widgets['"+this.element_id+"'].enTimer = true;}", 100); + } + + } + + on_key_click(symbols) { + var syms = symbols.split(" "); + this.shift |= this.caps; + this.editstr += syms[this.shift?syms.length-1:0]; + this.shift = false; + this.update(); + } + + on_Esc_click() { + end_modal.call(this); + } + + on_Enter_click() { + end_modal.call(this); + let callback_obj = this.result_callback_obj; + callback_obj.edit_callback(this.editstr); + } + + on_BackSpace_click() { + this.editstr = this.editstr.slice(0,this.editstr.length-1); + this.update(); + } + + on_Sign_click() { + if(this.editstr[0] == "-") + this.editstr = this.editstr.slice(1,this.editstr.length); + else + this.editstr = "-" + this.editstr; + this.update(); + } + + on_NumDot_click() { + if(this.editstr.indexOf(".") == "-1"){ + this.editstr += "."; + this.update(); + } + } + + on_Space_click() { + this.editstr += " "; + this.update(); + } + + caps = false; + _caps = undefined; + on_CapsLock_click() { + this.caps = !this.caps; + this.update(); + } + + shift = false; + _shift = undefined; + on_Shift_click() { + this.shift = !this.shift; + this.caps = false; + this.update(); + } + editstr = ""; + _editstr = undefined; + result_callback_obj = undefined; + start_edit(info, valuetype, callback_obj, initial,size) { + show_modal.call(this,size); + this.editstr = initial; + this.result_callback_obj = callback_obj; + this.Info_elt.textContent = info; + this.shift = false; + this.caps = false; + this.update(); + } + + update() { + if(this.editstr != this._editstr){ + this._editstr = this.editstr; + this.Value_elt.textContent = this.editstr; + } + if(this.shift != this._shift){ + this._shift = this.shift; + (this.shift?widget_active_activable:widget_inactive_activable)(this.Shift_sub); + } + if(this.caps != this._caps){ + this._caps = this.caps; + (this.caps?widget_active_activable:widget_inactive_activable)(this.CapsLock_sub); + } + } + } + || + template "widget[@type='Keypad']", mode="widget_defs" { param "hmi_element"; labels("Esc Enter BackSpace Keys Info Value"); - optional_labels("Sign Space NumDot"); + optional_labels("Sign Space NumDot position"); activable_labels("CapsLock Shift"); | init: function() { foreach "$hmi_element/*[@inkscape:label = 'Keys']/*" { @@ -26,82 +175,19 @@ | if(this.«.»_elt) | this.«.»_elt.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_«.»_click()"); } + | if(this.position_elt){ + | this.position_elt.setAttribute("onmousedown", "hmi_widgets['"+this.element_id+"'].on_position_click(evt)"); + | this.position_elt.setAttribute("ontouchstart", "hmi_widgets['"+this.element_id+"'].on_position_click(evt)"); + + | window.addEventListener("mouseup", hmi_widgets[this.element_id].off_position_click.bind(this)); + | window.addEventListener("touchend", hmi_widgets[this.element_id].off_position_click.bind(this)); + | window.addEventListener("touchcancel", hmi_widgets[this.element_id].off_position_click.bind(this)); + + | window.addEventListener("mousemove", hmi_widgets[this.element_id].on_move.bind(this)); + | window.addEventListener("touchmove", hmi_widgets[this.element_id].on_move.bind(this)); + | } | }, - | on_key_click: function(symbols) { - | var syms = symbols.split(" "); - | this.shift |= this.caps; - | this.editstr += syms[this.shift?syms.length-1:0]; - | this.shift = false; - | this.update(); - | }, - | on_Esc_click: function() { - | end_modal.call(this); - | }, - | on_Enter_click: function() { - | end_modal.call(this); - | callback_obj = this.result_callback_obj; - | callback_obj.edit_callback(this.editstr); - | }, - | on_BackSpace_click: function() { - | this.editstr = this.editstr.slice(0,this.editstr.length-1); - | this.update(); - | }, - | on_Sign_click: function() { - | if(this.editstr[0] == "-") - | this.editstr = this.editstr.slice(1,this.editstr.length); - | else - | this.editstr = "-" + this.editstr; - | this.update(); - | }, - | on_NumDot_click: function() { - | if(this.editstr.indexOf(".") == "-1"){ - | this.editstr += "."; - | this.update(); - | } - | }, - | on_Space_click: function() { - | this.editstr += " "; - | this.update(); - | }, - | caps: false, - | _caps: undefined, - | on_CapsLock_click: function() { - | this.caps = !this.caps; - | this.update(); - | }, - | shift: false, - | _shift: undefined, - | on_Shift_click: function() { - | this.shift = !this.shift; - | this.caps = false; - | this.update(); - | }, + | const "g", "$geometry[@Id = $hmi_element/@id]"; | coordinates: [«$g/@x», «$g/@y»], - | editstr: "", - | _editstr: undefined, - | result_callback_obj: undefined, - | start_edit: function(info, valuetype, callback_obj, initial) { - | show_modal.call(this); - | this.editstr = initial; - | this.result_callback_obj = callback_obj; - | this.Info_elt.textContent = info; - | this.shift = false; - | this.caps = false; - | this.update(); - | }, - | update: function() { - | if(this.editstr != this._editstr){ - | this._editstr = this.editstr; - | this.Value_elt.textContent = this.editstr; - | } - | if(this.shift != this._shift){ - | this._shift = this.shift; - | (this.shift?widget_active_activable:widget_inactive_activable)(this.Shift_sub); - | } - | if(this.caps != this._caps){ - | this._caps = this.caps; - | (this.caps?widget_active_activable:widget_inactive_activable)(this.CapsLock_sub); - | } - | }, }