svghmi/widget_jump.ysl2
author Edouard Tisserant <edouard.tisserant@gmail.com>
Sat, 05 Mar 2022 11:14:00 +0100
branchwxPython4
changeset 3437 ce366d67a5b7
parent 3242 f037e901a17c
child 3512 fce3d407bb46
permissions -rw-r--r--
Tests: Enhance robustness of stdout driven waiting state in Sikuli based tests.

Some tests were randomly passing, because from time to time waiting for idle was skiped. It was combination of multiple problems :
- buffering on stdout (now use readline + flush for each write to log)
- it is sometime required to wait for activity before waiting for timeout added "WaitForChangeAndIdle" to "stdoutIdleObserver"
// 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;
};

||