/** * Project  : AMDA-NG4 * Name : CalculatorUI.js * @class amdaDesktop.ExplorerModule * @extends Ext.util.Observable * @brief Calculator Plugin used in SearchUI and ParameterUI * @author elena * @version $Id: CalculatorUI.js 1399 2013-03-27 12:44:50Z elena $ * ****************************************************************************** * FT Id : Date : Name - Description ****************************************************************************** * * : :06/05/2011: CDA - Extjs 4.0.0 Migration * : :16/06/2011: elena - resolve rendering problem (sencha support) * : :26/10/2011: BRE -autoload constants and functions from xml files */ /** * @plugin calculator * @extends Ext.util.Observable * @ptype calculator */ var CalculatorData = ['1','2','3','4','5','6','7','8','9','0','(',')','[',']','+','-','*','/','^', '.','>','<', '&', '|']; Ext.define('amdaUI.CalculatorUI', { extend: 'Ext.util.Observable', requires : [ 'amdaModel.Constant', 'amdaModel.Function' ], alias: 'plugin.calculator', statics : { constantStore : null, functionStore : null }, win: null, constructor: function(config) { Ext.apply(this, config); this.callParent(arguments); }, init: function(cmp) { this.hostCmp = cmp; this.hostCmp.on({ scope: this, added: function(){ this.hostCmp.ownerCt.on({ render: this.onRender, show: this.onShow, hide : this.onHide, scope: this }); } }); }, onRender: function() { this.win = new Ext.Window({ width: 350, height: 170, x: 380, y: 0, baseCls:'x-panel', title: 'Tools For ' + this.context + ' Construction', layout: 'fit', closable: false, collapsible: true, constrain: true, floating: true, ghost: false, renderTo: this.hostCmp.id, items: this.getFormConfig(), listeners : { boxready: function (w) { if (w.y + w.height > myDesktopApp.desktop.el.getHeight()) w.el.setY((myDesktopApp.desktop.el.getHeight()-w.height > 0) ? myDesktopApp.desktop.el.getHeight()-w.height : 0); } }, getConstrainVector: function(constrainTo){ var me = this; if (me.constrain || me.constrainHeader) { constrainTo = constrainTo || (me.floatParent && me.floatParent.getTargetEl()) || me.container || me.el.getScopeParent(); return (me.constrainHeader ? me.header.el : me.el).getConstrainVector(constrainTo); } } }); //load constants store if (!amdaUI.CalculatorUI.constantStore) { amdaUI.CalculatorUI.constantStore = Ext.create('Ext.data.Store',{model: 'amdaModel.Constant'}); amdaUI.CalculatorUI.constantStore.load({ scope : this, callback: function(records, operation, success) { this.createConstantBtns(); } }); } else this.createConstantBtns(); //load functions store if (!amdaUI.CalculatorUI.functionStore) { amdaUI.CalculatorUI.functionStore = Ext.create('Ext.data.Store',{model: 'amdaModel.Function'}); amdaUI.CalculatorUI.functionStore.load({ scope : this, callback: function(records, operation, success) { this.createAllFunctionBtns(); } }); } else this.createAllFunctionBtns(); }, onShow: function() { this.win.show(); var parentWin = this.hostCmp.findParentByType('window'); if (parentWin.getId() === myDesktopApp.dynamicModules.param.id) { this.win.setPosition(335,10); } else { var posX = parentWin.getWidth() - this.win.getWidth() - 30; var posY = parentWin.getHeight() - this.win.getHeight() - 110 - 30/*20*/; this.win.setPosition(posX,posY);//(420,290); } }, onHide : function() { this.win.hide(); }, getFormConfig: function(){ return { xtype: 'tabpanel', border: false, frame: true, plain: true, enableTabScroll: true, defaults: { frame: true, border: false, plain: true, autoScroll:true}, activeTab: 0, items: [ { title: 'Calculator',layout: 'column', defaults: { xtype: 'button', columnWidth: .11}, items: this.getItems('Calculator') } , { title: 'Constants', layout: 'column', defaults: { xtype: 'button', columnWidth: .20}, id : 'calc_tab_const_id' }, { title: 'Functions', xtype:'tabpanel', //iconCls: 'tabs', enableTabScroll: true, tabPosition: 'bottom', defaults: { frame: true, border: false, plain: true, layout: 'column', autoScroll:true}, activeTab: 0, id : 'calc_tab_func_id' }] }; }, /** * Prompt any argument to user before processing Formula * @param sel selected text * @param currentBtn calculator button pressed * @param params array of parameters */ preProcessFormula: function(sel,currentBtn, params) { if (currentBtn.initialConfig.args!=0 && currentBtn.initialConfig.prompt!=""){ // Prompt for user precision and process the result using a callback Ext.Msg.prompt('Argument',currentBtn.initialConfig.prompt, function(bt2, text){ if (bt2 === 'ok'){ var afterParamsText = "," + text + ")"; //TODO: more than one args and prompt this.processFormula(sel,currentBtn, params, afterParamsText); } },this); } else { this.processFormula(sel,currentBtn, params, ")"); }// endif prompt }, processFormula : function(sel,currentBtn, params, afterParamsText){ // calculation of the required number of parameters var nbParams = currentBtn.initialConfig.params; var fnText = currentBtn.text.split('('); var newConstruction = sel.beforeText + fnText[0]+"("; // if there at least one parameter selected if (params.length){ for (var i=0;i0) { newConstruction += ","; } newConstruction += params[i]; } } // we keep position var afterParameterPos = newConstruction.length; newConstruction += afterParamsText; var caretPos = newConstruction.length; newConstruction += sel.afterText; this.hostCmp.constructionField.setValue(newConstruction); // If we haven't the right number of selected parameters if (params.length < nbParams){ var stringParamRequired = currentBtn.initialConfig.params+" parameter(s)"; Ext.Msg.alert('Caution', 'you\'ll have to add '+ stringParamRequired +' to apply this function', function(){ // set Caret Position at placement of required parameter in function this.hostCmp.constructionField.setCaretPosition(afterParameterPos); },this ); } else { // set Caret Position after inserted Text this.hostCmp.constructionField.setCaretPosition(caretPos); } }, /** * This method construct an array of arguments into selected text * @param selectedText the selection to parse * @param parseIndex the index to start parsing * @return the arguments array */ parseArgsInFormula : function (selectedText, parseIndex) { if (!selectedText || selectedText==""){ return []; } else { var params = []; var startIndex = parseIndex; var curIndex = parseIndex; var openBrace = 0; var sep = 0; var closeBrace = 0; // while there is a separator while(sep!=-1){ openBrace = selectedText.indexOf("(",curIndex); sep = selectedText.indexOf(",",curIndex); closeBrace = selectedText.indexOf(")",curIndex); // if there's an open bracket and no close bracket or inversely if (openBrace!=-1 && closeBrace==-1 || openBrace==-1 && closeBrace!=-1) { // invalid selection return -1; } // if there's a separator and opening brackets into selection if (sep!=-1 && openBrace!=-1){ // if brace is before separator if (openBrace'+c.get('value') : c.get('info')+'
'+c.get('value')+' '+c.get('units'), scope: this, handler: function(b,e){ // keep selection into construction field var selection = this.hostCmp.constructionField.getSelection(); // the new value of construction field var newConstruction = ""; // replacement of selection into construction field by text of clicked button newConstruction = selection.beforeText + '@'+b.text; var caretPos = newConstruction.length; newConstruction += selection.afterText; this.hostCmp.constructionField.setValue(newConstruction); // set Caret Position after inserted Text this.hostCmp.constructionField.setCaretPosition(caretPos); } }); },this); }, createAllFunctionBtns : function() { this.createFunctionBtns('IdlFunctions','Simple Maths'); this.createFunctionBtns('TimeFunctions','Statistics'); this.createFunctionBtns('FunctionsSliding','Statistics/Sliding'); this.createFunctionBtns('AmdaFunctions','Space Physics'); }, createFunctionBtns : function(item, tabTitle) { var funcTab = this.win.query('#calc_tab_func_id'); if (funcTab.length < 1) return; switch (item) { case 'IdlFunctions' : amdaUI.CalculatorUI.functionStore.filter('kind','idl'); break; case 'AmdaFunctions' : amdaUI.CalculatorUI.functionStore.filter('kind','amda'); break; case 'TimeFunctions' : amdaUI.CalculatorUI.functionStore.filter('kind','time'); break; case 'FunctionsSliding' : amdaUI.CalculatorUI.functionStore.filter('kind','sliding'); break; } var crtTab = funcTab[0].add( { title : tabTitle, defaults: { xtype: 'button', columnWidth: .20} }); amdaUI.CalculatorUI.functionStore.each( function(f){ crtTab.add( { text: f.get('name'), args: f.get('args'), params: f.get('params'),//"+", prompt: f.get('prompt'), tooltip: f.get('info_brief'), // disabled: f.get('argv') == 'vector', scope: this, handler: function(b,e){ var selection = this.hostCmp.constructionField.getSelection(); var selectedText = selection&&selection.text!="" ? Ext.util.Format.trim(selection.text) : null; if (selectedText && selectedText!==""){ selectedText.replace("[","("); selectedText.replace("{","("); selectedText.replace("}",")"); selectedText.replace("]",")"); } // Formula Parsing for arguments var params = this.parseArgsInFormula(selectedText,0); // var params = selectedText ? selectedText.split(',') : []; if (params === -1) { Ext.Msg.alert("Invalid Selection", "Action aborted"); } else { // calculation of the required number of parameters var nbParams = b.initialConfig.params; if (params.length>nbParams) { // Show a dialog using config options: Ext.Msg.show({ title:'Caution', msg: 'you have selected more than '+nbParams+' parameter(s) to apply this function
Only the first will be kept, others will be deleted', buttons: Ext.Msg.OKCANCEL, // animEl: 'elId', icon: Ext.MessageBox.WARNING, fn: function(bt1){ if (bt1 === 'ok'){ this.preProcessFormula(selection,b, params); } }, scope:this }); } else { this.preProcessFormula(selection,b, params); } } } }); }, this ); //clear filter amdaUI.CalculatorUI.functionStore.clearFilter(); }, getItems: function(item) { switch (item) { case 'Calculator': return this.getCalculatorBtn(); default: break; } return []; } });