svghmi/widget_keypad.ysl2
author Edouard Tisserant
Wed, 13 Jan 2021 10:28:09 +0100
branchsvghmi
changeset 3109 6c39d718e8cb
parent 3102 abb487b56911
child 3118 e704b0487515
permissions -rw-r--r--
Removed harmful assert in ProcessLogger.

ProcessLogger was having an assert in constructor when missing logger, leading to systematic exception when testing options accepted by compiler. This exception was silenced in ProjectController, and then MatIEC was always called without options.
// 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»],
}