/** * Project  : AMDA-NG * Name : PlotTree.js * @class amdaPlotComp.PlotTree * @extends Ext.tree.Panel * @brief Tree to define all elements of a plot * @author Benjamin Renard * @version $Id: PlotTree.js benjamin $ */ Ext.define('amdaPlotComp.PlotTree', { extend: 'Ext.tree.Panel', requires: [ 'amdaPlotObj.PlotTreeNode' ], // isSimplifiedView: false, //Link to the Plot Element Panel plotElementPanel: null, //Tab object tabObject: null, //Panels list node panelsNode: null, constructor: function(config) { this.init(config); this.callParent(arguments); }, setSimplifiedMode: function(isSimplifiedView) { this.isSimplifiedView = isSimplifiedView; this.buildTree(this.tabObject); }, buildTree: function(tabObject) { if (this.store.getRootNode().hasChildNodes()) this.store.getRootNode().removeAll(); this.tabObject = tabObject; if (!this.isSimplifiedView) { //Page Node var pageNode = this.store.getRootNode().appendChild(new amdaPlotObj.PlotPageTreeNode({object : tabObject})); //Layout node pageNode.appendChild(new amdaPlotObj.PlotLayoutTreeNode({object : tabObject})); //Panels node this.panelsNode = pageNode.appendChild(new amdaPlotObj.PlotPanelsTreeNode()); } else this.panelsNode = this.store.getRootNode(); this.buildPanelsNode(); }, buildPanelsNode: function() { if (this.panelsNode.hasChildNodes()) this.panelsNode.removeAll(); var me = this; this.tabObject.panels().each(function (panelObject) { me.addPanelNode(panelObject); }); }, buildPanelAxesNode: function(panelObject) { var axesNode = null; this.panelsNode.eachChild(function (panelNode) { //Retrieve corresponding panel node if (panelNode.object == panelObject) { //Retrieve axes node axesNode = panelNode.findChild('type', 'axes'); if (!axesNode) //create axes node axesNode = panelNode.appendChild(new amdaPlotObj.PlotAxesTreeNode({object : panelObject})); return; } }); if (axesNode == null) return; //Remove old axis nodes axesNode.removeAll(); //Add axis nodes panelObject.axes().each(function (axisObject) { switch (axisObject.get('axis-type')) { case 'time' : axesNode.appendChild(new amdaPlotObj.PlotTimeAxisTreeNode({object : axisObject})); break; case 'epoch' : axesNode.appendChild(new amdaPlotObj.PlotEpochAxisTreeNode({object : axisObject})); break; case 'x' : axesNode.appendChild(new amdaPlotObj.PlotXAxisTreeNode({object : axisObject})); break; case 'y-left' : axesNode.appendChild(new amdaPlotObj.PlotYLeftAxisTreeNode({object : axisObject})); break; case 'y-right' : axesNode.appendChild(new amdaPlotObj.PlotYRightAxisTreeNode({object : axisObject})); break; case 'color' : axesNode.appendChild(new amdaPlotObj.PlotColorAxisTreeNode({object : axisObject})); break; } }); this.getView().refresh(); }, buildPanelParamsNode: function(panelObject, selectedParamId) { selectedParamId = (typeof selectedParamId !== 'undefined') ? selectedParamId : ''; var paramsNode = null; var me = this; this.panelsNode.eachChild(function (panelNode) { //Retrieve corresponding panel node if (panelNode.object == panelObject) { if (!me.isSimplifiedView) { //Retrieve params node paramsNode = panelNode.findChild('type', 'params'); if (!paramsNode) //create axes node paramsNode = panelNode.appendChild(new amdaPlotObj.PlotParamsTreeNode({object : panelObject})); } else paramsNode = panelNode; return; } }); if (paramsNode == null) return; //Remove old param nodes paramsNode.removeAll(); //Add param nodes var selectedParamNode = null; panelObject.params().each(function (paramObject) { var paramNode = paramsNode.appendChild(new amdaPlotObj.PlotParamTreeNode({object : paramObject})); if (paramObject.get('id') == selectedParamId) selectedParamNode = paramNode; }); this.getView().refresh(); if (selectedParamNode) this.getSelectionModel().select(selectedParamNode); }, addPanelNode: function(panelObject) { var panelNode = this.panelsNode.appendChild(new amdaPlotObj.PlotPanelTreeNode({object : panelObject})); if (!this.isSimplifiedView) //Axes node this.buildPanelAxesNode(panelObject); //Params node this.buildPanelParamsNode(panelObject); return panelNode; }, movePanel : function(record,targetNode,position) { var fromIndex = targetNode.parentNode.indexOf(record); var toIndex = targetNode.parentNode.indexOf(targetNode); var fromRecord = this.tabObject.panels().getAt(fromIndex); if (!fromRecord) return false; switch (position) { case 'before' : this.tabObject.panels().data.removeAt(fromIndex); var insertIndex = (fromIndex > toIndex) ? toIndex : toIndex - 1; this.tabObject.panels().data.insert(insertIndex, fromRecord); this.buildPanelsNode(); this.getSelectionModel().select(this.panelsNode.getChildAt(insertIndex)); return true; case 'after' : this.tabObject.panels().data.removeAt(fromIndex); var insertIndex = (fromIndex > toIndex) ? toIndex + 1 : toIndex; this.tabObject.panels().data.insert(insertIndex, fromRecord); this.buildPanelsNode(); this.getSelectionModel().select(this.panelsNode.getChildAt(insertIndex)); return true; break; default : return false; } return true; }, moveParam : function(record,targetNode,position) { /*var fromIndex = targetNode.parentNode.indexOf(record); var toIndex = targetNode.parentNode.indexOf(targetNode); var fromRecord = this.tabObject.panels().getAt(fromIndex); if (!fromRecord) return false; switch (position) { case 'before' : this.tabObject.panels().data.removeAt(fromIndex); var insertIndex = (fromIndex > toIndex) ? toIndex : toIndex - 1; this.tabObject.panels().data.insert(insertIndex, fromRecord); this.buildPanelsNode(); this.getSelectionModel().select(this.panelsNode.getChildAt(insertIndex)); return true; case 'after' : this.tabObject.panels().data.removeAt(fromIndex); var insertIndex = (fromIndex > toIndex) ? toIndex + 1 : toIndex; this.tabObject.panels().data.insert(insertIndex, fromRecord); this.buildPanelsNode(); this.getSelectionModel().select(this.panelsNode.getChildAt(insertIndex)); return true; break; default : return false; }*/ console.log('ToDo move param'); return true; }, onNodeSelect: function(tree, record, index, eOpts) { if (index == -1) return; if (this.plotElementPanel != null) this.plotElementPanel.setElement(record.type, record.object, this); }, onNodeDeselect: function(tree, record, index, eOpts) { if (this.plotElementPanel != null) this.plotElementPanel.resetElement(); }, onCellClick: function(tree, td, cellIndex, record, tr, rowIndex, e, eOpts) { if ((cellIndex === 1) && record.get('removable')) { this.getSelectionModel().deselectAll(); switch (record.get('type')) { case 'panel' : if (this.tabObject.removePanelById(record.object.get('id'))) this.buildPanelsNode(); break; case 'param' : var panelObject = null; if (!this.isSimplifiedView) panelObject = record.parentNode.parentNode.object; else panelObject = record.parentNode.object; //removeParamById if (panelObject.removeParamById(record.object.get('id'))) this.buildPanelsNode(); break; } } }, getSelectedNode: function() { var selection = this.getSelectionModel().getSelection(); if ((selection == null) || (selection.length == 0)) return null; return selection[0]; }, getSelectedPlotType: function() { var selectedNode = this.getSelectedNode(); if (selectedNode == null) return 'none'; var crtNode = selectedNode; do { if (crtNode.get('type') == 'panel') return crtNode.object.get('panel-plot-type'); crtNode = crtNode.parentNode; } while(crtNode != null); return 'none'; }, isValidToDrop : function(record,targetNode,position) { switch (record.$className) { case 'amdaModel.LocalParamNode' : case 'amdaModel.RemoteParamNode' : case 'amdaModel.RemoteSimuParamNode' : return record.get('isParameter') && ! record.get('disable'); case 'amdaModel.AliasNode' : case 'amdaModel.DerivedParamNode' : case 'amdaModel.MyDataParamNode' : return record.isLeaf(); case 'amdaPlotObj.PlotParamTreeNode' : return true; case 'amdaPlotObj.PlotPanelTreeNode' : switch (position) { case 'append' : return false; case 'before' : return (targetNode.$className == 'amdaPlotObj.PlotPanelTreeNode'); case 'after' : return ((targetNode.$className == 'amdaPlotObj.PlotPanelTreeNode') && targetNode.isLast()); } } return false; }, dropParamToCreate : function(targetNode, position, paramId, needsArgs, plotOnly) { var panelObject = null; if (targetNode == null) { //create new panel panelObject = this.tabObject.createNewPanel(); //Rebuild params node this.buildPanelsNode(); } else { switch (targetNode.$className) { case 'amdaPlotObj.PlotParamsTreeNode' : case 'amdaPlotObj.PlotPanelTreeNode' : case 'amdaPlotObj.PlotAxesTreeNode' : panelObject = targetNode.object; break; case 'amdaPlotObj.PlotTimeAxisTreeNode' : case 'amdaPlotObj.PlotEpochAxisTreeNode' : case 'amdaPlotObj.PlotXAxisTreeNode' : case 'amdaPlotObj.PlotYLeftAxisTreeNode' : case 'amdaPlotObj.PlotYRightAxisTreeNode' : case 'amdaPlotObj.PlotColorAxisTreeNode' : case 'amdaPlotObj.PlotParamTreeNode' : panelObject = targetNode.parentNode.object; break; default: //create new panel panelObject = this.tabObject.createNewPanel(); //Rebuild params node this.buildPanelsNode(); } } //Create param object var newParamObject = panelObject.createNewParam(); newParamObject.set('param-id', paramId); this.buildPanelParamsNode(panelObject, newParamObject.get('id')); }, dropRecord : function(record,targetNode,position) { var selModel = this.getSelectionModel(); //select the target node if defined if (targetNode) selModel.select(targetNode); else selModel.deselectAll(); switch (record.$className) { case 'amdaModel.LocalParamNode' : case 'amdaModel.RemoteParamNode' : case 'amdaModel.RemoteSimuParamNode' : if (!record.get('isParameter') || record.get('disable')) return false; var needsArgs = false; if (record.$className == 'amdaModel.RemoteSimuParamNode') { needsArgs = record.get('needsArgs'); } else if (record.$className == 'amdaModel.LocalParamNode') { needsArgs = record.get('needsArgs') && !record.get('isSpectra'); } if (record.get('alias') != "" ) this.dropParamToCreate(targetNode, position, "#"+record.get('alias'), needsArgs); else this.dropParamToCreate(targetNode, position, record.get('id'), needsArgs, record.get('notyet')); return true; case 'amdaModel.AliasNode' : if (!record.isLeaf()) return false; this.dropParamToCreate(targetNode, position, "#"+record.get('text')); return true; case 'amdaModel.DerivedParamNode' : if (!record.isLeaf()) return false; this.dropParamToCreate(targetNode, position, "ws_"+record.get('text')); return true; case 'amdaModel.MyDataParamNode' : if (!record.isLeaf()) return false; this.dropParamToCreate(targetNode, position, "wsd_"+record.get('text')); return true; case 'amdaPlotObj.PlotParamTreeNode' : return this.moveParam(record,targetNode,position); case 'amdaPlotObj.PlotPanelTreeNode' : return this.movePanel(record,targetNode,position); default : return false; } return false; }, getDragAndDropPluginConfig : function() { var me = this; return { ptype:'treeviewdragdrop', ddGroup:'explorerTree', enableDrag:true, enableDrop:true, appendOnly : false, allowContainerDrops : true, containerScroll : true, isValidDropPoint : function (node, position, dragZone, e, data) { if (!node || !data.item) { return false; } var view = this.view, targetNode = view.getRecord(node), draggedRecords = data.records, dataLength = draggedRecords.length, ln = draggedRecords.length, i, record; // No drop position, or dragged records: invalid drop point if (!(targetNode && position && dataLength)) { return false; } // If the targetNode is within the folder we are dragging for (i = 0; i < ln; i++) { record = draggedRecords[i]; if (record.isNode && record.contains(targetNode)) { return false; } } // Respect the allowDrop field on Tree nodes if (position === 'append' && targetNode.get('allowDrop') === false) { return false; } // If the target record is in the dragged dataset, then invalid drop if (Ext.Array.contains(draggedRecords, targetNode)) { return false; } if (dataLength > 1) return false; var draggedRecord = draggedRecords[0]; return me.isValidToDrop(draggedRecord,targetNode,position); }, onPlotContainerDrop : function(dd, e, data){ if (data.records.length != 1) return false; return me.dropRecord(data.records[0],null,null); }, onPlotNodeDrop : function(n, dd, e, data){ if (data.records.length != 1) return false; return me.dropRecord(data.records[0],this.view.getRecord(n),this.getPosition(e,n)); }, onPlotContainerOver : function(dd, e, data) { if (data.records.length != 1) return false; var draggedRecord = data.records[0]; return me.isValidToDrop(draggedRecord,null,'append') ? this.dropAllowed : this.dropNotAllowed; }, onViewRender : function(view) { var me = this; if (me.enableDrag) { me.dragZone = Ext.create('Ext.tree.ViewDragZone', { view: view, ddGroup: me.dragGroup || me.ddGroup, dragText: me.dragText, repairHighlightColor: me.nodeHighlightColor, repairHighlight: me.nodeHighlightOnRepair }); } if (me.enableDrop) { me.dropZone = Ext.create('Ext.tree.ViewDropZone', { view: view, ddGroup: me.dropGroup || me.ddGroup, allowContainerDrops: me.allowContainerDrops, appendOnly: me.appendOnly, allowParentInserts: me.allowParentInserts, expandDelay: me.expandDelay, dropHighlightColor: me.nodeHighlightColor, dropHighlight: me.nodeHighlightOnDrop, isValidDropPoint : me.isValidDropPoint, onContainerDrop : me.onPlotContainerDrop, onNodeDrop : me.onPlotNodeDrop, onContainerOver : me.onPlotContainerOver }); } } } }, init : function(config) { var me = this; this.plotElementPanel = config.plotElementPanel; var store = Ext.create('Ext.data.TreeStore', { root: { expanded: true } }); this.plotElementPanel = config.plotElementPanel; var myConf = { store: store, rootVisible: false, hideHeaders: true, viewConfig:{ plugins: this.getDragAndDropPluginConfig() }, listeners: { select: me.onNodeSelect, deselect: me.onNodeDeselect, cellclick: me.onCellClick, scope: me }, columns: [ { xtype: 'treecolumn', text: 'Plot Element', flex: 1, dataIndex: 'text', renderer: function (val, meta, rec) { var fullVal = val; if (rec.getAdditionalText) fullVal += rec.getAdditionalText(); return fullVal; } }, { menuDisabled: true, align: 'center', width: 24, renderer: function(v,m,record){ if (record.get('removable')) return'
'; else return ''; } } ], tbar: [ { xtype: 'button', text: 'Add panel', iconCls: 'icon-add', handler: function() { var newPabelNode = this.addPanelNode(this.tabObject.createNewPanel()); this.getSelectionModel().select(newPabelNode); }, scope: this }, '->', { xtype: 'checkbox', boxLabel: 'Simplified View', listeners: { change: function(combo, newValue, oldValue, eOpts) { this.setSimplifiedMode(newValue); }, scope: this } } ] }; Ext.apply (this , Ext.apply (arguments, myConf)); } });