UNPKG

webgme

Version:

Web-based Generic Modeling Environment

398 lines (315 loc) 12.9 kB
/*globals define, _, WebGMEGlobal, $*/ /*jshint browser: true*/ /** * @author rkereskenyi / https://github.com/rkereskenyi * @author nabana / https://github.com/nabana * @author brollb / https://github.com/brollb */ define(['js/logger', 'js/util', 'js/Constants', 'js/Utils/GMEConcepts', 'js/NodePropertyNames' ], function (Logger, util, CONSTANTS, GMEConcepts, nodePropertyNames) { 'use strict'; var GraphVizControl; GraphVizControl = function (options) { this._logger = Logger.create('gme:Panels:GraphViz:GraphVizControl', WebGMEGlobal.gmeConfig.client.log); this._client = options.client; //initialize core collections and variables this._graphVizWidget = options.widget; this._currentNodeId = null; this._currentNodeParentId = undefined; this._displayModelsOnly = false; this._initWidgetEventHandlers(); this._logger.debug('Created'); this._timeoutId = null; }; GraphVizControl.prototype._initWidgetEventHandlers = function () { var self = this; this._graphVizWidget.onBackgroundDblClick = function () { if (self._currentNodeParentId) { WebGMEGlobal.State.registerActiveObject(self._currentNodeParentId); } }; this._graphVizWidget.onNodeOpen = function (id) { self._selfPatterns[id] = {children: 1}; self._client.updateTerritory(self._territoryId, self._selfPatterns); }; this._graphVizWidget.onNodeDblClick = function (id) { WebGMEGlobal.State.registerActiveObject(id); }; this._graphVizWidget.onExtendMenuItems = (nodeId, menuItems) => { return this.onExtendMenuItems(nodeId, menuItems); }; this._graphVizWidget.deleteNode = nodeId => { this._client.deleteNode(nodeId); }; this._graphVizWidget.onNodeClose = function (id) { var deleteRecursive, node, childrenIDs, i; deleteRecursive = function (nodeId) { if (self._selfPatterns.hasOwnProperty(nodeId)) { node = self._nodes[nodeId]; if (node) { childrenIDs = node.childrenIDs; for (i = 0; i < childrenIDs.length; i += 1) { deleteRecursive(childrenIDs[i]); } } delete self._selfPatterns[nodeId]; } }; //call the cleanup recursively deleteRecursive(id); if (id === self._currentNodeId) { self._selfPatterns[id] = {children: 0}; } self._client.updateTerritory(self._territoryId, self._selfPatterns); }; }; GraphVizControl.prototype.selectedObjectChanged = function (nodeId) { var desc = this._getObjectDescriptor(nodeId), self = this; this._logger.debug('activeObject nodeId \'' + nodeId + '\''); //remove current territory patterns if (this._currentNodeId) { this._client.removeUI(this._territoryId); } this._currentNodeId = nodeId; this._currentNodeParentId = undefined; this._nodes = {}; clearTimeout(this._timeoutId); if (typeof this._currentNodeId === 'string' && desc) { //put new node's info into territory rules this._selfPatterns = {}; this._selfPatterns[nodeId] = {children: 0}; this._graphVizWidget.setTitle((desc.name || '').toUpperCase()); // if (desc.parentId || desc.parentId === CONSTANTS.PROJECT_ROOT_ID) { // this.$btnModelHierarchyUp.show(); // } else { // this.$btnModelHierarchyUp.hide(); // } this._currentNodeParentId = desc.parentId; this._territoryId = this._client.addUI(this, function (events) { self._eventCallback(events); }); //update the territory this._client.updateTerritory(this._territoryId, this._selfPatterns); this._timeoutId = setTimeout(function () { self._selfPatterns[nodeId] = {children: 1}; self._client.updateTerritory(self._territoryId, self._selfPatterns); }, 1000); } }; GraphVizControl.prototype._getObjectDescriptor = function (nodeId) { var nodeObj = this._client.getNode(nodeId), objDescriptor; if (nodeObj) { objDescriptor = { 'id': undefined, 'name': undefined, 'childrenIDs': undefined, 'parentId': undefined, 'isConnection': false }; objDescriptor.id = nodeObj.getId(); objDescriptor.name = nodeObj.getAttribute(nodePropertyNames.Attributes.name); objDescriptor.childrenIDs = nodeObj.getChildrenIds(); objDescriptor.childrenNum = objDescriptor.childrenIDs.length; objDescriptor.parentId = nodeObj.getParentId(); objDescriptor.isConnection = GMEConcepts.isConnection(nodeId); } return objDescriptor; }; GraphVizControl.prototype._eventCallback = function (events) { var i = events ? events.length : 0, e; this._logger.debug('_eventCallback \'' + i + '\' items'); while (i--) { e = events[i]; switch (e.etype) { case CONSTANTS.TERRITORY_EVENT_LOAD: this._onLoad(e.eid); break; case CONSTANTS.TERRITORY_EVENT_UPDATE: this._onUpdate(e.eid); break; case CONSTANTS.TERRITORY_EVENT_UNLOAD: this._onUnload(e.eid); break; default: break; } } this._generateData(); this._logger.debug('_eventCallback \'' + events.length + '\' items - DONE'); }; GraphVizControl.prototype._generateData = function () { var self = this, data; data = _.extend({}, (this._currentNodeId || this._currentNodeId === CONSTANTS.PROJECT_ROOT_ID) ? this._nodes[this._currentNodeId] : {}); function loadRecursive(node) { var len = (node && node.childrenIDs) ? node.childrenIDs.length : 0; while (len--) { node.children = node.children || []; if (self._nodes[node.childrenIDs[len]]) { if ((self._displayModelsOnly === true && self._nodes[node.childrenIDs[len]].isConnection !== true) || self._displayModelsOnly === false) { node.children.push(_.extend({}, self._nodes[node.childrenIDs[len]])); loadRecursive(node.children[node.children.length - 1]); } } } } loadRecursive(data); this._graphVizWidget.setData(data); }; // PUBLIC METHODS GraphVizControl.prototype._onLoad = function (gmeID) { this._nodes[gmeID] = this._getObjectDescriptor(gmeID); }; GraphVizControl.prototype._onUpdate = function (gmeID) { this._nodes[gmeID] = this._getObjectDescriptor(gmeID); }; GraphVizControl.prototype._onUnload = function (gmeID) { delete this._nodes[gmeID]; }; GraphVizControl.prototype.destroy = function () { clearTimeout(this._timeoutId); if (this._territoryId) { this._client.removeUI(this._territoryId); } this._detachClientEventListeners(); this._removeToolbarItems(); }; GraphVizControl.prototype._stateActiveObjectChanged = function (model, activeObjectId) { if (this._currentNodeId === activeObjectId) { // [patrik] added this check to avoid redrawing when becoming active in split panel mode. this._logger.debug('Disregarding activeObject changed when it is already the same.'); } else { this.selectedObjectChanged(activeObjectId); } }; GraphVizControl.prototype._attachClientEventListeners = function () { this._detachClientEventListeners(); WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged, this); }; GraphVizControl.prototype._detachClientEventListeners = function () { WebGMEGlobal.State.off('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged); }; GraphVizControl.prototype.onActivate = function () { this._attachClientEventListeners(); this._displayToolbarItems(); //setting the active object to the root of the graph if (typeof this._currentNodeId === 'string') { WebGMEGlobal.State.registerActiveObject(this._currentNodeId, {suppressVisualizerFromNode: true}); } }; GraphVizControl.prototype.onDeactivate = function () { this._detachClientEventListeners(); this._hideToolbarItems(); }; GraphVizControl.prototype._displayToolbarItems = function () { var i; if (this._toolbarInitialized === true) { for (i = 0; i < this._toolbarItems.length; i++) { this._toolbarItems[i].show(); } } else { this._initializeToolbar(); } }; GraphVizControl.prototype._hideToolbarItems = function () { var i; if (this._toolbarInitialized === true) { for (i = 0; i < this._toolbarItems.length; i++) { this._toolbarItems[i].hide(); } } }; GraphVizControl.prototype._removeToolbarItems = function () { var i; if (this._toolbarInitialized === true) { for (i = 0; i < this._toolbarItems.length; i++) { this._toolbarItems[i].destroy(); } } }; GraphVizControl.prototype._initializeToolbar = function () { var toolBar = WebGMEGlobal.Toolbar; this._toolbarItems = []; this._toolbarItems.push(toolBar.addSeparator()); /************** MODEL / CONNECTION filter *******************/ // // this.$cbShowConnection = toolBar.addCheckBox({ // title: 'Show connection', // icon: 'gme icon-gme_diagonal-arrow', // checkChangedFn: function (data, checked) { // self._displayModelsOnly = !checked; // self._generateData(); // } // }); // // this._toolbarItems.push(this.$cbShowConnection); /************** END OF - MODEL / CONNECTION filter *******************/ this._toolbarInitialized = true; }; GraphVizControl.prototype._addSplitPanelToolbarBtns = function (toolbarEl) { var self = this, connBtn = $('<span class="split-panel-toolbar-btn no-print glyphicon glyphicon-filter"></span>'); connBtn.on('click', function () { self._displayModelsOnly = !self._displayModelsOnly; if (self._displayModelsOnly) { connBtn.attr('title', 'Show connections'); } else { connBtn.attr('title', 'Hide connections'); } self._generateData(); }); if (self._displayModelsOnly) { connBtn.attr('title', 'Show connections'); } else { connBtn.attr('title', 'Hide connections'); } toolbarEl.append(connBtn); connBtn.hide(); return toolbarEl; }; GraphVizControl.prototype.onExtendMenuItems = function (nodeId, menuItems) { const node = this._client.getNode(nodeId); const childIds = Object.keys((node && node.getValidChildrenTypesDetailed()) || {}); if (childIds.length > 0) { const childMenuItems = {}; const validChildren = childIds.forEach(id => { const node = this._client.getNode(id); childMenuItems[id] = { name: node.getAttribute('name'), callback: () => { const params = { parentId: nodeId, baseId: id, }; this._client.createNode(params); }, }; }); menuItems.createNode = { name: 'Create child', icon: 'add', items: childMenuItems, }; } return menuItems; }; return GraphVizControl; });