Hi,
I’ve searched through the forum and tried a lot of things, but can’t seem to find a good solution…
I have two diagrams, palette and main. When a node is dropped from palette onto the main diagram (either empty space or another node), I’d like to be able to detect whether the node being dropped is already in the main diagram, hence preventing duplicate nodes. Simply deleting selection from palette is not enough for my use case, as palette will be reloaded and some nodes in the palette might already be included in the main diagram from before.
I tried using both mouseDrop of node template as well as “ExternalObjectsDropped” handler for the main diagram as suggested in another thread and following the Flowgrammer example.
In the example below, palette nodes with keys 1, 2, 3 are already on the main diagram, therefore dropping them onto the main diagram would introduce duplicates which is what I am trying to avoid.
Any hints or tips are greatly appreciated.
Cheers,
<!doctype html>
<html>
<head>
<title>Palette Test</title>
<script src="go-debug.js"></script>
<script id="code">
function init() {
var $ = go.GraphObject.make; // for conciseness in defining templates
// initialize the main Diagram
var diagram =
$(go.Diagram, "diagramContainer", // must be the ID or reference to div
{
initialContentAlignment: go.Spot.Center,
// make sure users can only create trees
validCycle: go.Diagram.CycleDestinationTree,
// users can select only one part at a time
maxSelectionCount: 1,
layout: $(go.TreeLayout, {
treeStyle: go.TreeLayout.StyleLastParents,
arrangement: go.TreeLayout.ArrangementHorizontal,
// properties for most of the tree:
angle: 90,
layerSpacing: 35,
// properties for the "last parents":
alternateAngle: 90,
alternateLayerSpacing: 35,
alternateAlignment: go.TreeLayout.AlignmentBus,
alternateNodeSpacing: 20
}),
// enable undo & redo
"undoManager.isEnabled": true,
allowDragOut: false,
allowDrop: true
});
diagram.nodeTemplate =
$(go.Node, "Auto",
{
mouseDragEnter: function(e, node, prev) {
var diagram = node.diagram;
var selnode = diagram.selection.first();
if (!canBeChild(selnode, node)) return;
},
mouseDrop: dropOntoNode
},
$(go.Shape, "RoundedRectangle", {
fill: "white"
},
new go.Binding("fill", "color"), {
cursor: "pointer"
}),
$(go.TextBlock, {
margin: 5
},
new go.Binding("text", "color"))
);
diagram.model.nodeDataArray = [{
key: 1,
color: "lightblue"
},
{
key: 2,
color: "orange"
}, {
key: 3,
color: "yellow"
}, {
key: 4,
color: "red"
}, {
key: 5,
color: "gray"
}];
diagram.model.linkDataArray = [{"from":1, "to":2}, {"from":1, "to":3},{"from":2, "to":4}, {"from":1, "to":5} ];
function canBeChild(node1, node2) {
if (!(node1 instanceof go.Node)) return false; // must be a Node
if (node1 === node2) return false; // cannot be child of yourself
if (node2.isInTreeOf(node1)) return false; // already have a parent
return true;
}
// start off with no Parts
diagram.undoManager.isEnabled = true;
// create the Palette
var palette =
$(go.Palette, "myPaletteDiv", { maxSelectionCount: 1});
// the Palette's node template is different from the main Diagram's
palette.nodeTemplate =
$(go.Node, "Horizontal",
$(go.Shape, {
width: 14,
height: 14,
fill: "white"
},
new go.Binding("fill", "color")),
$(go.TextBlock,
new go.Binding("text", "color"))
);
// the list of data to show in the Palette
palette.model.nodeDataArray = [{
key: 1,
color: "lightblue"
},{
key: 2,
color: "orange"
},{
key: 3,
color: "yellow"
}, {
key: 4,
color: "purple"
}, {
key: 5,
color: "green"
}];
palette.model.undoManager = diagram.model.undoManager;
diagram.addDiagramListener("ExternalObjectsDropped", function(e) {
var newnode = palette.selection.first(); //always dropping from palette
var dupe = isDupe(newnode.data);
if(dupe){ //already in diagram, remove the duplicate
diagram.commandHandler.deleteSelection();
}
else{ // new node to add to diagram
palette.commandHandler.deleteSelection(); //reomve from palette
}
});
function dropOntoNode(e, node) {
var diagram = node.diagram;
var selnode = diagram.selection.first(); // assume just one Node in selection
// should do a duplicate check?
if (canBeChild(selnode, node)) {
// find any existing link into the selected node
var link = selnode.findTreeParentLink();
if (link !== null) { // reconnect any existing link
link.fromNode = node;
} else { // else create a new link
diagram.toolManager.linkingTool.insertLink(node, node.port, selnode, selnode.port);
}
}
}
function isDupe(data){
var el = diagram.findNodeForData(data);
var b = el != null;
return b;
}
}
</script>
</head>
<body onload="init()">
<div>
<span id="paletteSpan" style="display: inline-block; vertical-align: top">
<b>Palette:</b><br>
<div id="myPaletteDiv" style="width: 120px; height: 250px; position: relative; cursor: auto; border : solid 1px blue;" class="diagramContainer"></div>
</span>
<span id="diagramSpan" style="display: inline-block; vertical-align: top">
<b>Diagram:</b><br>
<div class="diagramContainer" style="width: 350px; height: 250px; position: relative; cursor: auto; border : solid 1px blue;" id="diagramContainer"></div>
</span>
</div>
</body>
</html>