svghmi/widget_keypad.ysl2
author Edouard Tisserant <edouard.tisserant@gmail.com>
Fri, 15 Jan 2021 10:15:41 +0100
branchsvghmi
changeset 3110 476bd870313d
parent 3102 abb487b56911
child 3118 e704b0487515
permissions -rw-r--r--
merge
// widget_keypad.ysl2

emit "declarations:keypad" {
    |
    | var keypads = {
    foreach "$keypads_descs"{
        const "keypad_id","@id";
        foreach "arg"{
            const "g", "$geometry[@Id = $keypad_id]";
    |     "«@value»":["«$keypad_id»", «$g/@x», «$g/@y»],
        }
    }
    | }
}

template "widget[@type='Keypad']", mode="widget_class"
    ||
    class KeypadWidget extends Widget{
         moving = undefined;
         click = undefined;
         offset = undefined;

         on_position_click(evt) {
             this.moving = true;

             // chatch window events
             window.addEventListener("touchmove", this.bound_on_drag, true);
             window.addEventListener("mousemove", this.bound_on_drag, true);

             window.addEventListener("mouseup", this.bound_on_release, true)
             window.addEventListener("touchend", this.bound_on_release, true);
             window.addEventListener("touchcancel", this.bound_on_release, 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]
         }

         on_release(evt) {
            //relase binds
            window.removeEventListener("touchmove", this.bound_on_drag, true);
            window.removeEventListener("mousemove", this.bound_on_drag, true);

            window.removeEventListener("mouseup", this.bound_on_release, true)
            window.removeEventListener("touchend", this.bound_on_release, true);
            window.removeEventListener("touchcancel", this.bound_on_release, true);

            if(this.moving)
                this.moving = false;
         }

         on_drag(evt) {
             if(this.moving)
                //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;
                }
                this.click = [clickX,clickY]

                //requeset redraw
                this.request_animate();
         }

         animate(){
            //get keyboard pos in html
            let [eltid, tmpgrp] = current_modal;
            let [xcoord,ycoord] = this.coordinates;
            let [clickX,clickY] = this.click;
            let [xdest,ydest,svgWidth,svgHeight] = page_desc[current_visible_page].bbox;

            //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)+")");
         }

         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() {
             let coercedval = (typeof this.initial) == "number" ? Number(this.editstr) : this.editstr;
             if(typeof coercedval == 'number' && isNaN(coercedval)){
                 // revert to initial so it explicitely shows input was ignored
                 this.editstr = String(this.initial);
                 this.update();
             } else { 
                 let callback_obj = this.result_callback_obj;
                 end_modal.call(this);
                 callback_obj.edit_callback(coercedval);
             }
         }

         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 = String(initial);
             this.result_callback_obj = callback_obj;
             this.Info_elt.textContent = info;
             this.shift = false;
             this.caps = false;
             this.initial = initial;

             this.update();
         }

         update() {
             if(this.editstr != this._editstr){
                 this._editstr = this.editstr;
                 this.Value_elt.textContent = this.editstr;
             }
             if(this.Shift_sub && this.shift != this._shift){
                 this._shift = this.shift;
                 (this.shift?widget_active_activable:widget_inactive_activable)(this.Shift_sub);
             }
             if(this.CapsLock_sub && 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 position");
    activable_labels("CapsLock Shift");
    |     init: function() {
    foreach "$hmi_element/*[@inkscape:label = 'Keys']/*" {
    |         id("«@id»").setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_key_click('«func:escape_quotes(@inkscape:label)»')");
    }
    foreach "str:split('Esc Enter BackSpace Sign Space NumDot CapsLock Shift')" {
    |         if(this.«.»_elt)
    |             this.«.»_elt.setAttribute("onclick", "hmi_widgets['«$hmi_element/@id»'].on_«.»_click()");
    }
    |         if(this.position_elt){
    |            this.bound_on_release = this.on_release.bind(this);
    |            this.bound_on_drag = this.on_drag.bind(this);
    |
    |            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)");
    |        }
    |     },
    |
    const "g", "$geometry[@Id = $hmi_element/@id]"; 
    |     coordinates: [«$g/@x», «$g/@y»],
}