svghmi/widget_jump.ysl2
author Edouard Tisserant
Wed, 01 Dec 2021 09:54:02 +0100
branchRuntimeLists
changeset 3394 9ea29ac18837
parent 3242 f037e901a17c
child 3512 fce3d407bb46
permissions -rw-r--r--
RUNTIME: Variable trace now uses limited list and buffer instead of flags in instance tree that was requiring systematical instance tree traversal, and worst size buffer. Forcing and retain still use tree traversal.
// widget_jump.ysl2

widget_desc("Jump") {
    longdesc
    ||
    Jump widget brings focus to a different page. Mandatory single argument
    gives name of the page.

    Optional single path is used as new reference when jumping to a relative
    page, it must point to a HMI_NODE.

    "active"+"inactive" labeled elements can be provided and reflect current
    page being shown.

    "disabled" labeled element, if provided, is shown instead of "active" or
    "inactive" widget when pointed HMI_NODE is null.
    ||

    shortdesc > Jump to given page

    arg name="page" accepts="string" > name of page to jump to

    path name="reference" count="optional" accepts="HMI_NODE" > reference for relative jump
}

widget_class("Jump") {
||
        activable = false;
        active = false;
        disabled = false;
        frequency = 2;

        update_activity() {
            if(this.active) {
                 /* show active */ 
                 this.active_elt.style.display = "";
                 /* hide inactive */ 
                 this.inactive_elt.style.display = "none";
            } else {
                 /* show inactive */ 
                 this.inactive_elt.style.display = "";
                 /* hide active */ 
                 this.active_elt.style.display = "none";
            }
        }

        update_disability() {
            if(this.disabled) {
                /* show disabled */ 
                this.disabled_elt.style.display = "";
                /* hide inactive */ 
                this.inactive_elt.style.display = "none";
                /* hide active */ 
                this.active_elt.style.display = "none";
            } else {
                /* hide disabled */ 
                this.disabled_elt.style.display = "none";
                this.update_activity();
            }
        }

        make_on_click() {
            let that = this;
            const name = this.args[0];
            return function(evt){
                /* TODO: in order to allow jumps to page selected through for exemple a dropdown,
                   support path pointing to local variable whom value 
                   would be an HMI_TREE index and then jump to a relative page not hard-coded in advance */

                if(!that.disabled) {
                    const index = that.indexes.length > 0 ? that.indexes[0] + that.offset : undefined;
                    switch_page(name, index);
                }
            }
        }

        notify_page_change(page_name, index) {
            if(this.activable) {
                const ref_index = this.indexes.length > 0 ? this.indexes[0] + this.offset : undefined;
                const ref_name = this.args[0];
                this.active = ((ref_name == undefined || ref_name == page_name) && index == ref_index);
                this.update_state();
            }
        }

        dispatch(value) {
            this.disabled = !Number(value);
            this.update_state();
        }
||
}

widget_defs("Jump") {
    // TODO: ensure both active and inactive are provided
    const "activity" optional_labels("active inactive");
    const "have_activity","string-length($activity)>0";
    value "$activity";

    const "disability" optional_labels("disabled");
    const "have_disability","$have_activity and string-length($disability)>0";
    value "$disability";

    |     init: function() {
    |         this.element.onclick = this.make_on_click();
    if "$have_activity" {
    |         this.activable = true;
    }
    if "not($have_disability)" {
    |         this.unsubscribable = true;
    }
    >         this.update_state = 
    choose {
        when "$have_disability" {
            > this.update_disability
        }
        when "$have_activity" {
            > this.update_activity
        }
        otherwise > null
    }
    > ;\n
    |     },

}

widget_page("Jump"){
    param "page_desc";
    /* check that given path is compatible with page's reference path */
    if "path" {
        /* TODO: suport local variable containing an HMI_TREE index to jump to a relative page */
        /* when no page name provided, check for same page */
        const "target_page_name" choose {
            when "arg" value "arg[1]/@value";
            otherwise value "$page_desc/arg[1]/@value";
        }
        const "target_page_path" choose {
            when "arg" value "$hmi_pages_descs[arg[1]/@value = $target_page_name]/path[1]/@value";
            otherwise value "$page_desc/path[1]/@value";
        }

        if "not(func:same_class_paths($target_page_path, path[1]/@value))"
            error > Jump id="«@id»" to page "«$target_page_name»" with incompatible path "«path[1]/@value» (must be same class as "«$target_page_path»")
    }
}

emit "declarations:jump"
||
var jumps_need_update = false;
var jump_history = [[default_page, undefined]];

function update_jumps() {
    page_desc[current_visible_page].jumps.map(w=>w.notify_page_change(current_visible_page,current_page_index));
    jumps_need_update = false;
};

||