UNPKG

gojs

Version:

Interactive diagrams, charts, and graphs, such as trees, flowcharts, orgcharts, UML, BPMN, or business diagrams

252 lines (235 loc) 11.4 kB
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Selection Adornment Buttons</title> <meta name="description" content="When a diagram node is selected show a selection Adornment holding buttons on which a click invokes a command or a drag starts a tool"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Copyright 1998-2020 by Northwoods Software Corporation. --> <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; // for conciseness in defining templates myDiagram = $(go.Diagram, "myDiagramDiv", // create a Diagram for the DIV HTML element { "linkingTool.isEnabled": false, // invoked explicitly by drawLink function, below "linkingTool.direction": go.LinkingTool.ForwardsOnly, // only draw "from" towards "to" "undoManager.isEnabled": true // enable undo & redo }); myDiagram.linkTemplate = $(go.Link, { routing: go.Link.AvoidsNodes, corner: 5 }, $(go.Shape, { strokeWidth: 1.5 }), $(go.Shape, { toArrow: "OpenTriangle" }) ); myDiagram.nodeTemplate = $(go.Node, "Auto", { desiredSize: new go.Size(80, 80), // rearrange the link points evenly along the sides of the nodes as links are // drawn or reconnected -- these event handlers only make sense when the fromSpot // and toSpot are Spot.xxxSides linkConnected: function(node, link, port) { if (link.fromNode !== null) link.fromNode.invalidateConnectedLinks(); if (link.toNode !== null) link.toNode.invalidateConnectedLinks(); }, linkDisconnected: function(node, link, port) { if (link.fromNode !== null) link.fromNode.invalidateConnectedLinks(); if (link.toNode !== null) link.toNode.invalidateConnectedLinks(); }, locationSpot: go.Spot.Center }, new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify), $(go.Shape, { name: "SHAPE", // named so that changeColor can modify it strokeWidth: 0, // no border fill: "lightgray", // default fill color portId: "", // use the following property if you want users to draw new links // interactively by dragging from the Shape, and re-enable the LinkingTool // in the initialization of the Diagram //cursor: "pointer", fromSpot: go.Spot.AllSides, fromLinkable: true, fromLinkableDuplicates: true, fromLinkableSelfNode: true, toSpot: go.Spot.AllSides, toLinkable: true, toLinkableDuplicates: true, toLinkableSelfNode: true }, new go.Binding("fill", "color").makeTwoWay()), $(go.TextBlock, { name: "TEXTBLOCK", // named so that editText can start editing it margin: 3, // use the following property if you want users to interactively start // editing the text by clicking on it or by F2 if the node is selected: //editable: true, overflow: go.TextBlock.OverflowEllipsis, maxLines: 5 }, new go.Binding("text").makeTwoWay()) ); // a selected node shows an Adornment that includes both a blue border // and a row of Buttons above the node myDiagram.nodeTemplate.selectionAdornmentTemplate = $(go.Adornment, "Spot", $(go.Panel, "Auto", $(go.Shape, { stroke: "dodgerblue", strokeWidth: 2, fill: null }), $(go.Placeholder) ), $(go.Panel, "Horizontal", { alignment: go.Spot.Top, alignmentFocus: go.Spot.Bottom }, $("Button", { click: editText }, // defined below, to support editing the text of the node $(go.TextBlock, "t", { font: "bold 10pt sans-serif", desiredSize: new go.Size(15, 15), textAlign: "center" }) ), $("Button", { click: changeColor, "_buttonFillOver": "transparent" }, // defined below, to support changing the color of the node new go.Binding("ButtonBorder.fill", "color", nextColor), $(go.Shape, { fill: null, stroke: null, desiredSize: new go.Size(14, 14) }) ), $("Button", { // drawLink is defined below, to support interactively drawing new links click: drawLink, // click on Button and then click on target node actionMove: drawLink // drag from Button to the target node }, $(go.Shape, { geometryString: "M0 0 L8 0 8 12 14 12 M12 10 L14 12 12 14" }) ), $("Button", { actionMove: dragNewNode, // defined below, to support dragging from the button _dragData: { text: "a Node", color: "lightgray" }, // node data to copy click: clickNewNode // defined below, to support a click on the button }, $(go.Shape, { geometryString: "M0 0 L3 0 3 10 6 10 x F1 M6 6 L14 6 14 14 6 14z", fill: "gray" }) ) ) ); function editText(e, button) { var node = button.part.adornedPart; e.diagram.commandHandler.editTextBlock(node.findObject("TEXTBLOCK")); } // used by nextColor as the list of colors through which we rotate var myColors = ["lightgray", "lightblue", "lightgreen", "yellow", "orange", "pink"]; // used by both the Button Binding and by the changeColor click function function nextColor(c) { var idx = myColors.indexOf(c); if (idx < 0) return "lightgray"; if (idx >= myColors.length - 1) idx = 0; return myColors[idx + 1]; } function changeColor(e, button) { var node = button.part.adornedPart; var shape = node.findObject("SHAPE"); if (shape === null) return; node.diagram.startTransaction("Change color"); shape.fill = nextColor(shape.fill); button["_buttonFillNormal"] = nextColor(shape.fill); // update the button too node.diagram.commitTransaction("Change color"); } function drawLink(e, button) { var node = button.part.adornedPart; var tool = e.diagram.toolManager.linkingTool; tool.startObject = node.port; e.diagram.currentTool = tool; tool.doActivate(); } // used by both clickNewNode and dragNewNode to create a node and a link // from a given node to the new node function createNodeAndLink(data, fromnode) { var diagram = fromnode.diagram; var model = diagram.model; var nodedata = model.copyNodeData(data); model.addNodeData(nodedata); var newnode = diagram.findNodeForData(nodedata); var linkdata = model.copyLinkData({}); model.setFromKeyForLinkData(linkdata, model.getKeyForNodeData(fromnode.data)); model.setToKeyForLinkData(linkdata, model.getKeyForNodeData(newnode.data)); model.addLinkData(linkdata); diagram.select(newnode); return newnode; } // the Button.click event handler, called when the user clicks the "N" button function clickNewNode(e, button) { var data = button._dragData; if (!data) return; e.diagram.startTransaction("Create Node and Link"); var fromnode = button.part.adornedPart; var newnode = createNodeAndLink(button._dragData, fromnode); newnode.location = new go.Point(fromnode.location.x + 200, fromnode.location.y); e.diagram.commitTransaction("Create Node and Link"); } // the Button.actionMove event handler, called when the user drags within the "N" button function dragNewNode(e, button) { var tool = e.diagram.toolManager.draggingTool; if (tool.isBeyondDragSize()) { var data = button._dragData; if (!data) return; e.diagram.startTransaction("button drag"); // see doDeactivate, below var newnode = createNodeAndLink(data, button.part.adornedPart); newnode.location = e.diagram.lastInput.documentPoint; // don't commitTransaction here, but in tool.doDeactivate, after drag operation finished // set tool.currentPart to a selected movable Part and then activate the DraggingTool tool.currentPart = newnode; e.diagram.currentTool = tool; tool.doActivate(); } } // using dragNewNode also requires modifying the standard DraggingTool so that it // only calls commitTransaction when dragNewNode started a "button drag" transaction; // do this by overriding DraggingTool.doDeactivate: var tool = myDiagram.toolManager.draggingTool; tool.doDeactivate = function() { // commit "button drag" transaction, if it is ongoing; see dragNewNode, above if (tool.diagram.undoManager.nestedTransactionNames.elt(0) === "button drag") { tool.diagram.commitTransaction(); } go.DraggingTool.prototype.doDeactivate.call(tool); // call the base method }; myDiagram.model = new go.GraphLinksModel( [ { key: 1, text: "Alpha", color: "lightblue", location: "0 0" }, { key: 2, text: "Beta", color: "orange", location: "140 0" }, { key: 3, text: "Gamma", color: "lightgreen", location: "0 140" }, { key: 4, text: "Delta", color: "pink", location: "140 140" } ], [ { from: 1, to: 2 } ]); myDiagram.findNodeForKey(4).isSelected = true; } </script> </head> <body onload="init()"> <div id="sample"> <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div> <p> The node template uses a custom <a>Part.selectionAdornmentTemplate</a> to add a row of Buttons when the node is selected. Select a node and you will see the Buttons for the node. </p> <p> The first button, "T", when clicked, starts in-place editing of the text. </p> <p> The second button, "C", when clicked, changes the color of the node, rotating through a list of colors. </p> <p> The third button, "L", when clicked or dragged, starts the <a>LinkingTool</a>, drawing a new link starting at the selected node. </p> <p> The fourth button, "N", when clicked, adds a new node and creates a link from the selected node to the new node. Dragging from the fourth button does the same thing as a click but also activates the <a>DraggingTool</a>, allowing the user to drag the new node where they like. </p> </div> </body> </html>