|
|
@ -108,7 +108,7 @@ var SelectionMixin = { |
|
|
|
_getNodeAt : function (pointer) { |
|
|
|
// we first check if this is an navigation controls element
|
|
|
|
var positionObject = this._pointerToPositionObject(pointer); |
|
|
|
overlappingNodes = this._getAllNodesOverlappingWith(positionObject); |
|
|
|
var overlappingNodes = this._getAllNodesOverlappingWith(positionObject); |
|
|
|
|
|
|
|
// if there are overlapping nodes, select the last one, this is the
|
|
|
|
// one which is drawn on top of the others
|
|
|
@ -121,6 +121,36 @@ var SelectionMixin = { |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* retrieve all edges overlapping with given object, selector is around center |
|
|
|
* @param {Object} object An object with parameters left, top, right, bottom |
|
|
|
* @return {Number[]} An array with id's of the overlapping nodes |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_getEdgesOverlappingWith : function (object, overlappingEdges) { |
|
|
|
var edges = this.edges; |
|
|
|
for (var edgeId in edges) { |
|
|
|
if (edges.hasOwnProperty(edgeId)) { |
|
|
|
if (edges[edgeId].isOverlappingWith(object)) { |
|
|
|
overlappingEdges.push(edgeId); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* retrieve all nodes overlapping with given object |
|
|
|
* @param {Object} object An object with parameters left, top, right, bottom |
|
|
|
* @return {Number[]} An array with id's of the overlapping nodes |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_getAllEdgesOverlappingWith : function (object) { |
|
|
|
var overlappingEdges = []; |
|
|
|
this._doInAllActiveSectors("_getEdgesOverlappingWith",object,overlappingEdges); |
|
|
|
return overlappingEdges; |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* Place holder. To implement change the _getNodeAt to a _getObjectAt. Have the _getObjectAt call |
|
|
|
* _getNodeAt and _getEdgesAt, then priortize the selection to user preferences. |
|
|
@ -130,18 +160,25 @@ var SelectionMixin = { |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_getEdgeAt : function(pointer) { |
|
|
|
return null; |
|
|
|
var positionObject = this._pointerToPositionObject(pointer); |
|
|
|
var overlappingEdges = this._getAllEdgesOverlappingWith(positionObject); |
|
|
|
|
|
|
|
if (overlappingEdges.length > 0) { |
|
|
|
return this.edges[overlappingEdges[overlappingEdges.length - 1]]; |
|
|
|
} |
|
|
|
else { |
|
|
|
return null; |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Add object to the selection array. The this.selection id array may not be needed. |
|
|
|
* Add object to the selection array. |
|
|
|
* |
|
|
|
* @param obj |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_addToSelection : function(obj) { |
|
|
|
this.selection.push(obj.id); |
|
|
|
this.selectionObj[obj.id] = obj; |
|
|
|
}, |
|
|
|
|
|
|
@ -149,16 +186,10 @@ var SelectionMixin = { |
|
|
|
/** |
|
|
|
* Remove a single option from selection. |
|
|
|
* |
|
|
|
* @param obj |
|
|
|
* @param {Object} obj |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_removeFromSelection : function(obj) { |
|
|
|
for (var i = 0; i < this.selection.length; i++) { |
|
|
|
if (obj.id == this.selection[i]) { |
|
|
|
this.selection.splice(i,1); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
delete this.selectionObj[obj.id]; |
|
|
|
}, |
|
|
|
|
|
|
@ -174,10 +205,9 @@ var SelectionMixin = { |
|
|
|
doNotTrigger = false; |
|
|
|
} |
|
|
|
|
|
|
|
this.selection = []; |
|
|
|
for (var objId in this.selectionObj) { |
|
|
|
if (this.selectionObj.hasOwnProperty(objId)) { |
|
|
|
this.selectionObj[objId].unselect(); |
|
|
|
for (var objectId in this.selectionObj) { |
|
|
|
if (this.selectionObj.hasOwnProperty(objectId)) { |
|
|
|
this.selectionObj[objectId].unselect(); |
|
|
|
} |
|
|
|
} |
|
|
|
this.selectionObj = {}; |
|
|
@ -189,6 +219,89 @@ var SelectionMixin = { |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* Unselect all clusters. The selectionObj is useful for this. |
|
|
|
* |
|
|
|
* @param {Boolean} [doNotTrigger] | ignore trigger |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_unselectClusters : function(doNotTrigger) { |
|
|
|
if (doNotTrigger === undefined) { |
|
|
|
doNotTrigger = false; |
|
|
|
} |
|
|
|
|
|
|
|
for (var objectId in this.selectionObj) { |
|
|
|
if (this.selectionObj.hasOwnProperty(objectId)) { |
|
|
|
if (this.selectionObj[objectId] instanceof Node) { |
|
|
|
if (this.selectionObj[objectId].clusterSize > 1) { |
|
|
|
this.selectionObj[objectId].unselect(); |
|
|
|
this._removeFromSelection(this.selectionObj[objectId]); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (doNotTrigger == false) { |
|
|
|
this._trigger('select', { |
|
|
|
nodes: this.getSelection() |
|
|
|
}); |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* return the number of selected nodes |
|
|
|
* |
|
|
|
* @returns {number} |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_getSelectedNodeCount : function() { |
|
|
|
var count = 0; |
|
|
|
for (var objectId in this.selectionObj) { |
|
|
|
if (this.selectionObj.hasOwnProperty(objectId)) { |
|
|
|
if (this.selectionObj[objectId] instanceof Node) { |
|
|
|
count += 1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return count; |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* return the number of selected edges |
|
|
|
* |
|
|
|
* @returns {number} |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_getSelectedEdgeCount : function() { |
|
|
|
var count = 0; |
|
|
|
for (var objectId in this.selectionObj) { |
|
|
|
if (this.selectionObj.hasOwnProperty(objectId)) { |
|
|
|
if (this.selectionObj[objectId] instanceof Edge) { |
|
|
|
count += 1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return count; |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* return the number of selected objects. |
|
|
|
* |
|
|
|
* @returns {number} |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_getSelectedObjectCount : function() { |
|
|
|
var count = 0; |
|
|
|
for (var objectId in this.selectionObj) { |
|
|
|
if (this.selectionObj.hasOwnProperty(objectId)) { |
|
|
|
count += 1; |
|
|
|
} |
|
|
|
} |
|
|
|
return count; |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* Check if anything is selected |
|
|
@ -197,41 +310,93 @@ var SelectionMixin = { |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_selectionIsEmpty : function() { |
|
|
|
if (this.selection.length == 0) { |
|
|
|
return true; |
|
|
|
for(var objectId in this.selectionObj) { |
|
|
|
if(this.selectionObj.hasOwnProperty(objectId)) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
return false; |
|
|
|
return true; |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* check if one of the selected nodes is a cluster. |
|
|
|
* |
|
|
|
* @returns {boolean} |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_clusterInSelection : function() { |
|
|
|
for(var objectId in this.selectionObj) { |
|
|
|
if(this.selectionObj.hasOwnProperty(objectId)) { |
|
|
|
if (this.selectionObj[objectId] instanceof Node) { |
|
|
|
if (this.selectionObj[objectId].clusterSize > 1) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* select the edges connected to the node that is being selected |
|
|
|
* |
|
|
|
* @param {Node} node |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_selectConnectedEdges : function(node) { |
|
|
|
for (var i = 0; i < node.dynamicEdges.length; i++) { |
|
|
|
var edge = node.dynamicEdges[i]; |
|
|
|
edge.select(); |
|
|
|
this._addToSelection(edge); |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* unselect the edges connected to the node that is being selected |
|
|
|
* |
|
|
|
* @param {Node} node |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_unselectConnectedEdges : function(node) { |
|
|
|
for (var i = 0; i < node.dynamicEdges.length; i++) { |
|
|
|
var edge = node.dynamicEdges[i]; |
|
|
|
edge.unselect(); |
|
|
|
this._removeFromSelection(edge); |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* This is called when someone clicks on a node. either select or deselect it. |
|
|
|
* If there is an existing selection and we don't want to append to it, clear the existing selection |
|
|
|
* |
|
|
|
* @param {Node} node |
|
|
|
* @param {Node || Edge} object |
|
|
|
* @param {Boolean} append |
|
|
|
* @param {Boolean} [doNotTrigger] | ignore trigger |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_selectNode : function(node, append, doNotTrigger) { |
|
|
|
_selectObject : function(object, append, doNotTrigger) { |
|
|
|
if (doNotTrigger === undefined) { |
|
|
|
doNotTrigger = false; |
|
|
|
} |
|
|
|
|
|
|
|
if (this._selectionIsEmpty() == false && append == false) { |
|
|
|
if (this._selectionIsEmpty() == false && append == false && this.forceAppendSelection == false) { |
|
|
|
this._unselectAll(true); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (node.selected == false) { |
|
|
|
node.select(); |
|
|
|
this._addToSelection(node); |
|
|
|
if (object.selected == false) { |
|
|
|
object.select(); |
|
|
|
this._addToSelection(object); |
|
|
|
if (object instanceof Node && this.blockConnectingEdgeSelection == false) { |
|
|
|
this._selectConnectedEdges(object); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
node.unselect(); |
|
|
|
this._removeFromSelection(node); |
|
|
|
object.unselect(); |
|
|
|
this._removeFromSelection(object); |
|
|
|
} |
|
|
|
if (doNotTrigger == false) { |
|
|
|
this._trigger('select', { |
|
|
@ -251,6 +416,7 @@ var SelectionMixin = { |
|
|
|
*/ |
|
|
|
_handleTouch : function(pointer) { |
|
|
|
if (this.constants.navigation.enabled == true) { |
|
|
|
this.pointerPosition = pointer; |
|
|
|
var node = this._getNavigationNodeAt(pointer); |
|
|
|
if (node != null) { |
|
|
|
if (this[node.triggerFunction] !== undefined) { |
|
|
@ -270,10 +436,16 @@ var SelectionMixin = { |
|
|
|
_handleTap : function(pointer) { |
|
|
|
var node = this._getNodeAt(pointer); |
|
|
|
if (node != null) { |
|
|
|
this._selectNode(node,false); |
|
|
|
this._selectObject(node,false); |
|
|
|
} |
|
|
|
else { |
|
|
|
this._unselectAll(); |
|
|
|
var edge = this._getEdgeAt(pointer); |
|
|
|
if (edge != null) { |
|
|
|
this._selectObject(edge,false); |
|
|
|
} |
|
|
|
else { |
|
|
|
this._unselectAll(); |
|
|
|
} |
|
|
|
} |
|
|
|
this._redraw(); |
|
|
|
}, |
|
|
@ -305,7 +477,13 @@ var SelectionMixin = { |
|
|
|
_handleOnHold : function(pointer) { |
|
|
|
var node = this._getNodeAt(pointer); |
|
|
|
if (node != null) { |
|
|
|
this._selectNode(node,true); |
|
|
|
this._selectObject(node,true); |
|
|
|
} |
|
|
|
else { |
|
|
|
var edge = this._getEdgeAt(pointer); |
|
|
|
if (edge != null) { |
|
|
|
this._selectObject(edge,true); |
|
|
|
} |
|
|
|
} |
|
|
|
this._redraw(); |
|
|
|
}, |
|
|
@ -327,27 +505,54 @@ var SelectionMixin = { |
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
* retrieve the currently selected nodes |
|
|
|
* retrieve the currently selected objects |
|
|
|
* @return {Number[] | String[]} selection An array with the ids of the |
|
|
|
* selected nodes. |
|
|
|
*/ |
|
|
|
getSelection : function() { |
|
|
|
return this.selection.concat([]); |
|
|
|
var nodeIds = this.getSelectedNodes(); |
|
|
|
var edgeIds = this.getSelectedEdges(); |
|
|
|
return {nodes:nodeIds, edges:edgeIds}; |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
* retrieve the currently selected nodes as objects |
|
|
|
* @return {Objects} selection An array with the ids of the |
|
|
|
* retrieve the currently selected nodes |
|
|
|
* @return {String} selection An array with the ids of the |
|
|
|
* selected nodes. |
|
|
|
*/ |
|
|
|
getSelectionObjects : function() { |
|
|
|
return this.selectionObj; |
|
|
|
getSelectedNodes : function() { |
|
|
|
var idArray = []; |
|
|
|
for(var objectId in this.selectionObj) { |
|
|
|
if(this.selectionObj.hasOwnProperty(objectId)) { |
|
|
|
if (this.selectionObj[objectId] instanceof Node) { |
|
|
|
idArray.push(objectId); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return idArray |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* // TODO: rework this function, it is from the old system
|
|
|
|
* |
|
|
|
* retrieve the currently selected edges |
|
|
|
* @return {Array} selection An array with the ids of the |
|
|
|
* selected nodes. |
|
|
|
*/ |
|
|
|
getSelectedEdges : function() { |
|
|
|
var idArray = []; |
|
|
|
for(var objectId in this.selectionObj) { |
|
|
|
if(this.selectionObj.hasOwnProperty(objectId)) { |
|
|
|
if (this.selectionObj[objectId] instanceof Edge) { |
|
|
|
idArray.push(objectId); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return idArray |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* select zero or more nodes |
|
|
|
* @param {Number[] | String[]} selection An array with the ids of the |
|
|
|
* selected nodes. |
|
|
@ -368,89 +573,34 @@ var SelectionMixin = { |
|
|
|
if (!node) { |
|
|
|
throw new RangeError('Node with id "' + id + '" not found'); |
|
|
|
} |
|
|
|
this._selectNode(node,true,true); |
|
|
|
this._selectObject(node,true,true); |
|
|
|
} |
|
|
|
|
|
|
|
this.redraw(); |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* TODO: rework this function, it is from the old system |
|
|
|
* |
|
|
|
* Validate the selection: remove ids of nodes which no longer exist |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_updateSelection : function () { |
|
|
|
var i = 0; |
|
|
|
while (i < this.selection.length) { |
|
|
|
var nodeId = this.selection[i]; |
|
|
|
if (!this.nodes.hasOwnProperty(nodeId)) { |
|
|
|
this.selection.splice(i, 1); |
|
|
|
delete this.selectionObj[nodeId]; |
|
|
|
} |
|
|
|
else { |
|
|
|
i++; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Unselect selected nodes. If no selection array is provided, all nodes |
|
|
|
* are unselected |
|
|
|
* @param {Object[]} selection Array with selection objects, each selection |
|
|
|
* object has a parameter row. Optional |
|
|
|
* @param {Boolean} triggerSelect If true (default), the select event |
|
|
|
* is triggered when nodes are unselected |
|
|
|
* @return {Boolean} changed True if the selection is changed |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
/* _unselectNodes : function(selection, triggerSelect) { |
|
|
|
var changed = false; |
|
|
|
var i, iMax, id; |
|
|
|
|
|
|
|
if (selection) { |
|
|
|
// remove provided selections
|
|
|
|
for (i = 0, iMax = selection.length; i < iMax; i++) { |
|
|
|
id = selection[i]; |
|
|
|
if (this.nodes.hasOwnProperty(id)) { |
|
|
|
this.nodes[id].unselect(); |
|
|
|
} |
|
|
|
var j = 0; |
|
|
|
while (j < this.selection.length) { |
|
|
|
if (this.selection[j] == id) { |
|
|
|
this.selection.splice(j, 1); |
|
|
|
changed = true; |
|
|
|
} |
|
|
|
else { |
|
|
|
j++; |
|
|
|
for(var objectId in this.selectionObj) { |
|
|
|
if(this.selectionObj.hasOwnProperty(objectId)) { |
|
|
|
if (this.selectionObj[objectId] instanceof Node) { |
|
|
|
if (!this.nodes.hasOwnProperty(objectId)) { |
|
|
|
delete this.selectionObj[objectId]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if (this.selection && this.selection.length) { |
|
|
|
// remove all selections
|
|
|
|
for (i = 0, iMax = this.selection.length; i < iMax; i++) { |
|
|
|
id = this.selection[i]; |
|
|
|
if (this.nodes.hasOwnProperty(id)) { |
|
|
|
this.nodes[id].unselect(); |
|
|
|
else { // assuming only edges and nodes are selected
|
|
|
|
if (!this.edges.hasOwnProperty(objectId)) { |
|
|
|
delete this.selectionObj[objectId]; |
|
|
|
} |
|
|
|
} |
|
|
|
changed = true; |
|
|
|
} |
|
|
|
this.selection = []; |
|
|
|
} |
|
|
|
|
|
|
|
if (changed && (triggerSelect == true || triggerSelect == undefined)) { |
|
|
|
// fire the select event
|
|
|
|
this._trigger('select', { |
|
|
|
nodes: this.getSelection() |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return changed; |
|
|
|
}, |
|
|
|
*/ |
|
|
|
} |
|
|
|
/** |
|
|
|
* select all nodes on given location x, y |
|
|
|
* @param {Array} selection an array with node ids |
|
|
@ -475,40 +625,23 @@ var SelectionMixin = { |
|
|
|
if (selection[i] != this.selection[i]) { |
|
|
|
selectionAlreadyThere = false; |
|
|
|
break; |
|
|
|
>>>>>>> develop |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (selectionAlreadyThere) { |
|
|
|
return changed; |
|
|
|
} |
|
|
|
|
|
|
|
if (append == undefined || append == false) { |
|
|
|
// first deselect any selected node
|
|
|
|
var triggerSelect = false; |
|
|
|
changed = this._unselectNodes(undefined, triggerSelect); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0, iMax = selection.length; i < iMax; i++) { |
|
|
|
// add each of the new selections, but only when they are not duplicate
|
|
|
|
var id = selection[i]; |
|
|
|
var isDuplicate = (this.selection.indexOf(id) != -1); |
|
|
|
if (!isDuplicate) { |
|
|
|
this.nodes[id].select(); |
|
|
|
this.selection.push(id); |
|
|
|
changed = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
<<<<<<< HEAD |
|
|
|
======= |
|
|
|
if (changed) { |
|
|
|
// fire the select event
|
|
|
|
this._trigger('select', { |
|
|
|
nodes: this.getSelection() |
|
|
|
}); |
|
|
|
} |
|
|
|
>>>>>>> develop |
|
|
|
|
|
|
|
return changed; |
|
|
|
}, |
|
|
|
*/ |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|