207 lines
8.1 KiB
HTML
207 lines
8.1 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Selectable Ports</title>
|
|
<meta name="description" content="Support selecting ports within nodes." />
|
|
<!-- Copyright 1998-2017 by Northwoods Software Corporation. -->
|
|
<meta charset="UTF-8">
|
|
<script src="../release/go.js"></script>
|
|
<script src="../assets/js/goSamples.js"></script> <!-- this is only for the GoJS Samples framework -->
|
|
<script id="code">
|
|
function init() {
|
|
if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
|
|
var $ = go.GraphObject.make;
|
|
|
|
myDiagram =
|
|
$(go.Diagram, "myDiagramDiv",
|
|
{
|
|
initialContentAlignment: go.Spot.Center,
|
|
// For this sample, automatically show the state of the diagram's model on the page
|
|
"ModelChanged": function(e) {
|
|
if (e.isTransactionFinished) showModel();
|
|
},
|
|
"undoManager.isEnabled": true
|
|
});
|
|
|
|
var UnselectedBrush = "lightgray"; // item appearance, if not "selected"
|
|
var SelectedBrush = "dodgerblue"; // item appearance, if "selected"
|
|
|
|
function makeItemTemplate(leftside) {
|
|
return $(go.Panel, "Auto",
|
|
{ margin: new go.Margin(1, 0) }, // some space between ports
|
|
$(go.Shape,
|
|
{
|
|
name: "SHAPE",
|
|
fill: UnselectedBrush, stroke: "gray",
|
|
geometryString: "F1 m 0,0 l 5,0 1,4 -1,4 -5,0 1,-4 -1,-4 z",
|
|
spot1: new go.Spot(0, 0, 5, 1), // keep the text inside the shape
|
|
spot2: new go.Spot(1, 1, -5, 0),
|
|
// some port-related properties
|
|
toSpot: go.Spot.Left,
|
|
toLinkable: leftside,
|
|
fromSpot: go.Spot.Right,
|
|
fromLinkable: !leftside,
|
|
cursor: "pointer"
|
|
},
|
|
new go.Binding("portId", "name")),
|
|
$(go.TextBlock,
|
|
new go.Binding("text", "name"),
|
|
{ // allow the user to select items -- the background color indicates whether "selected"
|
|
isActionable: true,
|
|
//?? maybe this should be more sophisticated than simple toggling of selection
|
|
click: function(e, tb) {
|
|
var shape = tb.panel.findObject("SHAPE");
|
|
if (shape !== null) {
|
|
// don't record item selection changes
|
|
var oldskips = shape.diagram.skipsUndoManager;
|
|
shape.diagram.skipsUndoManager = true;
|
|
// toggle the Shape.fill
|
|
if (shape.fill === UnselectedBrush) {
|
|
shape.fill = SelectedBrush;
|
|
} else {
|
|
shape.fill = UnselectedBrush;
|
|
}
|
|
shape.diagram.skipsUndoManager = oldskips;
|
|
}
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
myDiagram.nodeTemplate =
|
|
$(go.Node, "Spot",
|
|
{ selectionAdorned: false },
|
|
{ locationSpot: go.Spot.Center, locationObjectName: "BODY" },
|
|
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
|
|
$(go.Panel, "Auto",
|
|
{ name: "BODY" },
|
|
$(go.Shape, "RoundedRectangle",
|
|
{ stroke: "gray", strokeWidth: 2, fill: "transparent" },
|
|
new go.Binding("stroke", "isSelected", function(b) { return b ? SelectedBrush : UnselectedBrush; }).ofObject()),
|
|
$(go.Panel, "Vertical",
|
|
{ margin: 6 },
|
|
$(go.TextBlock,
|
|
new go.Binding("text", "name"),
|
|
{ alignment: go.Spot.Left }),
|
|
$(go.Picture, "images/60x90.png",
|
|
{ width: 30, height: 45, margin: new go.Margin(10, 10) })
|
|
)
|
|
),
|
|
$(go.Panel, "Vertical",
|
|
{ name: "LEFTPORTS", alignment: new go.Spot(0, 0.5, 0, 7) },
|
|
new go.Binding("itemArray", "inservices"),
|
|
{ itemTemplate: makeItemTemplate(true) }
|
|
),
|
|
$(go.Panel, "Vertical",
|
|
{ name: "RIGHTPORTS", alignment: new go.Spot(1, 0.5, 0, 7) },
|
|
new go.Binding("itemArray", "outservices"),
|
|
{ itemTemplate: makeItemTemplate(false) }
|
|
)
|
|
);
|
|
|
|
myDiagram.linkTemplate =
|
|
$(go.Link,
|
|
{ routing: go.Link.Orthogonal, corner: 10, toShortLength: -3 },
|
|
{ relinkableFrom: true, relinkableTo: true, reshapable: true, resegmentable: true },
|
|
$(go.Shape, { stroke: "gray", strokeWidth: 2.5 })
|
|
);
|
|
|
|
function findAllSelectedItems() {
|
|
var items = [];
|
|
for (var nit = myDiagram.nodes; nit.next(); ) {
|
|
var node = nit.value;
|
|
//?? Maybe this should only return selected items that are within selected Nodes
|
|
//if (!node.isSelected) continue;
|
|
var table = node.findObject("LEFTPORTS");
|
|
if (table !== null) {
|
|
for (var iit = table.elements; iit.next(); ) {
|
|
var itempanel = iit.value;
|
|
var shape = itempanel.findObject("SHAPE");
|
|
if (shape !== null && shape.fill === SelectedBrush) items.push(itempanel);
|
|
}
|
|
}
|
|
table = node.findObject("RIGHTPORTS");
|
|
if (table !== null) {
|
|
for (var iit = table.elements; iit.next(); ) {
|
|
var itempanel = iit.value;
|
|
var shape = itempanel.findObject("SHAPE");
|
|
if (shape !== null && shape.fill === SelectedBrush) items.push(itempanel);
|
|
}
|
|
}
|
|
}
|
|
return items;
|
|
}
|
|
|
|
// Override the standard CommandHandler deleteSelection and canDeleteSelection behavior.
|
|
// If there are any selected items, delete them instead of deleting any selected nodes or links.
|
|
|
|
myDiagram.commandHandler.canDeleteSelection = function() {
|
|
// true if there are any selected deletable nodes or links,
|
|
// or if there are any selected items within nodes
|
|
return go.CommandHandler.prototype.canDeleteSelection.call(myDiagram.commandHandler) ||
|
|
findAllSelectedItems().length > 0;
|
|
};
|
|
|
|
myDiagram.commandHandler.deleteSelection = function() {
|
|
var items = findAllSelectedItems();
|
|
if (items.length > 0) { // if there are any selected items, delete them
|
|
myDiagram.startTransaction("delete items");
|
|
for (var i = 0; i < items.length; i++) {
|
|
var item = items[i];
|
|
var nodedata = item.part.data;
|
|
var itemdata = item.data;
|
|
// find the item array that the item data is in; try "inservices" first
|
|
var itemarray = nodedata.inservices;
|
|
var itemindex = itemarray.indexOf(itemdata);
|
|
if (itemindex < 0) { // otherwise try "outservices"
|
|
itemarray = nodedata.outservices;
|
|
itemindex = itemarray.indexOf(itemdata);
|
|
}
|
|
if (itemindex >= 0) {
|
|
myDiagram.model.removeArrayItem(itemarray, itemindex);
|
|
}
|
|
}
|
|
myDiagram.commitTransaction("delete items");
|
|
} else { // otherwise just delete nodes and/or links, as usual
|
|
go.CommandHandler.prototype.deleteSelection.call(myDiagram.commandHandler);
|
|
}
|
|
};
|
|
|
|
myDiagram.model =
|
|
$(go.GraphLinksModel,
|
|
{
|
|
copiesArrays: true,
|
|
copiesArrayObjects: true,
|
|
linkFromPortIdProperty: "fromPort",
|
|
linkToPortIdProperty: "toPort",
|
|
nodeDataArray: [
|
|
{ key: 1, name: "Server", inservices: [{ name: "s1" }, { name: "s2" }], outservices: [{ name: "o1" }], loc: "0 0" },
|
|
{ key: 2, name: "Other", inservices: [{ name: "s1" }, { name: "s2" }], loc: "200 60" }
|
|
],
|
|
linkDataArray: [
|
|
{ from: 1, fromPort: "o1", to: 2, toPort: "s2" }
|
|
]
|
|
});
|
|
|
|
showModel();
|
|
|
|
function showModel() {
|
|
document.getElementById("mySavedModel").value = myDiagram.model.toJson();
|
|
}
|
|
}
|
|
</script>
|
|
</head>
|
|
<body onload="init()">
|
|
<div id="sample">
|
|
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
|
|
<p>
|
|
Click on a port to toggle its selection.
|
|
The Delete command will only delete selected ports, if there are any; otherwise it will delete Nodes and Links as it normally would.
|
|
</p>
|
|
<p>The model data, automatically updated after each change or undo or redo:</p>
|
|
<textarea id="mySavedModel" style="width:100%;height:300px"></textarea>
|
|
</div>
|
|
</body>
|
|
</html>
|