webgme
Version:
Web-based Generic Modeling Environment
1,227 lines (1,008 loc) • 85.2 kB
JavaScript
/*globals define, _, WebGMEGlobal, $ */
/*jshint browser: true*/
/**
* @author rkereskenyi / https://github.com/rkereskenyi
*/
define(['js/logger',
'common/util/guid',
'js/Constants',
'js/NodePropertyNames',
'js/RegistryKeys',
'js/Utils/GMEConcepts',
'js/Utils/GMEVisualConcepts',
'js/DragDrop/DragHelper',
'js/Utils/PreferencesHelper',
'js/Controls/AlignMenu'
], function (Logger,
generateGuid,
CONSTANTS,
nodePropertyNames,
REGISTRY_KEYS,
GMEConcepts,
GMEVisualConcepts,
DragHelper,
PreferencesHelper,
AlignMenu) {
'use strict';
var DiagramDesignerWidgetMultiTabMemberListControllerBase,
DEFAULT_DECORATOR = 'ModelDecorator',
WIDGET_NAME = 'DiagramDesigner',
SRC_POINTER_NAME = CONSTANTS.POINTER_SOURCE,
DST_POINTER_NAME = CONSTANTS.POINTER_TARGET,
DRAG_PARAMS_MULTI_TAB_MEMBER_LIST_CONTAINER_ID = 'DRAG_PARAMS_MULTI_TAB_MEMBER_LIST_CONTAINER_ID',
MEMBER_POSITION_REGISTRY_KEY = REGISTRY_KEYS.POSITION;
DiagramDesignerWidgetMultiTabMemberListControllerBase = function (options) {
var loggerName = options.loggerName || 'gme:Panels:ControllerBase:' +
'DiagramDesignerWidgetMultiTabMemberListControllerBase';
this.logger = Logger.create(loggerName, WebGMEGlobal.gmeConfig.client.log);
this._client = options.client;
this.disableConnectionRendering = options.disableConnectionRendering;
//initialize core collections and variables
this._widget = options.widget;
this._alignMenu = new AlignMenu(this._widget.CONSTANTS, {});
if (this._client === undefined) {
this.logger.error('DiagramDesignerWidgetMultiTabMemberListControllerBase\'s client is not specified...');
throw ('DiagramDesignerWidgetMultiTabMemberListControllerBase can not be created');
}
if (this._widget === undefined) {
this.logger.error('DiagramDesignerWidgetMultiTabMemberListControllerBase\'s widget is not specified...');
throw ('DiagramDesignerWidgetMultiTabMemberListControllerBase can not be created');
}
// Initialize maps
this._tabIDMemberListID = {};
this._memberListMembers = {};
this._memberListMemberCoordinates = {};
this._GMEID2ComponentID = {};
this._ComponentID2GMEID = {};
this._GMEID2Subcomponent = {};
this._Subcomponent2GMEID = {};
this._connectionWaitingListByDstGMEID = {};
this._connectionWaitingListBySrcGMEID = {};
this._connectionListBySrcGMEID = {};
this._connectionListByDstGMEID = {};
this._connectionListByID = {};
this._componentIDPartIDMap = {};
this._selectedMemberListMembers = [];
this._delayedConnections = [];
this._delayedConnectionsAsItems = {};
this._selectedMemberListMembersTerritoryPatterns = {};
this._notifyPackage = {};
this._attachDiagramDesignerWidgetEventHandlers();
this.logger.debug('DiagramDesignerWidgetMultiTabMemberListControllerBase ctor finished');
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._attachDiagramDesignerWidgetEventHandlers =
function () {
var self = this;
this._widget.onSelectedTabChanged = function (tabID) {
self._onSelectedTabChanged(tabID);
};
this._widget.onBackgroundDroppableAccept = function (event, dragInfo) {
return self._onBackgroundDroppableAccept(event, dragInfo);
};
this._widget.onBackgroundDrop = function (event, dragInfo, position) {
self._onBackgroundDrop(event, dragInfo, position);
};
this._widget.getDragItems = function (selectedElements) {
return self._getDragItems(selectedElements);
};
this._oGetDragParams = this._widget.getDragParams;
this._widget.getDragParams = function (selectedElements, event) {
return self._getDragParams(selectedElements, event);
};
this._widget.onSelectionDelete = function (idList) {
self._onSelectionDelete(idList);
};
this._widget.onTabTitleChanged = function (tabID, oldValue, newValue) {
self._onTabTitleChanged(tabID, oldValue, newValue);
};
this._widget.onTabsSorted = function (newTabIDOrder) {
self._onTabsSorted(newTabIDOrder);
};
this._widget.onTabDeleteClicked = function (tabID) {
self._onTabDeleteClicked(tabID);
};
this._widget.onTabAddClicked = function () {
self._onTabAddClicked();
};
this._widget.onSelectionChanged = function (selectedIds) {
self._onSelectionChanged(selectedIds);
};
this._widget.onSelectionFillColorChanged = function (selectedElements, color) {
self._onSelectionSetColor(selectedElements, color, REGISTRY_KEYS.COLOR);
};
this._widget.onSelectionBorderColorChanged = function (selectedElements, color) {
self._onSelectionSetColor(selectedElements, color, REGISTRY_KEYS.BORDER_COLOR);
};
this._widget.onSelectionTextColorChanged = function (selectedElements, color) {
self._onSelectionSetColor(selectedElements, color, REGISTRY_KEYS.TEXT_COLOR);
};
this._widget.onConnectionSegmentPointsChange = function (params) {
self._onConnectionSegmentPointsChange(params);
};
this._widget.onRegisterSubcomponent = function (objID, sCompID, metaInfo) {
self._onRegisterSubcomponent(objID, sCompID, metaInfo);
};
this._widget.onUnregisterSubcomponent = function (objID, sCompID) {
self._onUnregisterSubcomponent(objID, sCompID);
};
this._widget.onSelectionAlignMenu = function (selectedIds, mousePos) {
self._onSelectionAlignMenu(selectedIds, mousePos);
};
this._widget.onAlignSelection = function (selectedIds, type) {
self._onAlignSelection(selectedIds, type);
};
this._widget.onDesignerItemsMove = function (repositionDesc) {
self._onDesignerItemsMove(repositionDesc);
};
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype.selectedObjectChanged = function (nodeId) {
var self = this,
pattern;
this.logger.debug('activeObject nodeId "' + nodeId + '"');
//delete everything from model editor
this._widget.clear();
//remove current territory patterns
if (this._territoryId) {
this._client.removeUI(this._territoryId);
if (this._selectedMemberListMembersTerritoryId) {
this._client.removeUI(this._selectedMemberListMembersTerritoryId);
}
this._widget.clearTabs();
}
nodeId = this._validateNodeId(nodeId);
this._memberListContainerID = nodeId;
this._selectedMemberListID = undefined;
if (nodeId || nodeId === CONSTANTS.PROJECT_ROOT_ID) {
//put new node's info into territory rules
pattern = {};
pattern[nodeId] = {children: 0};
this._widget.showProgressbar();
this._territoryId = this._client.addUI(this, function (/*events*/) {
self._processMemberListContainer();
self._widget.hideProgressbar();
});
//update the territory
this._client.updateTerritory(this._territoryId, pattern);
} else {
this._widget.setBackgroundText('No object to display...');
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._validateNodeId = function (nodeId) {
//do not work on ROOT element
if (nodeId === CONSTANTS.PROJECT_ROOT_ID) {
nodeId = undefined;
}
return nodeId;
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._stateActiveObjectChanged = function (model, activeObjectId) {
if (this._memberListContainerID === 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);
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._stateActiveTabChanged = function (model, tabId, opts) {
if (this._tabIDMemberListID &&
this._selectedMemberListID !== this._tabIDMemberListID[tabId] &&
opts.invoker !== this) {
this._widget.selectTab(tabId + '');
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._stateActiveSelectionChanged = function (model, activeSelection, opts) {
var selectedIDs = [],
len = activeSelection ? activeSelection.length : 0;
if (opts.invoker !== this) {
while (len--) {
if (this._GMEID2ComponentID.hasOwnProperty(activeSelection[len])) {
selectedIDs = selectedIDs.concat(this._GMEID2ComponentID[activeSelection[len]]);
}
}
this._widget.select(selectedIDs);
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._attachClientEventListeners = function () {
this._detachClientEventListeners();
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged, this);
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_SELECTION, this._stateActiveSelectionChanged, this);
WebGMEGlobal.State.on('change:' + CONSTANTS.STATE_ACTIVE_TAB, this._stateActiveTabChanged, this);
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._detachClientEventListeners = function () {
WebGMEGlobal.State.off('change:' + CONSTANTS.STATE_ACTIVE_OBJECT, this._stateActiveObjectChanged);
WebGMEGlobal.State.off('change:' + CONSTANTS.STATE_ACTIVE_SELECTION, this._stateActiveSelectionChanged);
WebGMEGlobal.State.off('change:' + CONSTANTS.STATE_ACTIVE_TAB, this._stateActiveTabChanged);
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype.onActivate = function () {
var tabId;
this._attachClientEventListeners();
this._displayToolbarItems();
if (this._tabIDMemberListID && this._selectedMemberListID) {
for (tabId in this._tabIDMemberListID) {
if (this._tabIDMemberListID[tabId] === this._selectedMemberListID) {
WebGMEGlobal.State.registerActiveTab(tabId, {invoker: this});
break;
}
}
}
//setting the active object to the container
if (typeof this._memberListContainerID === 'string') {
WebGMEGlobal.State.registerActiveObject(this._memberListContainerID, {suppressVisualizerFromNode: true});
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype.onDeactivate = function () {
this._detachClientEventListeners();
this._hideToolbarItems();
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._displayToolbarItems = function () {
var i;
if (this._toolbarInitialized === true) {
for (i = 0; i < this._toolbarItems.length; i++) {
this._toolbarItems[i].show();
}
} else {
this._initializeToolbar();
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._hideToolbarItems = function () {
var i;
if (this._toolbarInitialized === true) {
for (i = 0; i < this._toolbarItems.length; i++) {
this._toolbarItems[i].hide();
}
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._removeToolbarItems = function () {
var i;
if (this._toolbarInitialized === true) {
for (i = 0; i < this._toolbarItems.length; i++) {
this._toolbarItems[i].destroy();
}
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._initializeToolbar = function () {
this._toolbarItems = [];
this._toolbarInitialized = true;
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype.setReadOnly = function (/* isReadOnly */) {
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype.destroy = function () {
this._detachClientEventListeners();
this._removeToolbarItems();
this._client.removeUI(this._territoryId);
if (this._selectedMemberListMembersTerritoryId) {
this._client.removeUI(this._selectedMemberListMembersTerritoryId);
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._processMemberListContainer = function () {
var memberListContainerObj = this._client.getNode(this._memberListContainerID),
orderedMemberListInfo,
i,
memberListTabID,
selectedMemberListTabID,
memberListID,
tabTitle,
deleteTab,
renameTab,
j,
gmeID;
this.logger.debug('_processMemberListContainer');
//#1 - clear tabs
this._widget.clearTabs();
this._tabIDMemberListID = {};
this._memberListMembers = {};
this._memberListMemberCoordinates = {};
if (memberListContainerObj) {
//display name of the container
this._displayContainerObjectName();
//#2 - get pointer lists and display a tab for each one
orderedMemberListInfo = this.getOrderedMemberListInfo(memberListContainerObj) || [];
if (orderedMemberListInfo.length > 0) {
this._widget.addMultipleTabsBegin();
for (i = 0; i < orderedMemberListInfo.length; i += 1) {
memberListID = orderedMemberListInfo[i].memberListID;
tabTitle = orderedMemberListInfo[i].title;
deleteTab = orderedMemberListInfo[i].enableDeleteTab && true;
renameTab = orderedMemberListInfo[i].enableRenameTab && true;
//create tab
memberListTabID = this._widget.addTab(tabTitle, deleteTab, renameTab);
this._tabIDMemberListID[memberListTabID] = memberListID;
//get members of this pointer list
this._memberListMembers[memberListID] = memberListContainerObj.getMemberIds(memberListID);
//get member coordinates
this._memberListMemberCoordinates[memberListID] = {};
j = this._memberListMembers[memberListID].length;
while (j--) {
gmeID = this._memberListMembers[memberListID][j];
this._memberListMemberCoordinates[memberListID][gmeID] =
memberListContainerObj.getMemberRegistry(memberListID, gmeID, MEMBER_POSITION_REGISTRY_KEY);
}
//#3 - set selected based on actual selection
//if there is no actual selection, select thr first tab
if (this._selectedMemberListID &&
this._selectedMemberListID === memberListID) {
selectedMemberListTabID = memberListTabID;
}
}
this._widget.addMultipleTabsEnd();
//set tab based on the UI state
if (!selectedMemberListTabID &&
WebGMEGlobal.State.getActiveTab() !== null && WebGMEGlobal.State.getActiveTab() !== undefined &&
WebGMEGlobal.State.getActiveTab() < Object.keys(this._tabIDMemberListID).length) {
selectedMemberListTabID = WebGMEGlobal.State.getActiveTab();
}
if (!selectedMemberListTabID) {
for (selectedMemberListTabID in this._tabIDMemberListID) {
if (this._tabIDMemberListID.hasOwnProperty(selectedMemberListTabID)) {
break;
}
}
}
this._widget.selectTab(selectedMemberListTabID);
this._updateSelectedMemberListMembersTerritoryPatterns();
} else {
this._widget.clear();
this._displayContainerObjectName();
this.displayNoTabMessage();
}
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._updateSelectedMemberListMembersTerritoryPatterns =
function () {
var currentlyDisplayedMembers = (this._selectedMemberListMembers || []).slice(0),
actualMembers = (this._memberListMembers[this._selectedMemberListID] || []).slice(0),
diff,
len,
territoryChanged = false,
territoryId = this._selectedMemberListMembersTerritoryId,
territoryPatterns = this._selectedMemberListMembersTerritoryPatterns,
client = this._client,
desc,
obj;
//let's see who has been deleted
diff = _.difference(currentlyDisplayedMembers, actualMembers);
len = diff.length;
while (len--) {
delete territoryPatterns[diff[len]];
territoryChanged = true;
}
//let's see who has been added
diff = _.difference(actualMembers, currentlyDisplayedMembers);
len = diff.length;
while (len--) {
territoryPatterns[diff[len]] = {children: 0};
territoryChanged = true;
}
//let's update the one that has not been changed but their position might have
diff = _.intersection(actualMembers, currentlyDisplayedMembers);
len = diff.length;
this._widget.beginUpdate();
while (len--) {
//only items are interesting since only those position is stored in the container's set's registry
//connections are interesting too since their color or segment points could have changed
// which is set specific
if (this.disableConnectionRendering || GMEConcepts.isConnection(diff[len]) === false) {
this._onUpdate(diff[len], {isConnection: false});
} else {
if (this._delayedConnectionsAsItems[diff[len]]) {
//delayed connection, rendered as an item
this._onUpdate(diff[len], {isConnection: false});
} else {
//real connection
desc = {isConnection: true};
obj = client.getNode(diff[len]);
if (obj) {
desc.srcID = obj.getPointer(SRC_POINTER_NAME).to;
desc.dstID = obj.getPointer(DST_POINTER_NAME).to;
this._onUpdate(diff[len], desc);
}
}
}
}
this._widget.endUpdate();
//save current list of members
this._selectedMemberListMembers = actualMembers;
if (territoryChanged) {
setTimeout(function () {
client.updateTerritory(territoryId, territoryPatterns);
}, 10);
}
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype.getOrderedMemberListInfo = function (memberListContainerObject) {
//result should be an array of objects:
/*{
'memberListID': setNames[len],
'title': setNames[len],
'enableDeleteTab': true,
'enableRenameTab': true
};
*/
this.logger.warn('DiagramDesignerWidgetMultiTabMemberListControllerBase.getOrderedMemberListInfo(memberList' +
'ContainerObject) is not overridden for object "' + memberListContainerObject + '", returning default...');
return undefined;
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype.getMemberListSetsRegistryKey = function () {
this.logger.warn('DiagramDesignerWidgetMultiTabMemberListControllerBase.getMemberListSetsRegistryKey is not ' +
'overridden, returning default value...');
return undefined;
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype.getMemberListSetsRegistry = function (/*nodeId*/) {
this.logger.warn('DiagramDesignerWidgetMultiTabMemberListControllerBase.getMemberListSetsRegistry is not ' +
'overridden, returning default value...');
return undefined;
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._onSelectedTabChanged = function (tabID) {
if (this._tabIDMemberListID[tabID] && this._selectedMemberListID !== this._tabIDMemberListID[tabID]) {
this._selectedMemberListID = this._tabIDMemberListID[tabID];
this.logger.debug('_selectedMemberListID changed to : ' + this._selectedMemberListID);
this._initializeSelectedMemberList();
}
// Always register the tab to the state (needed if state triggers a tab that does not exist for this object)
WebGMEGlobal.State.registerActiveTab(tabID, {invoker: this});
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._getDragParams = function (selectedElements,
event) {
var oParams = this._oGetDragParams.call(this._widget, selectedElements, event),
params = {positions: {}},
i;
params[DRAG_PARAMS_MULTI_TAB_MEMBER_LIST_CONTAINER_ID] = this._getDragParamsDataID();
for (i in oParams.positions) {
if (oParams.positions.hasOwnProperty(i)) {
params.positions[this._ComponentID2GMEID[i]] = oParams.positions[i];
}
}
return params;
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._getDragItems = function (selectedElements) {
var res = [],
i = selectedElements.length;
while (i--) {
res.push(this._ComponentID2GMEID[selectedElements[i]]);
}
return res;
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._getDragParamsDataID = function () {
return this._memberListContainerID + this._selectedMemberListID;
};
/**********************************************************/
/* HANDLE OBJECT DRAG & DROP ACCEPTANCE */
/**********************************************************/
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._onBackgroundDroppableAccept = function (event,
dragInfo) {
var gmeIDList = DragHelper.getDragItems(dragInfo),
params = DragHelper.getDragParams(dragInfo),
dragEffects = DragHelper.getDragEffects(dragInfo),
i,
accept = false;
// Ensure that there is a selected memberlist (with members initialized) to add the dragged elements to.
if (this._selectedMemberListID && this._memberListMembers[this._selectedMemberListID]) {
//accept is self reposition OR
//dragging from somewhere else and the items are not on the sheet yet
if (params &&
params.hasOwnProperty(DRAG_PARAMS_MULTI_TAB_MEMBER_LIST_CONTAINER_ID) &&
params[DRAG_PARAMS_MULTI_TAB_MEMBER_LIST_CONTAINER_ID] === this._getDragParamsDataID()) {
//reposition on the same sheet
accept = true;
} else {
//dragging from somewhere else
if (dragEffects.length === 1 &&
dragEffects[0] === DragHelper.DRAG_EFFECTS.DRAG_CREATE_INSTANCE) {
//dragging from PartBrowser
accept = false;
} else {
//return true if none of the dragged items are on the sheet already
//and do not try to add the container item itself as member of the list
if (gmeIDList.length > 0) {
accept = true;
for (i = 0; i < gmeIDList.length; i += 1) {
if (gmeIDList[i] === this._memberListContainerID) {
// TODO: Is this really OK??
//accept = false;
//break;
} else if (this._memberListMembers[this._selectedMemberListID]
.indexOf(gmeIDList[i]) !== -1) {
accept = false;
break;
}
}
}
}
}
}
return accept;
};
/**********************************************************/
/* END OF --- HANDLE OBJECT DRAG & DROP ACCEPTANCE */
/**********************************************************/
/**********************************************************/
/* HANDLE OBJECT DRAG & DROP TO SHEET */
/**********************************************************/
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._onBackgroundDrop = function (event, dragInfo,
position) {
var client = this._client,
memberListContainerID = this._memberListContainerID,
memberListToAddTo = this._selectedMemberListID,
gmeIDList = DragHelper.getDragItems(dragInfo),
params = DragHelper.getDragParams(dragInfo),
i,
selectedIDs = [],
componentID,
posX,
posY;
//check to see it self drop and reposition or dropping from somewhere else
if (params &&
params.hasOwnProperty(DRAG_PARAMS_MULTI_TAB_MEMBER_LIST_CONTAINER_ID) &&
params[DRAG_PARAMS_MULTI_TAB_MEMBER_LIST_CONTAINER_ID] === this._getDragParamsDataID()) {
//params.position holds the old coordinates of the items being dragged
//update UI
client.startTransaction();
this._widget.beginUpdate();
for (i in params.positions) {
if (params.positions.hasOwnProperty(i)) {
posX = position.x + params.positions[i].x;
posY = position.y + params.positions[i].y;
client.setMemberRegistry(memberListContainerID,
i,
memberListToAddTo,
MEMBER_POSITION_REGISTRY_KEY,
{
x: posX,
y: posY
});
componentID = this._GMEID2ComponentID[i][0];
selectedIDs.push(componentID);
this._widget.updateDesignerItem(componentID, {position: {x: posX, y: posY}});
}
}
this._widget.endUpdate();
this._widget.select(selectedIDs);
client.completeTransaction();
} else {
client.startTransaction();
//if the item is not currently in the currently selected member list, add it
if (gmeIDList.length > 0) {
for (i = 0; i < gmeIDList.length; i += 1) {
componentID = gmeIDList[i];
if (this._memberListMembers[memberListToAddTo].indexOf(componentID) === -1) {
posX = position.x;
posY = position.y;
//when dragging between ASPECT sheets, read position from dragParams
if (params &&
params.positions &&
params.positions[componentID]) {
posX += params.positions[componentID].x;
posY += params.positions[componentID].y;
} else {
position.x += 20;
position.y += 20;
}
client.addMember(memberListContainerID, componentID, memberListToAddTo);
client.setMemberRegistry(memberListContainerID,
componentID,
memberListToAddTo,
MEMBER_POSITION_REGISTRY_KEY,
{
x: posX,
y: posY
});
}
}
}
client.completeTransaction();
}
};
/**********************************************************/
/* END OF --- HANDLE OBJECT DRAG & DROP TO SHEET */
/**********************************************************/
/*************************************************************/
/* HANDLE OBJECT / CONNECTION DELETION IN THE ASPECT ASPECT */
/*************************************************************/
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._onSelectionDelete = function (idList) {
var client = this._client,
memberListContainerID = this._memberListContainerID,
memberListToRemoveFrom = this._selectedMemberListID,
len,
gmeID;
client.startTransaction();
len = idList.length;
while (len--) {
gmeID = this._ComponentID2GMEID[idList[len]];
client.removeMember(memberListContainerID, gmeID, memberListToRemoveFrom);
}
client.completeTransaction();
};
/************************************************************************/
/* END OF --- HANDLE OBJECT / CONNECTION DELETION IN THE ASPECT ASPECT */
/************************************************************************/
//initialize the selected memberlist's members
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._initializeSelectedMemberList = function () {
var len,
self = this;
this.logger.debug('_initializeSelectedMemberList');
//delete everything from model editor
this._widget.clear();
//display name
this._displayContainerObjectName();
//clean up local hash map
this._GMEID2ComponentID = {};
this._ComponentID2GMEID = {};
this._GMEID2Subcomponent = {};
this._Subcomponent2GMEID = {};
this._connectionWaitingListByDstGMEID = {};
this._connectionWaitingListBySrcGMEID = {};
this._connectionListBySrcGMEID = {};
this._connectionListByDstGMEID = {};
this._connectionListByID = {};
this._componentIDPartIDMap = {};
this._selectedMemberListMembers = [];
this._delayedConnections = [];
this._delayedConnectionsAsItems = {};
//remove current territory patterns
if (this._selectedMemberListMembersTerritoryId) {
this._client.removeUI(this._selectedMemberListMembersTerritoryId);
}
this._selectedMemberListMembersTerritoryPatterns = {};
if (this._selectedMemberListID && this._memberListMembers[this._selectedMemberListID]) {
len = this._memberListMembers[this._selectedMemberListID].length;
if (len > 0) {
this._widget.showProgressbar();
}
while (len--) {
this._selectedMemberListMembers.push(this._memberListMembers[this._selectedMemberListID][len]);
this._selectedMemberListMembersTerritoryPatterns[this._memberListMembers[
this._selectedMemberListID][len]] = {children: 0};
}
}
this._selectedMemberListMembersTerritoryId = this._client.addUI(this, function (events) {
self._memberListTerritoryCallback(events);
});
this._client.updateTerritory(this._selectedMemberListMembersTerritoryId,
this._selectedMemberListMembersTerritoryPatterns);
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._memberListTerritoryCallback = function (events) {
var decoratorsToDownload = [DEFAULT_DECORATOR],
len = events.length,
obj,
objDecorator,
client = this._client,
self = this;
while (len--) {
if ((events[len].etype === CONSTANTS.TERRITORY_EVENT_LOAD) ||
(events[len].etype === CONSTANTS.TERRITORY_EVENT_UPDATE)) {
obj = client.getNode(events[len].eid);
events[len].desc = {
isConnection: !this.disableConnectionRendering && GMEConcepts.isConnection(events[len].eid)
};
if (obj) {
//if it is a connection find src and dst and do not care about decorator
if (events[len].desc.isConnection === true) {
events[len].desc.srcID = obj.getPointer(SRC_POINTER_NAME).to;
events[len].desc.dstID = obj.getPointer(DST_POINTER_NAME).to;
} else {
objDecorator = obj.getRegistry(REGISTRY_KEYS.DECORATOR);
if (!objDecorator ||
objDecorator === '') {
objDecorator = DEFAULT_DECORATOR;
}
if (decoratorsToDownload.indexOf(objDecorator) === -1) {
decoratorsToDownload.pushUnique(objDecorator);
}
events[len].desc.decorator = objDecorator;
}
}
}
}
client.decoratorManager.download(decoratorsToDownload, WIDGET_NAME, function () {
self._dispatchEvents(events);
});
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._dispatchEvents = function (events) {
var i,
e,
territoryChanged = false,
j,
ce,
orderedItemEvents = [],
orderedConnectionEvents = [],
unloadEvents,
srcGMEID,
dstGMEID,
srcConnIdx,
dstConnIdx,
insertIdxAfter,
insertIdxBefore,
MAX_VAL = 999999999,
depSrcConnIdx = MAX_VAL,
depDstConnIdx = MAX_VAL;
this.logger.debug('_dispatchEvents "' + events.length + '" items: ' + JSON.stringify(events));
this._widget.beginUpdate();
//first call the updates of the decorators so they can pu out any port they use
j = Object.keys(this._GMEID2ComponentID || {});
for (i = 0; i < j.length; i += 1) {
if (this._widget.items[this._GMEID2ComponentID[j[i]]] &&
this._widget.items[this._GMEID2ComponentID[j[i]]]._decoratorInstance) {
this._widget.items[this._GMEID2ComponentID[j[i]]]._decoratorInstance.update();
}
}
//decorators have been updated we can move on
/********** ORDER EVENTS BASED ON DEPENDENCY ************/
/** 1: items first, no dependency **/
/** 2: connections second, dependency if a connection is connected to an other connection **/
if (this._delayedConnections && this._delayedConnections.length > 0) {
//if there are saved connections, first check if any UPDATE or UNLOAD event is about them
//if so, remove/update those information from delayed connections list
i = events.length;
while (i--) {
e = events[i];
if (e.etype === CONSTANTS.TERRITORY_EVENT_UNLOAD) {
//if it's an unload, remove the delayed connection entry
j = this._delayedConnections.length;
while (j--) {
if (this._delayedConnections[j].ID === e.eid) {
this.logger.debug('Removing ' + e.eid + ' from delayed connections...');
this._delayedConnections.splice(j, 1);
//TODO: find a better solution for removing connection, if
// visualized as a box
this._widget.deleteComponent(this._delayedConnectionsAsItems[e.eid]);
delete this._delayedConnectionsAsItems[e.eid];
}
}
} else if (e.etype === CONSTANTS.TERRITORY_EVENT_UPDATE &&
e.desc.isConnection === true) {
//if it is an UPDATE, update the SRC and DST info
j = this._delayedConnections.length;
while (j--) {
if (this._delayedConnections[j].ID === e.eid) {
this.logger.debug('Updating ' + e.eid + ' in delayed connections...');
this._delayedConnections[j].desc.srcID = e.desc.srcID;
this._delayedConnections[j].desc.dstID = e.desc.dstID;
//remove this guy from the event list since it will be added to orderedConnectionEvents list
events.splice(i, 1);
}
}
}
}
for (i = 0; i < this._delayedConnections.length; i += 1) {
if (this._delayedConnections[i].desc.src && this._delayedConnections[i].desc.dst) {
//otherwise there is no possible way for this box to became a connection...
orderedConnectionEvents.push({
etype: CONSTANTS.TERRITORY_EVENT_LOAD,
eid: this._delayedConnections[i].ID,
desc: this._delayedConnections[i].desc
});
//TODO: connection as box
//remove the box that represents this connections
this._widget.deleteComponent(this._delayedConnectionsAsItems[this._delayedConnections[i].ID]);
delete this._delayedConnectionsAsItems[this._delayedConnections[i].ID];
}
}
}
this._delayedConnections = [];
this._delayedConnectionsAsItems = {};
unloadEvents = [];
i = events.length;
while (i--) {
e = events[i];
if (e.etype !== CONSTANTS.TERRITORY_EVENT_COMPLETE && e.etype !== CONSTANTS.TERRITORY_EVENT_INCOMPLETE) {
if (e.etype === CONSTANTS.TERRITORY_EVENT_UNLOAD) {
unloadEvents.push(e);
} else if (e.desc.isConnection === false) {
orderedItemEvents.push(e);
} else if (e.desc.isConnection === true) {
srcGMEID = e.desc.srcID;
dstGMEID = e.desc.dstID;
//check to see if SRC and DST is another connection
//if so, put this guy AFTER them
srcConnIdx = -1;
dstConnIdx = -1;
j = orderedConnectionEvents.length;
while (j--) {
ce = orderedConnectionEvents[j];
if (ce.id === srcGMEID) {
srcConnIdx = j;
} else if (ce.id === dstGMEID) {
dstConnIdx = j;
}
if (srcConnIdx !== -1 && dstConnIdx !== -1) {
break;
}
}
insertIdxAfter = Math.max(srcConnIdx, dstConnIdx);
//check to see if this guy is a DEPENDENT of any already processed CONNECTION
//insert BEFORE THEM
j = orderedConnectionEvents.length;
while (j--) {
ce = orderedConnectionEvents[j];
if (e.eid === ce.desc.srcID) {
depSrcConnIdx = j;
} else if (e.eid === ce.desc.dstID) {
depDstConnIdx = j;
}
if (depSrcConnIdx !== MAX_VAL && depDstConnIdx !== MAX_VAL) {
break;
}
}
insertIdxBefore = Math.min(depSrcConnIdx, depDstConnIdx);
if (insertIdxAfter === -1 && insertIdxBefore === MAX_VAL) {
orderedConnectionEvents.push(e);
} else {
if (insertIdxAfter !== -1 &&
insertIdxBefore === MAX_VAL) {
orderedConnectionEvents.splice(insertIdxAfter + 1, 0, e);
} else if (insertIdxAfter === -1 &&
insertIdxBefore !== MAX_VAL) {
orderedConnectionEvents.splice(insertIdxBefore, 0, e);
} else if (insertIdxAfter !== -1 &&
insertIdxBefore !== MAX_VAL) {
orderedConnectionEvents.splice(insertIdxBefore, 0, e);
}
}
}
}
}
this._notifyPackage = {};
//item insert/update/unload & connection unload
events = unloadEvents.concat(orderedItemEvents);
for (i = 0; i < events.length; i += 1) {
e = events[i];
switch (e.etype) {
case CONSTANTS.TERRITORY_EVENT_LOAD:
territoryChanged = this._onLoad(e.eid, e.desc) || territoryChanged;
break;
case CONSTANTS.TERRITORY_EVENT_UPDATE:
this._onUpdate(e.eid, e.desc);
break;
case CONSTANTS.TERRITORY_EVENT_UNLOAD:
territoryChanged = this._onUnload(e.eid) || territoryChanged;
break;
default:
break;
}
}
this._handleDecoratorNotification();
//connections
events = orderedConnectionEvents;
for (i = 0; i < events.length; i += 1) {
e = events[i];
switch (e.etype) {
case CONSTANTS.TERRITORY_EVENT_LOAD:
this._onLoad(e.eid, e.desc);
break;
case CONSTANTS.TERRITORY_EVENT_UPDATE:
this._onUpdate(e.eid, e.desc);
break;
case CONSTANTS.TERRITORY_EVENT_UNLOAD:
this._onUnload(e.eid);
break;
default:
break;
}
}
this._widget.endUpdate();
this._widget.hideProgressbar();
//update the territory
if (territoryChanged) {
this.logger.debug('Updating territory with ruleset from decorators: ' + JSON.stringify(this._selfPatterns));
this._client.updateTerritory(this._selectedMemberListMembersTerritoryId,
this._selectedMemberListMembersTerritoryPatterns);
}
this.logger.debug('_dispatchEvents "' + events.length + '" items - DONE');
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._updateDecoratorTerritoryQuery = function (decorator, doDelete) {
var query,
entry,
territoryPatterns = this._selectedMemberListMembersTerritoryPatterns,
territoryChanged = false;
if (decorator) {
query = decorator.getTerritoryQuery();
if (query) {
for (entry in query) {
if (query.hasOwnProperty(entry)) {
if (doDelete) {
delete territoryPatterns[entry];
} else {
territoryPatterns[entry] = query[entry];
}
territoryChanged = true;
}
}
}
}
return territoryChanged;
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._getItemDecorator = function (decorator) {
var result;
result = this._client.decoratorManager.getDecoratorForWidget(decorator, WIDGET_NAME);
if (!result) {
result = this._client.decoratorManager.getDecoratorForWidget(DEFAULT_DECORATOR, WIDGET_NAME);
}
return result;
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._getAllSourceDestinationPairsForConnection = function (GMESrcId,
GMEDstId) {
var sources = [],
destinations = [],
i;
if (this._GMEID2ComponentID.hasOwnProperty(GMESrcId)) {
//src is a DesignerItem
i = this._GMEID2ComponentID[GMESrcId].length;
while (i--) {
sources.push({
objId: this._GMEID2ComponentID[GMESrcId][i],
subCompId: undefined
});
}
} else {
//src is not a DesignerItem
//must be a sub_components somewhere, find the corresponding designerItem
if (this._GMEID2Subcomponent && this._GMEID2Subcomponent.hasOwnProperty(GMESrcId)) {
for (i in this._GMEID2Subcomponent[GMESrcId]) {
if (this._GMEID2Subcomponent[GMESrcId].hasOwnProperty(i)) {
sources.push({
objId: i,
subCompId: this._GMEID2Subcomponent[GMESrcId][i]
});
}
}
}
}
if (this._GMEID2ComponentID.hasOwnProperty(GMEDstId)) {
i = this._GMEID2ComponentID[GMEDstId].length;
while (i--) {
destinations.push({
objId: this._GMEID2ComponentID[GMEDstId][i],
subCompId: undefined
});
}
} else {
//dst is not a DesignerItem
//must be a sub_components somewhere, find the corresponding designerItem
if (this._GMEID2Subcomponent && this._GMEID2Subcomponent.hasOwnProperty(GMEDstId)) {
for (i in this._GMEID2Subcomponent[GMEDstId]) {
if (this._GMEID2Subcomponent[GMEDstId].hasOwnProperty(i)) {
destinations.push({
objId: i,
subCompId: this._GMEID2Subcomponent[GMEDstId][i]
});
}
}
}
}
return {
sources: sources,
destinations: destinations
};
};
DiagramDesignerWidgetMultiTabMemberListControllerBase.prototype._onLoad = function (gmeID, desc) {
var uiComponent,
decClass,
objDesc = {},
sources = [],
destinations = [],
territoryChanged = false,
srcDst,
k,
l,
connVisualProperties,
alreadySaved,
len;
// component loaded
// we are interested in the load of member items and their custom territory involvement
// check if the decorator is available before drawing
if (this._selectedMemberListMembers.indexOf(gmeID) !== -1 && desc.decorator) {
if (desc.isConnection === false) {
decClass = this._getItemDecorator(desc.decorator);
objDesc.decoratorClass = decClass;
objDesc.control = this;
objDesc.metaInfo = {};
objDesc.metaInfo[CONSTANTS.GME_ID] = gmeID;
objDesc.position = {x: 100, y: 100};
if (this._memberListMemberCoordinates[this._selectedMemberListID] &&
this._memberListMemberCoordinates[this._selectedMemberListID][gmeID]) {
objDesc.position.x = this._memberListMemberCoordinates[this._selectedMemberListID][gmeID].x;
objDesc.position.y = this._memberListMemberCoordinates[this._selectedMemberListID][gmeID].y;
}
objDesc.decoratorParams = {};
if (desc.decoratorParams) {
_.extend(objDesc.decoratorParams, desc.decoratorParams);
}
//registry preferences