/** * Project  : AMDA-NG * Name : ParameterUI.js * @class amdaUI.ParameterUI * @extends Ext.container.Container * @brief Parameter Module UI definition (View) * @author * @version $Id: ParameterUI.js 2257 2014-04-02 12:21:27Z elena $ */ Ext.define('amdaUI.ParameterUI', { extend: 'Ext.container.Container', alias: 'widget.panelParam', requires: [ 'amdaUI.AliasUI', 'amdaUI.CalculatorUI', 'extensions.SelectableTextArea', 'amdaUI.ParamArgumentsPlug', 'amdaModel.RequestParamObject' ], constructor: function (config) { this.init(config); this.callParent(arguments); // load object into form this.formPanel.getForm().loadRecord(this.object); var paramArgsPlug = this.getPlugin('derived-param-arguments-plugin'); if (paramArgsPlug) paramArgsPlug.onApply = this.onApplyParameterArgs; }, addParamInEditor: function (param) { var selection = this.constructionField.getSelection(); this.constructionField.setValue(selection.beforeText + param + selection.afterText); this.constructionField.focus(); if (this.constructionField.getValue()[(selection.beforeText + param).length] == ',') { this.constructionField.setCaretPosition((selection.beforeText + param).length + 1); } else { this.constructionField.setCaretPosition(this.constructionField.getValue().length); } }, onApplyParameterArgs: function (uiScope, paramRequestObject) { var fullParam = paramRequestObject.getParamFullName(); uiScope.addParamInEditor(fullParam); }, addParam: function (newParamName, isLeaf, needArgs, components) { //if (!isLeaf || needArgs || components) if (needArgs) this.editParameterArgs(newParamName, components); else this.addParamInEditor(newParamName); }, editParameterArgs: function (name, components) { var paramObj = amdaModel.RequestParamObject.getEmptyObj(); paramObj.paramid = name; if (components) { if (components['index1']) { paramObj['dim1-index'] = components['index1']; ++paramObj['type']; } if (components['index2']) { paramObj['dim2-index'] = components['index2']; ++paramObj['type']; } } var paramArgsPlug = this.getPlugin('derived-param-arguments-plugin'); if (paramArgsPlug) { var workinRequestParamObject = Ext.create('amdaModel.RequestParamObject', paramObj); paramArgsPlug.show('derived-param-arguments-plugin', workinRequestParamObject); } }, setObject: function (object) { this.object = object; // load object into form this.formPanel.getForm().loadRecord(this.object); }, /** * update this.object from form */ updateObject: function () { // get the basic form var basicForm = this.formPanel.getForm(); var updateStatus = true; var fieldsWithoutName = basicForm.getFields().items; Ext.Array.each(fieldsWithoutName, function (item, index, allItems) { if (item !== this.fieldName) { if (!item.isValid()) { // set update isn't allowed updateStatus = false; } } }, this); // if the update is allowed if (updateStatus) { /// real object update // update TimeTable object with the content of form basicForm.updateRecord(this.object); } // return the update status return updateStatus; }, updateConstruct: function (oldval, newval) { // update constructionField (Construct parameter) in window parameter var expression = this.constructionField.value; oldval = oldval.replace(/[(]/g, "\\("); oldval = oldval.replace(/[)]/g, "\\)"); var reg = new RegExp(oldval, "g"); expression = expression.replace(reg, newval); this.constructionField.setValue(expression); }, /** * Generate info for parameter desplay */ generateParamInfo: function (onSuccess) { var me = this; var paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id); var obj = { paramId: 'ws_' + this.object.get('name'), buildchain: this.object.get('buildchain'), timestep: this.object.get('timestep'), reference_param: this.object.get('reference_param'), sampling_mode: this.object.get('sampling_mode') }; loadMask.show(); AmdaAction.generateParamInfo(obj, function (result, e) { if (!result || !result.success) { loadMask.hide(); if (result.message) myDesktopApp.warningMsg(result.message); else myDesktopApp.warningMsg('Unknown error during parameter compilation'); return; } loadMask.hide(); paramModule.linkedNode.get('object').set('dim_1', parseInt(result.dimensions.dim_1)); paramModule.linkedNode.get('object').set('dim_2', parseInt(result.dimensions.dim_2)); if (onSuccess) onSuccess(); /* paramModule.linkedNode.update({scope : me, failure: function(record, operation) { }, callback: function() { } }); */ }); }, /** * save method called by Save button */ saveProcess: function (toRename) { if (this.object.dirty) { // Parameter Module var paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id); // if the name has been modified this is a creation if (this.object.isModified('name')) { // if object already has an id : it's a 'rename' of an existing TimeTable if (this.object.get('id')) { // the context Node is the parent node of current edited one var contextNode = paramModule.linkedNode.parentNode; // link a new node to the TimeTableModule paramModule.createLinkedNode(); // set the contextNode paramModule.linkedNode.set('contextNode', contextNode); // create a new object linked paramModule.createObject(this.object.getJsonValues()); var paramobj = paramModule.linkedNode.get('object'); //synchronize objects this.object = paramobj; if (toRename) paramModule.linkedNode.toRename = true; } this.generateParamInfo(function () { paramModule.linkedNode.set('isParameter', true); paramModule.linkedNode.create({ scope: this, callback: function () { } }); }); } else { paramModule.linkedNode.set('contextNode', paramModule.contextNode); this.generateParamInfo(function () { paramModule.linkedNode.update({ scope: this, callback: function () { } }); }); } } }, /** * overwrite metod called by Save button */ overwriteProcess: function (btn) { if (btn == 'cancel') return; this.fieldName.clearInvalid(); this.saveProcess(true); }, /** * Check if brackets are balanced */ isBalanced: function (str) { str = ("" + str).replace(/[^()\[\]{}]/g, ""); var bracket = { "]": "[", "}": "{", ")": "(" }, openBrackets = [], isClean = true, i = 0, len = str.length; for (; isClean && i < len; i++) { if (bracket[str[i]]) { isClean = (openBrackets.pop() === bracket[str[i]]); } else { openBrackets.push(str[i]); } } if (!(isClean && !openBrackets.length)) return 'Brackets are not balanced'; return true; }, /** * Check if changes were made before closing window * @return true if changes */ fclose: function () { var isDirty = this.formPanel.getForm().isDirty(); return isDirty; }, init: function (config) { this.fieldName = new Ext.form.field.Text({ labelAlign: 'top', itemId: 'formParamName', labelPad: 0, fieldLabel: 'Parameter Name', name: 'name', allowBlank: false, //blankText : 'Name is required', emptyText: 'Please only low case!', width: 150, validateOnChange: false, validateOnBlur: false, enableKeyEvents: true, validFlag: false, validator: function () { return this.validFlag; }, stripCharsRe: /(^\s+|\s+$)/g, listeners: { keyUp: function (field, e, opt) { this.setValue(this.getValue().toLowerCase()); } } }); this.constructionField = new extensions.SelectableTextArea({ labelAlign: 'top', labelPad: 0, itemId: 'formParamConstructParameter', fieldLabel: ' Construct Parameter', allowBlank: false, blankText: 'Construct Parameter is required', name: 'buildchain', flex: 0.6, validateOnChange: false, validateOnBlur: false, validator: this.isBalanced, listeners: { render: function (o, op) { var me = this; var meEl = me.bodyEl; var dropTarget = Ext.create('Ext.dd.DropTarget', meEl, { ddGroup: 'explorerTree', notifyEnter: function (ddSource, e, data) { }, notifyOver: function (ddSource, e, data) { if (data.records[0].get('nodeType') == 'localParam' && data.records[0].get('notyet')) { this.valid = false; return this.dropNotAllowed; } if (((data.records[0].get('nodeType') == 'localParam') || (data.records[0].get('nodeType') == 'remoteParam') || (data.records[0].get('nodeType') == 'remoteSimuParam') || (data.records[0].get('nodeType') == 'derivedParam') || (data.records[0].get('nodeType') == 'specialParam') || (data.records[0].get('nodeType') == 'myDataParam') || (data.records[0].get('nodeType') == 'timeTable') || (data.records[0].get('nodeType') == 'catalog') || (data.records[0].get('nodeType') == 'sharedtimeTable') || (data.records[0].get('nodeType') == 'sharedcatalog') || (data.records[0].get('nodeType') == 'alias')) && (data.records[0].isLeaf() || data.records[0].get('isParameter')) && !(data.records[0].data.disable)) { this.valid = true; return this.dropAllowed; } this.valid = false; return this.dropNotAllowed; }, notifyDrop: function (ddSource, e, data) { if (!this.valid) return false; var nameToSent; var components = null; switch (data.records[0].get('nodeType')) { case 'localParam': case 'remoteParam': case 'remoteSimuParam': nameToSent = data.records[0].get('id'); if (data.records[0].get('alias') != "") var nameToSent = "#" + data.records[0].get('alias'); var component_info = data.records[0].get('component_info'); if (component_info && component_info.parentId) { if (component_info.index1 && component_info.index2) { nameToSent = component_info.parentId; components = []; if (component_info.index1) components['index1'] = component_info.index1; if (component_info.index2) components['index2'] = component_info.index2; } if (data.records[0].get('needsArgs')) { nameToSent = component_info.parentId; if (component_info.index1) { components = []; components['index1'] = component_info.index1; } } } break; case 'alias': nameToSent = "#" + data.records[0].get('text'); break; case 'derivedParam': nameToSent = "ws_" + data.records[0].get('text'); break; case 'specialParam': nameToSent = data.records[0].get('id'); break; case 'timeTable': nameToSent = "tt_"+data.records[0].get('text'); break; case 'catalog': nameToSent = "cat_"+data.records[0].get('text'); break; case 'sharedtimeTable': nameToSent = "sharedtimeTable"+data.records[0].get('text'); break; case 'sharedcatalog': nameToSent = "sharedcatalog_"+data.records[0].get('text'); break; case 'myDataParam': var name = data.records[0].get('text'); nameToSent = "wsd_" + name; break; default: return false; } var paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id); if (paramModule) { if (data.records[0].get('predefinedArgs')) { paramModule.parseTemplatedParam(nameToSent, function (param_info) { paramModule.addParam(param_info.paramid, data.records[0].get('leaf'), true, components, param_info.template_args, null); }); } else { paramModule.addParam(nameToSent, data.records[0].get('leaf'), data.records[0].get('needsArgs'), components,null,null); } } return true; } }); } } //TODO: ?validator on formula structure? // listener : { // valid : function(field) { // // } // } }); var samplingmode_store = new Ext.data.ArrayStore({ fields: ['id', 'name'], data: [ ['timestep', 'Time Step'], ['refparam', 'Ref. Parameter'] ] }); this.timeStepField = new Ext.form.NumberField({ fieldLabel: ' Time Step (sec)', labelAlign: 'top', labelPad: 0, blankText: 'Time Step is required', name: 'timestep', minValue: 0.001, decimalPrecision: 10, hideTrigger: true, width: 150, validateOnBlur: false, allowBlank: false, isValid: function () { var me = this, disabled = me.disabled, validate = me.forceValidation || !disabled; if (!me.isVisible()) { return true; } return validate ? me.validateValue(me.processRawValue(me.getRawValue())) : disabled; } }); this.refParamField = new Ext.form.TextField({ fieldLabel: ' Reference Param.', labelAlign: 'top', labelPad: 0, name: 'reference_param', width: 150, hidden: true, allowBlank: false, listeners: { afterrender: function (field, eOpts) { var paramTarget = new Ext.dd.DropTarget(field.el.dom, { ddGroup: 'explorerTree', notifyEnter: function (ddSource, e, data) { }, notifyDrop: function (ddSource, e, data) { var selectedRecord = ddSource.dragData.records[0]; switch (selectedRecord.$className) { case 'amdaModel.LocalParamNode': case 'amdaModel.RemoteParamNode': case 'amdaModel.RemoteSimuParamNode': if (!selectedRecord.get('isParameter') || selectedRecord.get('disable')) return false; if (selectedRecord.get('alias') != "") field.setValue("#" + selectedRecord.get('alias')); else field.setValue(selectedRecord.get('id')); return true; case 'amdaModel.AliasNode': if (!selectedRecord.isLeaf()) return false; field.setValue("#" + selectedRecord.get('text')); return true; case 'amdaModel.DerivedParamNode': if (!selectedRecord.isLeaf()) return false; field.setValue("ws_" + selectedRecord.get('text')); return true; case 'amdaModel.MyDataParamNode': if (!selectedRecord.isLeaf()) return false; field.setValue("wsd_" + selectedRecord.get('text')); return true; default: return false; } return true; } } ); }, scope: this }, isValid: function () { var me = this, disabled = me.disabled, validate = me.forceValidation || !disabled; if (!me.isVisible()) { return true; } return validate ? me.validateValue(me.processRawValue(me.getRawValue())) : disabled; } }); this.samplingDefContainer = new Ext.container.Container({ border: false, items: [ this.timeStepField, this.refParamField ], width: 150 }); this.formPanel = new Ext.form.Panel({ id: 'vbox-paramForm', bodyStyle: { background: '#dfe8f6' }, border: false, buttonAlign: 'left', region: 'center', trackResetOnLoad: true, //reset to the last loaded record layout: { type: 'vbox', defaultMargins: { top: 5, left: 5, bottom: 10, right: 10 }, align: 'stretch' }, defaults: { border: false }, items: [ { flex: 1, xtype: 'container', border: false, layout: { type: 'table', columns: 3 }, defaultType: 'textfield', defaults: { labelAlign: 'top', labelPad: 0 }, items: [ this.fieldName, { xtype: 'component', width: 20 }, { fieldLabel: 'Last modification', xtype: 'displayfield', name: 'last_update', width: 150, renderer: function (value, field) { var tpl = new Ext.XTemplate('

{date}'); var mod_date = 'Not saved'; if (value > 0) mod_date = Ext.Date.format(new Date(value * 1000), "Y-m-d\\TH:i:s"); return tpl.apply({ date: mod_date }); }, }, { xtype: 'combo', fieldLabel: 'Sampling mode', name: 'sampling_mode', queryMode: 'local', editable: false, valueField: 'id', displayField: 'name', store: samplingmode_store, value: samplingmode_store.first(), listeners: { change: function (field, value) { this.timeStepField.setVisible(value != 'refparam'); this.refParamField.setVisible(value == 'refparam'); }, scope: this } }, { xtype: 'component', width: 20 }, this.samplingDefContainer, { itemId: 'formParamUnit', fieldLabel: 'Units', name: 'units', width: 150 }, { xtype: 'component', width: 20 }, { itemId: 'formParamYTitle', fieldLabel: 'Y Title for Plot', name: 'ytitle', width: 150 }, { itemId: 'formParamDescription', name: 'description', xtype: 'textarea', fieldLabel: 'Description', width: 320, height: 75, colspan: 3 }] }, this.constructionField ], fbar: [ { text: 'Save', scope: this, handler: function () { if (this.updateObject()) { var paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id); if (!paramModule) return; var me = this; paramModule.linkedNode.isValidName(this.fieldName.getValue(), function (res) { if (!res) { me.fieldName.validFlag = 'Error during object validation'; myDesktopApp.errorMsg(me.fieldName.validFlag); me.fieldName.validate(); return; } if (!res.valid) { if (res.error) { if (res.error.search('subtree') != -1) { Ext.MessageBox.show({ title: 'Warning', msg: res.error + '
Do you want to overwrite it?', width: 300, buttons: Ext.MessageBox.OKCANCEL, fn: me.overwriteProcess, icon: Ext.MessageBox.WARNING, scope: me }); me.fieldName.validFlag = true; } else me.fieldName.validFlag = res.error; } else { me.fieldName.validFlag = 'Invalid object name'; myDesktopApp.errorMsg(me.fieldName.validFlag); } me.fieldName.validate(); return; } me.fieldName.validFlag = true; me.fieldName.validate(); me.saveProcess(false); }); } } }, { text: 'Reset', scope: this, handler: function () { var paramModule = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.param.id); paramModule.createLinkedNode(); paramModule.createObject(); this.setObject(paramModule.getLinkedNode().get('object')); /* reset with keeping old object this.formPanel.getForm().reset(); */ } } ] }); var myConf = { layout: 'border', border: false, defaults: { layout: 'fit', border: false }, items: [ this.formPanel, { xtype: 'panel', region: 'south', title: 'Information', collapsible: true, collapseMode: 'header', height: 100, autoHide: false, iconCls: 'icon-information', bodyStyle: 'padding:5px', loader: { autoLoad: true, url: helpDir + 'myParameterHOWTO' } }], plugins: [ { ptype: 'calculator', myBtns: [], context: 'Parameter' }, { ptype: 'paramArgumentsPlugin', pluginId: 'derived-param-arguments-plugin' } ], listeners: { click: { element: 'el', fn: function (e, t) { var me = t, text = me.getAttribute('amda_clicktip'); if (text) { e.preventDefault(); AmdaAction.getInfo({ name: text }, function (res, e) { if (res.success) myDesktopApp.infoMsg(res.result); }); } } } } }; Ext.apply(this, Ext.apply(arguments, myConf)); } });