/** * 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' ], //Link to the combo box to define the use of the simplified view simplifiedViewCombo : null, //Link to the combo to attach the tab to the multi plot mode //Link to the Plot Element Panel plotElementPanel: null, //Link to the Plot Tab Content Panel plotTabContent : null, //Tab object tabObject: null, //Panels list node panelsNode: null, constructor: function(config) { this.init(config); this.callParent(arguments); }, refresh: function() { this.getView().refresh(); }, buildTree: function(tabObject) { if (this.store.getRootNode().hasChildNodes()) this.store.getRootNode().removeAll(); this.tabObject = tabObject; this.simplifiedViewCombo.setValue(this.tabObject.get('tree-simplified-view')); this.linkToMultiPlotCombo.setValue(this.tabObject.get('multi-plot-linked')); if (!this.tabObject.get('tree-simplified-view')) { //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(paramNodeToSelect) { if (this.panelsNode.hasChildNodes()) this.panelsNode.removeAll(); var me = this; this.tabObject.updatePanelIndex(); this.tabObject.panels().each(function (panelObject) { me.addPanelNode(panelObject, paramNodeToSelect); }); }, 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.tabObject.get('tree-simplified-view')) { //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); }, buildPanelAdditionalObjectsNode: function(panelObject, selectedObject) { selectedObject = (typeof selectedObject !== 'undefined') ? selectedObject : null; var objectsNode = null; var me = this; this.panelsNode.eachChild(function (panelNode) { //Retrieve corresponding panel node if (panelNode.object == panelObject) { //Retrieve additional objects node objectsNode = panelNode.findChild('type', 'objects'); if (!objectsNode) { //create additional objects node objectsNode = panelNode.appendChild(new amdaPlotObj.PlotAdditionalObjectsTreeNode({object : panelObject})); } return; } }); if (objectsNode == null) return; //Remove old objects nodes objectsNode.removeAll(); //create legends node this.buildPanelLegendsNode(panelObject, objectsNode, selectedObject); //create drawing objects node this.buildDrawingObjectsNode(panelObject, objectsNode, selectedObject); //create fills node this.buildFillsNode(panelObject, objectsNode, selectedObject); }, buildPanelLegendsNode: function(panelObject, objectsNode, selectedObject) { var legendsNode = objectsNode.appendChild(new amdaPlotObj.PlotLegendsTreeNode({object : panelObject})); legendsNode.appendChild(new amdaPlotObj.PlotSeriesLegendTreeNode({object : panelObject})); var textLegendsNode = legendsNode.appendChild(new amdaPlotObj.PlotTextLegendsTreeNode({object : panelObject})); var selectedTextLegendNode = null; panelObject.textLegends().each(function (legendObject) { var textLegendNode = textLegendsNode.appendChild(new amdaPlotObj.PlotTextLegendTreeNode({object : legendObject})); if (legendObject == selectedObject) selectedTextLegendNode = textLegendNode; }); this.getView().refresh(); if (selectedTextLegendNode) this.getSelectionModel().select(selectedTextLegendNode); }, buildDrawingObjectsNode: function(panelObject, objectsNode, selectedObject) { var drawingObjectsNode = objectsNode.appendChild(new amdaPlotObj.PlotDrawingObjectsTreeNode({object : panelObject})); //Constants var selectedConstantNode = null; panelObject.constants().each(function (constantObject) { var constantNode = drawingObjectsNode.appendChild(new amdaPlotObj.PlotConstantTreeNode({object : constantObject})); if (constantObject == selectedObject) selectedConstantNode = constantNode; }); //Texts var selectedTextNode = null; panelObject.textObjs().each(function (textObject) { var textNode = drawingObjectsNode.appendChild(new amdaPlotObj.PlotTextTreeNode({object : textObject})); if (textObject == selectedObject) selectedTextNode = textNode; }); //Curves var selectedCurveNode = null; panelObject.curves().each(function (curveObject) { var curveNode = drawingObjectsNode.appendChild(new amdaPlotObj.PlotCurveTreeNode({object : curveObject})); if (curveObject == selectedObject) selectedCurveNode = curveNode; }); //Refresh & selection this.getView().refresh(); if (selectedConstantNode) this.getSelectionModel().select(selectedConstantNode); if (selectedTextNode) this.getSelectionModel().select(selectedTextNode); if (selectedCurveNode) this.getSelectionModel().select(selectedCurveNode); }, buildFillsNode: function(panelObject, objectsNode, selectedObject) { var fillsNode = objectsNode.appendChild(new amdaPlotObj.PlotFillsTreeNode({object : panelObject})); var selectedFillNode = null; panelObject.fills().each(function (fillObject) { var fillNode = fillsNode.appendChild(new amdaPlotObj.PlotFillTreeNode({object : fillObject})); if (fillObject == selectedObject) selectedFillNode = fillNode; }); this.getView().refresh(); if (selectedFillNode) this.getSelectionModel().select(selectedFillNode); }, addPanelNode: function(panelObject, paramNodeToSelect) { var panelNode = this.panelsNode.appendChild(new amdaPlotObj.PlotPanelTreeNode({object : panelObject})); if (!this.tabObject.get('tree-simplified-view')) { //Axes node this.buildPanelAxesNode(panelObject); //Additional objects this.buildPanelAdditionalObjectsNode(panelObject); } //Params node this.buildPanelParamsNode(panelObject, paramNodeToSelect); 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) { if ((record.$className != 'amdaPlotObj.PlotParamTreeNode') || (targetNode == null)) return false; var fromIndex = record.parentNode.indexOf(record); var toIndex = targetNode.parentNode.indexOf(targetNode); var fromPanelObject = null; if (!this.tabObject.get('tree-simplified-view')) { fromPanelObject = record.parentNode.parentNode.object; } else fromPanelObject = record.parentNode.object; if (fromPanelObject == null) return false; switch (targetNode.$className) { case 'amdaPlotObj.PlotPanelTreeNode' : case 'amdaPlotObj.PlotParamsTreeNode' : var toPanelObject = targetNode.object; if (toPanelObject.get('panel-plot-type') != fromPanelObject.get('panel-plot-type')) return false; if (toPanelObject == fromPanelObject) { //Move param on the same panel fromPanelObject.params().data.removeAt(fromIndex); toPanelObject.params().data.add(record.object); this.buildPanelParamsNode(toPanelObject, record.object.get('id')); } else { //Move param on another panel var clonedObject = record.object.copy(); fromPanelObject.params().remove(record.object); toPanelObject.set('last-param-id', toPanelObject.get('last-param-id')+1); clonedObject.set('id', toPanelObject.get('last-param-id')); toPanelObject.params().add(clonedObject); this.buildPanelParamsNode(fromPanelObject); this.buildPanelParamsNode(toPanelObject, clonedObject.get('id')); } return true; case 'amdaPlotObj.PlotParamTreeNode' : var toPanelObject = null; if (!this.tabObject.get('tree-simplified-view')) { toPanelObject = targetNode.parentNode.parentNode.object; } else toPanelObject = targetNode.parentNode.object; targetNode.object; if (toPanelObject.get('panel-plot-type') != fromPanelObject.get('panel-plot-type')) return false; if (toPanelObject == fromPanelObject) { //Move param on the same panel var insertIndex = -1; switch (position) { case 'before' : insertIndex = (fromIndex > toIndex) ? toIndex : toIndex - 1; break; case 'after' : default : insertIndex = (fromIndex > toIndex) ? toIndex + 1 : toIndex; break; } fromPanelObject.params().data.removeAt(fromIndex); toPanelObject.params().data.insert(insertIndex, record.object); this.buildPanelParamsNode(toPanelObject, record.object.get('id')); } else { //move param on another panel var insertIndex = -1; switch (position) { case 'before' : insertIndex = (toIndex == 0) ? 0: toIndex - 1; break; case 'after' : default : insertIndex = toIndex + 1; break; } var clonedObject = record.object.copy(); fromPanelObject.params().remove(record.object); toPanelObject.set('last-param-id', toPanelObject.get('last-param-id')+1); clonedObject.set('id', toPanelObject.get('last-param-id')); toPanelObject.params().insert(insertIndex, clonedObject); this.buildPanelParamsNode(fromPanelObject); this.buildPanelParamsNode(toPanelObject, clonedObject.get('id')); } return true; } return false; }, 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.tabObject.get('tree-simplified-view')) panelObject = record.parentNode.parentNode.object; else panelObject = record.parentNode.object; //removeParamById if (panelObject.removeParamById(record.object.get('id'))) this.buildPanelsNode(); break; case 'text-legend' : var panelObject = null; if (!this.tabObject.get('tree-simplified-view')) panelObject = record.parentNode.parentNode.object; else panelObject = record.parentNode.object; if (panelObject.removeTextLegendById(record.object.get('id'))) this.buildPanelAdditionalObjectsNode(panelObject); break; case 'constant' : var panelObject = null; if (!this.tabObject.get('tree-simplified-view')) panelObject = record.parentNode.parentNode.object; else panelObject = record.parentNode.object; if (panelObject.removeConstantById(record.object.get('id'))) this.buildPanelAdditionalObjectsNode(panelObject); break; case 'text-obj' : var panelObject = null; if (!this.tabObject.get('tree-simplified-view')) panelObject = record.parentNode.parentNode.object; else panelObject = record.parentNode.object; if (panelObject.removeTextObjectById(record.object.get('id'))) this.buildPanelAdditionalObjectsNode(panelObject); break; case 'curve' : var panelObject = null; if (!this.tabObject.get('tree-simplified-view')) panelObject = record.parentNode.parentNode.object; else panelObject = record.parentNode.object; if (panelObject.removeCurveById(record.object.get('id'))) this.buildPanelAdditionalObjectsNode(panelObject); break; case 'fill' : var panelObject = null; if (!this.tabObject.get('tree-simplified-view')) panelObject = record.parentNode.parentNode.object; else panelObject = record.parentNode.object; if (panelObject.removeFillById(record.object.get('id'))) this.buildPanelAdditionalObjectsNode(panelObject); break; } } }, getSelectedNode: function() { var selection = this.getSelectionModel().getSelection(); if ((selection == null) || (selection.length == 0)) return null; return selection[0]; }, getSelectedPanelObject: function() { var selectedNode = this.getSelectedNode(); if (selectedNode == null) return null; var crtNode = selectedNode; do { if (crtNode.get('type') == 'panel') return crtNode.object; crtNode = crtNode.parentNode; } while(crtNode != null); return null; }, getSelectedPlotType: function() { var crtPanelObject = this.getSelectedPanelObject(); if (crtPanelObject == null) return 'none'; return crtPanelObject.get('panel-plot-type'); }, 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' : var fromPanelObject = null; if (!this.tabObject.get('tree-simplified-view')) { fromPanelObject = record.parentNode.parentNode.object; } else fromPanelObject = record.parentNode.object; if ((fromPanelObject == null) || (targetNode == null)) return false; var toPanelObject = null; switch (targetNode.$className) { case 'amdaPlotObj.PlotPanelTreeNode' : case 'amdaPlotObj.PlotParamsTreeNode' : toPanelObject = targetNode.object; break; case 'amdaPlotObj.PlotParamTreeNode' : if (!this.tabObject.get('tree-simplified-view')) { toPanelObject = targetNode.parentNode.parentNode.object; } else toPanelObject = targetNode.parentNode.object; break; } if (toPanelObject == null) return false; return (fromPanelObject.get('panel-plot-type') == toPanelObject.get('panel-plot-type')); 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, paramComponents) { var panelObject = null; if (targetNode == null) { //create new panel panelObject = this.tabObject.createNewPanel(); } 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(); } } //Create param object var me = this; panelObject.createNewParam(paramId, paramComponents, function (newParamObject) { //Rebuild params node me.buildPanelsNode(newParamObject.getId()); //BRE newParamObject }); }, 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; if (record.get('alias') != "" ) this.dropParamToCreate(targetNode, position, "#"+record.get('alias')); else { var component_info = record.get('component_info'); var param_id = record.get('id'); var components = null; if (component_info && component_info.parentId) { //It's a component param_id = component_info.parentId; components = []; if (component_info.index1) components['index1'] = component_info.index1; if (component_info.index2) components['index2'] = component_info.index2; } this.dropParamToCreate(targetNode, position, param_id, components); } 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 }); } } } }, updateLinkedToMultiPlotMode : function() { this.plotTabContent.updateLinkedToMultiPlotMode(this.tabObject.get('multi-plot-linked')); }, init : function(config) { var me = this; this.plotElementPanel = config.plotElementPanel; var store = Ext.create('Ext.data.TreeStore', { root: { expanded: true } }); this.plotElementPanel = config.plotElementPanel; this.simplifiedViewCombo = Ext.create('Ext.form.field.Checkbox', { xtype: 'checkbox', boxLabel: 'Simplified View', listeners: { change: function(combo, newValue, oldValue, eOpts) { if (this.tabObject) this.tabObject.set('tree-simplified-view', newValue); if (newValue != oldValue) this.buildTree(this.tabObject); }, scope: this } }); this.linkToMultiPlotCombo = Ext.create('Ext.form.field.Checkbox', { xtype: 'checkbox', boxLabel: 'Link to MultiPlot', listeners: { change: function(combo, newValue, oldValue, eOpts) { if (this.tabObject) { this.tabObject.set('multi-plot-linked', newValue); this.updateLinkedToMultiPlotMode(); } }, scope: this } }); var myConf = { store: store, rootVisible: false, hideHeaders: true, viewConfig:{ plugins: this.getDragAndDropPluginConfig(), preserveScrollOnRefresh: true }, 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 }, '->', this.linkToMultiPlotCombo, ' ', this.simplifiedViewCombo ] }; Ext.apply (this , Ext.apply (arguments, myConf)); } });