Options to Create new Nodes on Selection of Node

Requirement: On Node Selection/MouseOver - give options to create new nodes, Each NodeType can have it’s own set of Options for node creation

We have different node types. We have added multiple buttons in an Adornment depending on the node type. We achieved the requirement by binding “selectionAdornmentTemplate” at run-time. We have created multiple selection adornmnet temmplates and depending on the NodeType we bind it to “selectionAdornmentTemplate”.

The requirement was achieved, but this broke the saving logic[myDiagram.model.toJson()], it enters into some infinite loop. We fixed this by removing the selectionAdornmentTemplate from the Node before saving it.

Question#

  1. Was this the correct way of achieving the requirement? If not what could have been tried.
  2. If answer to question 1, is Yes then how to fix the broken saving logic.

//My Node Template
<span =“Apple-tab-span” style=“white-space:pre”> myDiagram.nodeTemplate = G(go.Node, “Auto”, {
<span =“Apple-tab-span” style=“white-space:pre”> selectionChanged : onNodeSelect,
<span =“Apple-tab-span” style=“white-space:pre”> doubleClick : showDecTable,
<span =“Apple-tab-span” style=“white-space:pre”> contextMenu : partContextMenu,
<span =“Apple-tab-span” style=“white-space:pre”> resizable : true,
<span =“Apple-tab-span” style=“white-space:pre”> visible : true,
<span =“Apple-tab-span” style=“white-space:pre”> desiredSize : new go.Size(NaN, NaN)
<span =“Apple-tab-span” style=“white-space:pre”> }, G(go.Shape, {
<span =“Apple-tab-span” style=“white-space:pre”> portId : “”,
<span =“Apple-tab-span” style=“white-space:pre”> fromLinkable : true,
<span =“Apple-tab-span” style=“white-space:pre”> name : “Node”
<span =“Apple-tab-span” style=“white-space:pre”> }, new go.Binding(“strokeWidth”, “strokeWidth”).makeTwoWay(),
<span =“Apple-tab-span” style=“white-space:pre”> new go.Binding(“toLinkable”, “to”),
<span =“Apple-tab-span” style=“white-space:pre”> new go.Binding(“figure”, “fig”), new go.Binding(“fill”, “color”)
<span =“Apple-tab-span” style=“white-space:pre”> .makeTwoWay(), new go.Binding(“geometry”, “geo”)), G(
<span =“Apple-tab-span” style=“white-space:pre”> go.TextBlock, {
<span =“Apple-tab-span” style=“white-space:pre”> name : “TextBlk”,
<span =“Apple-tab-span” style=“white-space:pre”> margin : 8,
<span =“Apple-tab-span” style=“white-space:pre”> wrap : go.TextBlock.WrapFit,
<span =“Apple-tab-span” style=“white-space:pre”> editable : true,
<span =“Apple-tab-span” style=“white-space:pre”> font : smallfont,
<span =“Apple-tab-span” style=“white-space:pre”> stroke : “black”
<span =“Apple-tab-span” style=“white-space:pre”> }, new go.Binding(“text”, “text”).makeTwoWay(), new go.Binding(
<span =“Apple-tab-span” style=“white-space:pre”> “stroke”, “stroke”).makeTwoWay(), new go.Binding(“font”,
<span =“Apple-tab-span” style=“white-space:pre”> “font”).makeTwoWay()), new go.Binding(“location”, “loc”,
<span =“Apple-tab-span” style=“white-space:pre”> go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding(
<span =“Apple-tab-span” style=“white-space:pre”> “selectionAdornmentTemplate”, “selectionAdornmentTemplate”),
<span =“Apple-tab-span” style=“white-space:pre”> new go.Binding(“desiredSize”, “desiredSize”).makeTwoWay(),
<span =“Apple-tab-span” style=“white-space:pre”> new go.Binding(“visible”, “visible”).makeTwoWay());

//Sample selectionAdornmentTemplate, we have created multiple adornment templates to have the requirement met
<span =“Apple-tab-span” style=“white-space:pre”> AdornmentTemplate1 = G(go.Adornment, “Spot”, G(go.Panel,
<span =“Apple-tab-span” style=“white-space:pre”> “Auto”, G(go.Shape, {
<span =“Apple-tab-span” style=“white-space:pre”> fill : null,
<span =“Apple-tab-span” style=“white-space:pre”> stroke : “#707070”,
<span =“Apple-tab-span” style=“white-space:pre”> strokeWidth : 2
<span =“Apple-tab-span” style=“white-space:pre”> }), G(go.Placeholder)),
<span =“Apple-tab-span” style=“white-space:pre”> G(“Button”, {
<span =“Apple-tab-span” style=“white-space:pre”> alignment : new go.Spot(1, 0, 5, 0),
<span =“Apple-tab-span” style=“white-space:pre”> alignmentFocus : go.Spot.Left,
<span =“Apple-tab-span” style=“white-space:pre”> click : addNodeType1
<span =“Apple-tab-span” style=“white-space:pre”> },
<span =“Apple-tab-span” style=“white-space:pre”> G(go.Shape, {
<span =“Apple-tab-span” style=“white-space:pre”> fill : G(go.Brush, go.Brush.Linear, {
<span =“Apple-tab-span” style=“white-space:pre”> 0 : “white”,
<span =“Apple-tab-span” style=“white-space:pre”> 1 : “#CCFFCC”,
<span =“Apple-tab-span” style=“white-space:pre”> start : new go.Spot(0, 0),
<span =“Apple-tab-span” style=“white-space:pre”> end : new go.Spot(1, 0)
<span =“Apple-tab-span” style=“white-space:pre”> }),
<span =“Apple-tab-span” style=“white-space:pre”> figure : “Rectangle”,
<span =“Apple-tab-span” style=“white-space:pre”> desiredSize : new go.Size(15, 10)
<span =“Apple-tab-span” style=“white-space:pre”> })), G(“Button”, {
<span =“Apple-tab-span” style=“white-space:pre”> alignment : new go.Spot(1, 1, 5, 0),
<span =“Apple-tab-span” style=“white-space:pre”> alignmentFocus : go.Spot.Left,
<span =“Apple-tab-span” style=“white-space:pre”> click : addNodeType2
<span =“Apple-tab-span” style=“white-space:pre”> },
<span =“Apple-tab-span” style=“white-space:pre”> G(go.Shape, {
<span =“Apple-tab-span” style=“white-space:pre”> fill : G(go.Brush, go.Brush.Linear, {
<span =“Apple-tab-span” style=“white-space:pre”> 0 : “white”,
<span =“Apple-tab-span” style=“white-space:pre”> 1 : “#FFCC00”,
<span =“Apple-tab-span” style=“white-space:pre”> start : new go.Spot(0, 0),
<span =“Apple-tab-span” style=“white-space:pre”> end : new go.Spot(1, 0)
<span =“Apple-tab-span” style=“white-space:pre”> }),
<span =“Apple-tab-span” style=“white-space:pre”> geometry : NodeType2Geometry,
<span =“Apple-tab-span” style=“white-space:pre”> desiredSize : new go.Size(15, 10)
<span =“Apple-tab-span” style=“white-space:pre”> })));

<span =“Apple-tab-span” style=“white-space:pre”>

  1. Yes, that’s right. Showing the Adornment on mouse-over is also possible. I assume you copied the examples in the Grafcet sample.

    2. The problem is that GraphObjects, including Adornments, should only be part of the “view”, not part of the “model”. I suggest that you just keep a simple data property, probably a string, on the data to name the kind of Adornment to show. Use a conversion function to look up the Adornment using the string value in a global object. This also avoids putting multiple copies of templates into your model. Templates ought to be shared.

    In the future Model.toJson could detect the presence of a GraphObject and signal an error or warning.