IntervalSelection.js 9.22 KB
// Define a constant for the layout style of the form
const LAYOUT_STYLE = {
    type: 'vbox', // vertical box layout
    pack: 'start', // controls the vertical alignment of child items
    align: 'stretch' // each child item is stretched to fill the width of the container
};

// Width of button
const width = 100;

// Define the parent class for all classes to use time interval selection.
Ext.define('amdaPlotComp.intervalSelection.IntervalSelection', {
    extend: 'Ext.window.Window', // This class extends from Ext.window.Window
    // Window configurations
    x: 0, y: 0, // The initial position of the window
    title: 'Interval Selection', // The title of the window
    constrain: true, // Constrains the window to within the boundaries of its containing element
    collapsible: true, // Allows the window to be collapsed
    resizable: false, // Prevents the window from being resizable
    ghost: false, // Disables "ghosting" (semi-transparent representation of the window body) when moving or resizing

    form: null, // a panel which contains all components
    hostCmp: null, // The host component from which this class is instantiated.
    interactiveId: '',
    panelId: -1,

    // Attributes of this class
    config: {
        field1Type: 'datefield', // The xtype of field1. By default is datefield because we are working with time series.
        field1Label: 'Start Time', // The label of field1.
        field1Format: 'Y/m/d H:i:s.u',
        field2Type: 'datefield', // The xtype of field2. By default is datefield.
        field2Label: 'Stop Time', // The label of field2.
        field2Format: 'Y/m/d H:i:s.u',
        buttonApply: 'Apply'
    },

    // Define the itemIds as constants
    // These will be used to reference the fields later in the code
    FIELD1_ITEM_ID: 'field1',
    FIELD2_ITEM_ID: 'field2',
    buttonUseTime: 'button-use-time',

    initComponent: function () {
        const self = this; // Reference to this instance for use in event handlers
        this.form = new Ext.form.FormPanel({ // Create a new FormPanel instance and assign it to form
            frame: true, // Display a frame around the panel
            width: 255, // Set the width of the panel
            layout: LAYOUT_STYLE, // Set the layout style of the panel
            fieldDefaults: {
                labelWidth: 60 // Set default label width for fields in this panel
            },
            items: [{
                xtype: 'fieldset', // Create a new FieldSet to group related fields together
                title: 'Interval Selection',
                name: 'interval-selection-fieldset',
                collapsible: false,
                layout: LAYOUT_STYLE,
                items: [{
                    xtype: this.field1Type,
                    fieldLabel: this.field1Label,
                    itemId: this.FIELD1_ITEM_ID,
                    format: this.field1Format,
                    listeners: {
                        change: function (field, newValue) {
                            if (newValue === null || newValue === undefined || newValue === '') return;
                            var field2 = self._getField2();
                            // Check if field2 is not empty
                            const value2 = field2.getValue();
                            if (value2 !== null && value2 !== undefined && value2 !== '') {
                                if (newValue > value2) {
                                    // Update both field1 and field2 to the new values
                                    field2.suspendEvents();
                                    field2.setValue(newValue);
                                    field.setValue(value2);
                                    field2.resumeEvents();
                                }
                            }
                        }
                    }
                },
                {
                    xtype: this.field2Type,
                    fieldLabel: this.field2Label,
                    itemId: this.FIELD2_ITEM_ID,
                    format: this.field2Format,
                    listeners: {
                        change: function (field, newValue) {
                            if (newValue === null || newValue === undefined || newValue === '') return;
                            var field1 = self._getField1();
                            // Check if field1 is not empty
                            const value1 = field1.getValue();
                            if (value1 !== null && value1 !== undefined && value1 !== '') {
                                if (newValue < value1) {
                                    // Update both field1 and field2 to the new values
                                    field1.suspendEvents();
                                    field1.setValue(newValue);
                                    field.setValue(value1);
                                    field1.resumeEvents();
                                }
                            }
                        }
                    }
                }, {
                    xtype: 'button',
                    text: 'Reset',
                    width: width,
                    handler: function () {
                        self.reset();
                    }
                },
                {
                    xtype: 'button',
                    text: 'Use in Time Selection',
                    itemId: this.buttonUseTime,
                    handler: function () {
                        self._setTimeInterval();
                    }
                }]
            }],
            fbar: [
                {
                    xtype: 'button',
                    width: width,
                    text: this.buttonApply,
                    handler: function () {
                        self._apply();
                    }
                }
            ]
        })

        Ext.apply(this, {
            items: this.form
        });

        this.setTitle(this.title + " - Panel Id : " + this.panelId);
        this.callParent(arguments);
    },

    /**
     * Resets the time interval selection in the host component.
     * This function calls the resetZoom method on the panelImage of the host component,
     * effectively resetting any zoom applied to the image.
     */
    _resetHostCmpSelection: function () {
        this.hostCmp.panelImage.resetZoom();
    },

    /**
 * Abstract method that must be implemented by subclasses.
 * Throws an error if not overridden.
 */
    _apply: function () {
        throw new Error('_apply() method must be implemented by subclass');
    },

    /**
     * Checks if the values of field1 and field2 are valid and if the form is valid.
     * Returns true if any of these conditions are not met.
     */
    _notValidValues: function () {
        return !this.getField1Value() || !this.getField2Value() || !this.form.getForm().isValid();
    },

    /**
     * Retrieves the component associated with FIELD1_ITEM_ID in the form.
     * Returns the component if found, null otherwise.
     */
    _getField1: function () {
        return this.form.down('#' + this.FIELD1_ITEM_ID);
    },

    /**
     * Retrieves the component associated with FIELD2_ITEM_ID in the form.
     * Returns the component if found, null otherwise.
     */
    _getField2: function () {
        return this.form.down('#' + this.FIELD2_ITEM_ID);
    },

    /**
 * Sets the time interval of the plot based on the values of the fields.
 * This method is triggered when the buttonUseTime is clicked.
 * It creates a new time object with start, stop, and interactiveId properties,
 * and then calls the setTimeInterval method on the plot module with this object.
 */
    _setTimeInterval: function () {
        const timeObj = new Object();
        timeObj.start = this.getField1Value();
        timeObj.stop = this.getField2Value();
        timeObj.interactiveId = this.interactiveId;
        const plotModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.plot.id);
        plotModule.setTimeInterval(timeObj);
    },

    /**
     * Hides the buttonUseTime when it's not needed.
     * For example, when we call Zoom on y-left axis we should not see this button.
     * It finds the button by its ID and then calls the hide method on it.
     */
    _removeUseTimeButton: function () {
        const buttonToHide = this.form.down('#' + this.buttonUseTime);
        buttonToHide.hide();
    },

    /**
     * Retrieves the value of field1 from the form.
     */
    getField1Value: function () {
        return this._getField1().getValue();
    },

    /**
     * Retrieves the value of field2 from the form.
     */
    getField2Value: function () {
        return this._getField2().getValue();
    },

    /**
     * Sets a new value for field1 in the form.
     */
    setField1Value: function (value) {
        this._getField1().setValue(value);
    },

    /**
     * Sets a new value for field2 in the form.
     */
    setField2Value: function (value) {
        this._getField2().setValue(value);
    },

    /**
     * Resets the values of fields and host component selection.
     * It calls the reset method on field1 and field2, and then calls _resetHostCmpSelection.
     */
    reset: function () {
        this._getField1().reset();
        this._getField2().reset();
        this._resetHostCmpSelection();
    }

});