webgme
Version:
Web-based Generic Modeling Environment
929 lines (796 loc) • 41.2 kB
JavaScript
/*globals define, WebGMEGlobal, _, $*/
/*jshint browser: true*/
/**
* @author rkereskenyi / https://github.com/rkereskenyi
* @author pmeijer / https://github.com/pmeijer
* @author kecso / https://github.com/kecso
*/
define(['js/logger',
'js/NodePropertyNames',
'js/Constants',
'js/RegistryKeys',
'./ObjectBrowserControlBase',
'js/Utils/LibraryManager',
'js/Dialogs/ImportModel/ImportModelDialog',
'js/Utils/Exporters'
], function (Logger,
nodePropertyNames,
CONSTANTS,
REGISTRY_KEYS,
ObjectBrowserControlBase,
LibraryManager,
ImportModelDialog,
exporters) {
'use strict';
var NODE_PROGRESS_CLASS = 'node-progress',
GME_MODEL_CLASS = 'gme-model',
GME_ATOM_CLASS = 'gme-atom',
GME_CONNECTION_CLASS = 'gme-connection',
GME_ROOT_CLASS = 'gme-root',
GME_ASPECT_CLASS = 'gme-aspect',
GME_LIBRARY_CLASS = 'gme-library',
GME_META_ATOM_CLASS = 'gme-meta-atom',
GME_META_SET_CLASS = 'gme-meta-set',
GME_META_MODEL_CLASS = 'gme-meta-model',
GME_META_CONNECTION_CLASS = 'gme-meta-connection',
CROSSCUT_VISUALIZER = 'Crosscut',
SET_VISUALIZER = 'SetEditor',
TREE_ROOT = CONSTANTS.PROJECT_ROOT_ID;
function TreeBrowserControl(client, treeBrowser, config) {
var logger,
stateLoading = 0,
stateLoaded = 1,
selfId,
selfPatterns = {},
//local container for accounting the currently opened node list,
// its a hashmap with a key of nodeId and a value of { FancyTreeNode, childrenIds[], state }
nodes = {},
refresh,
initialize,
initialized = false,
self = this,
getNodeClass,
getLibraryInfo;
//get logger instance for this component
logger = Logger.create('gme:Panels:ObjectBrowser:TreeBrowserControl', WebGMEGlobal.gmeConfig.client.log);
this._logger = logger;
ObjectBrowserControlBase.call(this, client, treeBrowser, logger);
this._treeRootId = TREE_ROOT;
this._libraryManager = new LibraryManager(this._client);
function setTreeRoot() {
var projectId = client.getActiveProjectId(),
projectKind = client.getActiveProjectKind();
if (config.byProjectId.treeRoot.hasOwnProperty(projectId)) {
self._treeRootId = config.byProjectId.treeRoot[projectId];
} else if (projectKind && config.byProjectKind.treeRoot.hasOwnProperty(projectKind)) {
self._treeRootId = config.byProjectKind.treeRoot[projectKind];
} else {
self._treeRootId = config.treeRoot;
}
}
function refreshTreeRoot() {
// Create a new loading node for it in the tree.
var loadingRootTreeNode = treeBrowser.createNode(null, {
id: self._treeRootId,
name: 'Initializing tree...',
hasChildren: true,
class: NODE_PROGRESS_CLASS
});
// Store the node's info in the local hash-map.
nodes[self._treeRootId] = {
treeNode: loadingRootTreeNode,
children: [],
state: stateLoading
};
// Add the tree-root to the query and update the territory.
selfPatterns = {};
selfPatterns[self._treeRootId] = {children: 1};
client.updateTerritory(selfId, selfPatterns);
}
initialize = function () {
var rootNode = client.getNode(CONSTANTS.PROJECT_ROOT_ID);
logger.debug('entered initialize');
setTreeRoot();
if (rootNode) {
logger.debug('rootNode avaliable now');
selfId = client.addUI(self, function (events) {
self._eventCallback(events);
if (initialized === false) {
if (client.getNode(self._treeRootId)) {
logger.debug('loaded territory from "' + self._treeRootId + '" at initialize');
initialized = true;
logger.debug('expanding tree-root', self._treeRootId);
//treeBrowser.updateNode(nodes[self._treeRootId].treeNode, {
// icon: self.getIcon(self._treeRootId, true)
//});
nodes[self._treeRootId].treeNode.setExpanded(true);
} else {
logger.error('Specified tree-root ' + self._treeRootId +
' did not exist in model - falling back on root-node.');
treeBrowser.deleteNode(nodes[self._treeRootId].treeNode);
self._treeRootId = CONSTANTS.PROJECT_ROOT_ID;
nodes = {};
refreshTreeRoot();
}
}
});
refreshTreeRoot();
} else {
logger.debug('rootNode not avaliable at initialize');
setTimeout(initialize, 500);
}
};
getNodeClass = function (nodeObj, isMetaNode) {
var objID = nodeObj.getId(),
c;
if (objID === CONSTANTS.PROJECT_ROOT_ID) {
//if root object
c = GME_ROOT_CLASS;
} else if (nodeObj.isLibraryRoot()) {
c = GME_LIBRARY_CLASS;
} else if (nodeObj.getCrosscutsInfo().length > 0 || nodeObj.getValidSetNames().length > 0) {
c = isMetaNode ? GME_META_SET_CLASS : GME_ASPECT_CLASS;
} else if (nodeObj.isConnection()) {
//if it's a connection, let it have the connection icon
c = isMetaNode ? GME_META_CONNECTION_CLASS : GME_CONNECTION_CLASS;
} else if (nodeObj.getChildrenIds().length > 0) {
//if it has children, let it have the model icon
c = isMetaNode ? GME_META_MODEL_CLASS : GME_MODEL_CLASS;
} else {
//by default everyone is represented with the atom class
c = isMetaNode ? GME_META_ATOM_CLASS : GME_ATOM_CLASS;
}
return c;
};
getLibraryInfo = function (nodeObj) {
var info;
if (!nodeObj.isLibraryRoot()) {
return null;
}
info = client.getLibraryInfo(nodeObj.getFullyQualifiedName());
if (info) {
return 'origin: ' + info.projectId + ' : ' +
(info.branchName ? info.branchName + '@' + info.commitHash : info.commitHash);
}
return null;
};
//called from the TreeBrowserWidget when a node is expanded by its expand icon
treeBrowser.onNodeOpen = function (nodeId) {
//first create dummy elements under the parent representing the childrend being loaded
var parent = client.getNode(nodeId),
childrenDescriptors = [],
metaTypeInfo,
newNodes,
parentNode,
childrenIDs,
i,
currentChildId,
childNode,
childTreeNode;
if (parent) {
//get the DOM node representing the parent in the tree
parentNode = nodes[nodeId].treeNode;
//get the children IDs of the parent
childrenIDs = parent.getChildrenIds();
for (i = 0; i < childrenIDs.length; i += 1) {
currentChildId = childrenIDs[i];
childNode = client.getNode(currentChildId);
//local variable for the created treenode of the child node (loading or full)
childTreeNode = null;
//check if the node could be retreived from the client
if (childNode) {
metaTypeInfo = self.getMetaInfo(childNode);
//the node was present on the client side, render ist full data
childrenDescriptors.push({
id: currentChildId,
name: childNode.getFullyQualifiedName(),
hasChildren: (childNode.getChildrenIds()).length > 0,
class: getNodeClass(childNode, metaTypeInfo.isMetaNode),
icon: self.getIcon(childNode),
isConnection: childNode.isConnection(),
isAbstract: childNode.isAbstract(),
isLibrary: childNode.isLibraryRoot() || childNode.isLibraryElement(),
isLibraryRoot: childNode.isLibraryRoot(),
isMetaNode: metaTypeInfo.isMetaNode,
metaType: metaTypeInfo.name,
libraryInfo: getLibraryInfo(childNode),
// Data used locally here.
STATE: stateLoaded,
CHILDREN: childNode.getChildrenIds()
});
} else {
//the node is not present on the client side, render a loading node instead
childrenDescriptors.push({
id: currentChildId,
name: 'Loading...',
hasChildren: false,
class: NODE_PROGRESS_CLASS,
// Data used locally here.
STATE: stateLoading,
CHILDREN: []
});
}
}
newNodes = treeBrowser.createNodes(parentNode, childrenDescriptors);
for (i = 0; i < childrenDescriptors.length; i += 1) {
nodes[childrenDescriptors[i].id] = {
treeNode: newNodes[i],
children: childrenDescriptors[i].CHILDREN,
state: childrenDescriptors[i].STATE
};
}
treeBrowser.updateNode(parentNode, {icon: self.getIcon(parent, true)});
treeBrowser.applyFilters();
}
//need to expand the territory
selfPatterns[nodeId] = {children: 1};
client.updateTerritory(selfId, selfPatterns);
};
//called from the TreeBrowserWidget when a node has been closed by its collapse icon
treeBrowser.onNodeClose = function (nodeId) {
//remove all children (all deep-nested children) from the accounted open-node list
//local array to hold all the (nested) children ID to remove from the territory
var removeFromTerritory = [],
deleteNodeAndChildrenFromLocalHash;
//removes all the (nested)childrendIDs from the local hashmap
// accounting the currently opened nodes's info
deleteNodeAndChildrenFromLocalHash = function (childNodeId, deleteSelf) {
var xx;
//if the given node is in this hashmap itself, go forward with its children's ID recursively
if (nodes[childNodeId]) {
for (xx = 0; xx < nodes[childNodeId].children.length; xx += 1) {
deleteNodeAndChildrenFromLocalHash(nodes[childNodeId].children[xx], true);
}
//finally delete the nodeId itself (if needed)
if (deleteSelf === true) {
delete nodes[childNodeId];
//and collect the nodeId from territory removal
if (selfPatterns[childNodeId]) {
removeFromTerritory.push({nodeid: childNodeId});
delete selfPatterns[childNodeId];
}
}
}
};
//call the cleanup recursively and mark this node (being closed) as non removable
// (from local hashmap neither from territory)
deleteNodeAndChildrenFromLocalHash(nodeId, false);
treeBrowser.updateNode(nodes[nodeId].treeNode, {icon: self.getIcon(nodeId)});
//if there is anything to remove from the territory, do it
if (removeFromTerritory.length > 0) {
client.updateTerritory(selfId, selfPatterns);
}
};
//called from the TreeBrowserWidget when a node has been marked to "copy this"
treeBrowser.onNodeCopy = function (selectedIds) {
client.copyNodes(selectedIds);
};
//called when the user double-cliked on a node in the tree
treeBrowser.onNodeDoubleClicked = function (nodeId) {
logger.debug('Firing onNodeDoubleClicked with nodeId: ' + nodeId);
//var settings = {};
WebGMEGlobal.State.registerActiveObject(nodeId);
};
// We overwrite the one from the base class..
treeBrowser.onExtendMenuItems = function (nodeId, menuItems) {
var validChildren = self._getValidChildrenTypesFlattened(nodeId),
selectedIds = self._treeBrowser.getSelectedIDs() || [],
single = selectedIds.length === 1,
nodeObj = self._client.getNode(nodeId),
createChildFn = function (key/*, options*/) {
self._createChild(nodeId, key);
},
validChildrenMetaNames = Object.keys(validChildren),
i;
if (!nodeObj) {
return;
}
if (single && validChildrenMetaNames.length > 0 && !nodeObj.isReadOnly()) {
menuItems.create = { // The "create" menu item
name: 'Create child',
icon: 'add',
items: {}
};
validChildrenMetaNames.sort();
//iterate through each possible item and att it to the list
for (i = 0; i < validChildrenMetaNames.length; i += 1) {
menuItems.create.items[validChildren[validChildrenMetaNames[i]]] = {
name: validChildrenMetaNames[i],
callback: createChildFn
};
}
}
//now we are removing invalid items
if (nodeObj.isReadOnly() || nodeId === CONSTANTS.PROJECT_ROOT_ID) {
delete menuItems.delete;
}
if (client.isReadOnly() || nodeObj.isLibraryElement()) {
delete menuItems.rename;
}
//check if there is any operation left in the menu and set separators accordingly
if (menuItems.delete || menuItems.rename || menuItems.create) {
menuItems.separatorOperationsEnd = '-';
} else {
delete menuItems.separatorOperationsStart;
}
if (nodeId === CONSTANTS.PROJECT_ROOT_ID) {
if (client.isReadOnly() === false) {
menuItems.addLibrary = {
name: 'Add Library ...',
callback: function (/*key, options*/) {
self._libraryManager.add();
},
icon: false
};
}
menuItems.exportProject = {
name: 'Export project',
icon: false,
items: {
assetfull: {
name: 'with assets',
callback: function (/*key, options*/) {
exporters.exportProject(self._client, self._logger, null, true);
},
icon: false
},
assetless: {
name: 'without assets',
callback: function (/*key, options*/) {
exporters.exportProject(self._client, self._logger, null, false);
},
icon: false
}
}
};
}
if (selectedIds.indexOf(CONSTANTS.PROJECT_ROOT_ID) === -1 || selectedIds.length === 1) {
// TODO check and decide where and how to put an additional separator
// menuItems.separatorModelStart = '-';
if (selectedIds.indexOf(CONSTANTS.PROJECT_ROOT_ID) === -1) {
menuItems.exportModel = {
name: 'Export models',
icon: false,
items: {
assetfull: {
name: 'with assets',
callback: function (/*key, options*/) {
exporters.exportModels(self._client, self._logger, selectedIds, true);
},
icon: false
},
assetless: {
name: 'without assets',
callback: function (/*key, options*/) {
exporters.exportModels(self._client, self._logger, selectedIds, false);
},
icon: false
}
}
};
if (selectedIds.length === 1) {
menuItems.exportModel.name = 'Export model';
}
}
if (selectedIds.length === 1 && nodeObj.isReadOnly() === false) {
menuItems.importModel = {
name: 'Import models ...',
icon: false,
callback: function (/*key,options*/) {
var importDialog = new ImportModelDialog(self._client, self._logger.fork('ImportModel'));
importDialog.show(nodeId);
}
};
}
}
if (nodeObj.isLibraryRoot() && !nodeObj.isLibraryElement()) {
delete menuItems.exportModel;
delete menuItems.importModel;
menuItems.library = {
name: 'Library',
items: {
viewLibrary: {
name: 'View commit of library',
callback: function (/*key, options*/) {
self._libraryManager.openLibraryOriginInNewWindow(nodeId);
},
icon: false
},
followLibrary: {
name: 'View branch of library',
callback: function (/*key, options*/) {
self._libraryManager.openLibraryOriginInNewWindow(nodeId, true);
},
icon: false
}
},
icon: false
};
if (client.isReadOnly() === false) {
menuItems.library.items.libraryEditSepararator = '-';
menuItems.library.items.refreshLibrary = {
name: 'Update library ...',
callback: function (/*key, options*/) {
var libraryName = nodeObj.getFullyQualifiedName();
self._libraryManager.update(nodeId);
},
icon: false
};
menuItems.library.items.removeLibrary = {
name: 'Remove library ...',
callback: function (/*key, options*/) {
self._libraryManager.remove(nodeId);
},
icon: 'delete'
};
//the rename should not be inplace
menuItems.rename.callback = function (/*key, options*/) {
self._libraryManager.rename(nodeId);
};
menuItems.rename.name = 'Rename ...';
}
}
if (nodeObj.getCrosscutsInfo().length > 0 || nodeObj.getValidSetNames().length > 0) {
// Turn open into a menu ..
menuItems.open = {
name: 'Open in visualizer',
items: {
defaultViz: menuItems.open
},
icon: 'paste'
};
menuItems.open.items.defaultViz.name = 'Default visualizer';
menuItems.open.items.defaultViz.icon = false;
if (nodeObj.getCrosscutsInfo().length > 0) {
menuItems.open.items.crosscut = { //Open in crosscuts
name: 'Crosscuts',
callback: function (/*key, options*/) {
var settings = {};
settings[CONSTANTS.STATE_ACTIVE_OBJECT] = nodeId;
settings[CONSTANTS.STATE_ACTIVE_VISUALIZER] = CROSSCUT_VISUALIZER;
WebGMEGlobal.State.set(settings, {
suppressVisualizerFromNode: true
});
},
icon: false
};
}
if (nodeObj.getValidSetNames().length > 0) {
menuItems.open.items.set = { //Open in crosscuts
name: 'Set membership',
callback: function (/*key, options*/) {
var settings = {};
settings[CONSTANTS.STATE_ACTIVE_OBJECT] = nodeId;
settings[CONSTANTS.STATE_ACTIVE_VISUALIZER] = SET_VISUALIZER;
WebGMEGlobal.State.set(settings, {
suppressVisualizerFromNode: true
});
},
icon: false
};
}
}
};
refresh = function (eventType, objectId) {
var nodeDescriptor = null,
currentChildId = null,
j = 0,
removeFromTerritory,
updatedObject,
objType,
oldChildren,
currentChildren,
childrenDeleted,
deleteNodeAndChildrenFromLocalHash,
childrenAdded,
childNode,
metaTypeInfo,
childTreeNode;
logger.debug('Refresh event \'' + eventType + '\', with objectId: \'' + objectId + '\'');
//HANDLE INSERT
//object got inserted into the territory
if (eventType === 'insert') {
//check if this control shows any interest for this object
if (nodes[objectId]) {
//if the object is in "loading" state according to the local hashmap
//update the "loading" node accordingly
if (nodes[objectId].state === stateLoading) {
//set eventType to "update" and let it go and be handled by "update" event
eventType = 'update';
}
}
}
//ENDOF : HANDLE INSERT
//HANDLE UPDATE
//object got updated in the territory
if (eventType === 'update' || eventType === 'unload') {
//handle deleted children
removeFromTerritory = [];
//check if this control shows any interest for this object
if (nodes[objectId]) {
logger.debug('Update object with id: ' + objectId);
//get the node from the client
updatedObject = client.getNode(objectId);
if (updatedObject) {
if (objectId === CONSTANTS.PROJECT_ROOT_ID) {
self._libraryManager.follow();
}
currentChildren = updatedObject.getChildrenIds();
//check what state the object is in according to the local hashmap
if (nodes[objectId].state === stateLoading) {
//if the object is in "loading" state, meaning we were waiting for it
//render it's real data
metaTypeInfo = self.getMetaInfo(updatedObject);
//specify the icon for the treenode
objType = getNodeClass(updatedObject, metaTypeInfo.isMetaNode);
//create the node's descriptor for the tree-browser widget
nodeDescriptor = {
name: updatedObject.getFullyQualifiedName(),
hasChildren: currentChildren.length > 0,
class: objType,
icon: self.getIcon(updatedObject),
isConnection: updatedObject.isConnection(),
isAbstract: updatedObject.isAbstract(),
isLibrary: updatedObject.isLibraryRoot() || updatedObject.isLibraryElement(),
isLibraryRoot: updatedObject.isLibraryRoot(),
libraryInfo: getLibraryInfo(updatedObject),
isMetaNode: metaTypeInfo.isMetaNode,
metaType: metaTypeInfo.name
};
//update the node's representation in the tree
treeBrowser.updateNode(nodes[objectId].treeNode, nodeDescriptor);
//update the object's children list in the local hashmap
nodes[objectId].children = currentChildren;
//finally update the object's state showing loaded
nodes[objectId].state = stateLoaded;
} else {
//object is already loaded here, let's see what changed in it
//specify the icon for the treenode
metaTypeInfo = self.getMetaInfo(updatedObject);
objType = getNodeClass(updatedObject, metaTypeInfo.isMetaNode);
//create the node's descriptor for the treebrowser widget
nodeDescriptor = {
name: updatedObject.getFullyQualifiedName(),
hasChildren: currentChildren.length > 0,
class: objType,
icon: self.getIcon(updatedObject),
isConnection: updatedObject.isConnection(),
isAbstract: updatedObject.isAbstract(),
isLibrary: updatedObject.isLibraryRoot() || updatedObject.isLibraryElement(),
isLibraryRoot: updatedObject.isLibraryRoot(),
libraryInfo: getLibraryInfo(updatedObject),
isMetaNode: metaTypeInfo.isMetaNode,
metaType: metaTypeInfo.name
};
oldChildren = nodes[objectId].children;
//the concrete child deletion is important only if the node is open in the tree
if (treeBrowser.isExpanded(nodes[objectId].treeNode)) {
nodeDescriptor.icon = self.getIcon(updatedObject, true);
//figure out what are the deleted children's IDs
childrenDeleted = _.difference(oldChildren, currentChildren);
//removes all the (nested)childrendIDs from the local hashmap accounting
// the currently opened nodes's info
deleteNodeAndChildrenFromLocalHash = function (childNodeId) {
var xx;
//if the given node is in this hashmap itself,
// go forward with its children's ID recursively
if (nodes[childNodeId]) {
for (xx = 0; xx < nodes[childNodeId].children.length; xx += 1) {
deleteNodeAndChildrenFromLocalHash(nodes[childNodeId].children[xx]);
}
//finally delete the nodeId itself (if needed)
delete nodes[childNodeId];
//and collect the nodeId from territory removal
if (selfPatterns[childNodeId]) {
removeFromTerritory.push({nodeid: childNodeId});
delete selfPatterns[childNodeId];
}
}
};
for (j = 0; j < childrenDeleted.length; j += 1) {
currentChildId = childrenDeleted[j];
if (nodes[currentChildId]) {
//get all the children that have been removed with this node deletion
//and remove them from this.nodes
//call the node deletion in the tree-browser widget
treeBrowser.deleteNode(nodes[currentChildId].treeNode);
//call the cleanup recursively and mark this node (being closed)
// as non removable (from local hashmap neither from territory)
deleteNodeAndChildrenFromLocalHash(currentChildId);
}
}
}
//the concrete child addition is important only if the node is open in the tree
if (treeBrowser.isExpanded(nodes[objectId].treeNode)) {
//figure out what are the new children's IDs
childrenAdded = _.difference(currentChildren, oldChildren);
//handle added children
for (j = 0; j < childrenAdded.length; j += 1) {
currentChildId = childrenAdded[j];
childNode = client.getNode(currentChildId);
metaTypeInfo = self.getMetaInfo(childNode);
//local variable for the created treenode of the child node (loading or full)
childTreeNode = null;
//check if the node could be retreived from the project
if (childNode) {
//the node was present on the client side, render ist full data
childTreeNode = treeBrowser.createNode(nodes[objectId].treeNode, {
id: currentChildId,
name: childNode.getFullyQualifiedName(),
hasChildren: (childNode.getChildrenIds()).length > 0,
class: getNodeClass(childNode, metaTypeInfo.isMetaNode),
icon: self.getIcon(childNode),
isConnection: childNode.isConnection(),
isAbstract: childNode.isAbstract(),
isLibrary: childNode.isLibraryRoot() || childNode.isLibraryElement(),
isLibraryRoot: childNode.isLibraryRoot(),
libraryInfo: getLibraryInfo(childNode),
isMetaNode: metaTypeInfo.isMetaNode,
metaType: metaTypeInfo.name
});
//store the node's info in the local hashmap
nodes[currentChildId] = {
treeNode: childTreeNode,
children: childNode.getChildrenIds(),
state: stateLoaded
};
} else {
//the node is not present on the client side, render a loading node instead
//create a new node for it in the tree
childTreeNode = treeBrowser.createNode(nodes[objectId].treeNode, {
id: currentChildId,
name: 'Loading...',
hasChildren: false,
class: NODE_PROGRESS_CLASS
});
//store the node's info in the local hashmap
nodes[currentChildId] = {
treeNode: childTreeNode,
children: [],
state: stateLoading
};
}
}
}
//update the object's children list in the local hashmap
nodes[objectId].children = currentChildren;
//update the node's representation in the tree
treeBrowser.updateNode(nodes[objectId].treeNode, nodeDescriptor);
//finally update the object's state showing loaded
nodes[objectId].state = stateLoaded;
// When there is no more children of the current node, remove it from the territory
// if it was there and it is not the root node.
if (objectId !== CONSTANTS.PROJECT_ROOT_ID && selfPatterns[objectId] &&
currentChildren.length === 0) {
removeFromTerritory.push({nodeid: objectId});
delete selfPatterns[objectId];
}
//if there is anythign to remove from the territory, do so
if (removeFromTerritory.length > 0) {
client.updateTerritory(selfId, selfPatterns);
}
}
}
}
}
//ENDOF : HANDLE UPDATE
};
this._eventCallback = function (events) {
var i,
changesMade = false,
len = events.length;
for (i = 0; i < len; i += 1) {
if (events[i].etype === 'complete') {
// Do nothing..
} else if (events[i].etype === 'update') {
refresh('update', events[i].eid);
changesMade = true;
} else if (events[i].etype === 'load') {
refresh('insert', events[i].eid);
changesMade = true;
} else if (events[i].etype === 'unload') {
refresh('unload', events[i].eid);
changesMade = true;
} else {
logger.debug('unknown event type \'' + events[i].etype + '\' received');
}
}
if (changesMade) {
treeBrowser.applyFilters();
}
};
this.locateNode = function (nodeId, isActiveNode) {
var parentId = nodeId,
treeNode;
while (true) {
if (nodes.hasOwnProperty(parentId) && nodes[parentId].treeNode.class !== NODE_PROGRESS_CLASS) {
treeNode = nodes[parentId].treeNode;
treeNode.tree.activateKey(treeNode.key);
treeBrowser._deselectSelectedNodes();
nodes[parentId].treeNode.setSelected(true);
if (parentId === nodeId && !isActiveNode) {
// We reached the node and it was a selected node -> do not expand it.
} else {
treeNode.setExpanded(true);
}
treeNode.tree.setFocus(true);
break;
}
if (!parentId) {
break;
}
parentId = parentId.substring(0, parentId.lastIndexOf('/'));
}
};
this.reLaunch = function () {
logger.debug('reLaunch from client...');
//forget the old territory
client.removeUI(selfId);
treeBrowser.deleteNode(nodes[self._treeRootId].treeNode);
selfPatterns = {};
nodes = {};
initialized = false;
initialize();
};
this.destroy = function () {
$(document).find('link[href*="css/Panels/ObjectBrowser/TreeBrowserControl.css"]').remove();
};
setTimeout(initialize, 250);
}
// Prototypical inheritance
TreeBrowserControl.prototype = Object.create(ObjectBrowserControlBase.prototype);
TreeBrowserControl.prototype.constructor = TreeBrowserControl;
TreeBrowserControl.getDefaultConfig = function () {
return {
treeRoot: '',
filters: {
toggled: {
hideConnections: false,
hideAbstracts: false,
hideLeaves: false,
hideLibraries: false,
hideMetaNodes: false
}
},
byProjectKind: {
treeRoot: {}
},
byProjectId: {
treeRoot: {}
}
};
};
TreeBrowserControl.getComponentId = function () {
return 'GenericUITreeBrowserControl';
};
TreeBrowserControl.prototype._getValidChildrenTypesFlattened = function (nodeId) {
var types = {},
node = this._client.getNode(nodeId),
validChildrenInfo = {},
keys,
id,
title,
validNode;
if (node) {
validChildrenInfo = node.getValidChildrenTypesDetailed();
}
keys = Object.keys(validChildrenInfo || {});
for (id in validChildrenInfo) {
validNode = this._client.getNode(id);
// #1418 Make sure we do not create an instance in a base.
if (validNode && validNode.isInstanceOf(nodeId) === false) {
title = validNode.getFullyQualifiedName();
types[title] = id;
}
}
return types;
};
TreeBrowserControl.prototype._createChild = function (nodeId, childId) {
var client = this._client;
var params = {parentId: nodeId};
params[childId] = {registry: {}};
params[childId].registry[REGISTRY_KEYS.POSITION] = {x: 100, y: 100};
client.createChildren(params);
};
return TreeBrowserControl;
});