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