Which Diagram Layout to use?

Happy New Year! We need to change our current TreeLayout because of use case requirement changes.

I started off with the SideTreeLayout from your Samples page but I’m realizing that I don’t have much control of the position of the Assistant (blue Nodes) and we may have more than 1 Assistant so, I think SideTreeLayout is not the one to start off with.

Basically, we’re adding the functionality to drop from Palette these blue Nodes on the left and programmatically create some Links to the white Nodes.

Which Layout would you recommend for this use case? Thank you so much!

What is your model data?

This is the Palette Data:

export const paletteDataInit = [
  {
    key: 1,
    text: "Import Nodes",
    isGroup: true,
    category: "Imports",
  },
  {
    key: 2,
    isGroup: true,
    category: "PaletteDocletGroup",
  },
  {
    category: "ImportNode",
    group: 1,
    isAssistant: true,
    key: -1,
    state: "Palette",
    text: "PCD",
  },
  {
    category: "ImportNode",
    isAssistant: true,
    group: 1,
    key: -2,
    state: "Palette",
    text: "neo4j Query",
  },
  {
    category: "ImportNode",
    isAssistant: true,
    group: 1,
    key: -3,
    state: "Palette",
    text: "Python Script",
  },
  {
    category: "ImportNode",
    isAssistant: true,
    group: 1,
    key: -4,
    state: "Palette",
    text: "R Script",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "a34cc470-584f-491d-852c-e337b03ba9a9",
    key: "b3dbd719-33f5-45bd-bba1-ad5cd152369f",
    state: "Palette",
    tags: "",
    templateIndex: 0,
    title: "Approach",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "94358ae0-c808-46f1-bee1-ceb18d65e387",
    key: "9a444497-0183-4998-b790-011f65a8d8ae",
    state: "Palette",
    tags: "",
    templateIndex: 1,
    title: "Assumptions",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "eea7c2f2-a5c8-4e27-981e-b99add938e4f",
    key: "407e8e11-dd29-474d-9bd3-81f61fc83334",
    state: "Palette",
    tags: "",
    templateIndex: 2,
    title: "Change Order Process",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "6feb527c-d956-46f5-8cc1-42261be3a0ff",
    key: "91223f02-c8be-4cd4-a344-4e4bdee74f0c",
    state: "Palette",
    tags: "",
    templateIndex: 3,
    title: "Charges, Expenses and Invoicing",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "fc386d42-4874-4e3e-bb36-2e38430a17f8",
    key: "adbee4fd-e067-42c1-887a-f60d0460a8d4",
    state: "Palette",
    tags: "",
    templateIndex: 4,
    title: "Communications Plan",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "c145e9fd-66c7-47d2-9cd9-b1aa5f0e9906",
    key: "a495b561-c7a6-42ea-b4fc-92999bf3ba39",
    state: "Palette",
    tags: "",
    templateIndex: 5,
    title: "Deliverables",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "1f409525-7df2-4bb6-b406-3e6be8e9b347",
    key: "34a15cc6-7e1a-40c1-9c41-791a6f9a71da",
    state: "Palette",
    tags: "",
    templateIndex: 6,
    title: "Description of Work",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "2bb59c76-b54d-4b49-abbd-a0c6595d77bd",
    key: "9aa40170-bf05-4b5a-95e3-3d88b43f827e",
    state: "Palette",
    tags: "",
    templateIndex: 7,
    title: "Engagement Contacts",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "bc98aa1c-8a5a-444c-b41a-191cf5cfa261",
    key: "1a9fe4a6-2ec3-4e82-9137-dc1ff4cad7d1",
    state: "Palette",
    tags: "",
    templateIndex: 8,
    title: "Escalation Process",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "46f32999-4fd4-46fd-a49b-d2ffb1e90533",
    key: "c8523b52-07c2-4750-bf2e-821de65c8553",
    state: "Palette",
    tags: "",
    templateIndex: 9,
    title: "Initiation of Work",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "e34723c4-efd1-48e5-b134-c16475362833",
    key: "ede62a24-3d17-49bd-aaf7-ab126e89a3cb",
    state: "Palette",
    tags: "",
    templateIndex: 10,
    title: "Introduction",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "6c12812b-5cf4-4e6f-bce2-16afccfb91c0",
    key: "58be694e-7cf7-495f-88ee-412586e04ddd",
    state: "Palette",
    tags: "",
    templateIndex: 11,
    title: "IT&S Responsibilities",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "c4330a2c-d559-4800-8d41-b178e29ee1f3",
    key: "1612b684-9cf8-4bb5-b308-3261edb82bb0",
    state: "Palette",
    tags: "",
    templateIndex: 12,
    title: "Kickoff Meeting",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "91177f3a-3c6d-40ea-bb76-7121fd6580f5",
    key: "2603513c-02e2-40a7-a150-ef36b320cb8f",
    state: "Palette",
    tags: "",
    templateIndex: 13,
    title: "Project Dependencies",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "c42d5d77-4adc-40b4-a651-eb44d27958b4",
    key: "5f7704ea-da1d-4989-969d-1e6581a460f0",
    state: "Palette",
    tags: "",
    templateIndex: 14,
    title: "Timeline",
  },
  {
    category: "DocletTypeNode",
    group: 2,
    id: "b8e39e14-24bc-4b87-af6a-845d56ebf405",
    key: "a31e75d3-6a15-458c-aa27-443bf85b3119",
    state: "Palette",
    tags: "",
    templateIndex: 15,
    title: "TOC",
  },
];

This is Diagram Data

export const diagramDataInit = {
  nodeDataArray: [
    {
      category: "DropDocletType",
      key: "prepend",
      id: "prepend",
      text: "Prepend Doclet Type",
    },
    {
      category: "DocletTypeNode",
      state: "Diagram",
      key: "1f409525-7df2-4bb6-b406-3e6be8e9b347-0",
      id: "1f409525-7df2-4bb6-b406-3e6be8e9b347",
      tags: "",
      templateIndex: "-",
      title: "Description of Work",
    },
    {
      category: "DocletTypeNode",
      state: "Diagram",
      key: "1f409525-7df2-4bb6-b406-3e6be8e9b347-1",
      id: "1f409525-7df2-4bb6-b406-3e6be8e9b347",
      tags: "",
      templateIndex: "-",
      title: "Description of Work",
    },
    {
      category: "DocletTypeNode",
      state: "Diagram",
      key: "2bb59c76-b54d-4b49-abbd-a0c6595d77bd-2",
      id: "2bb59c76-b54d-4b49-abbd-a0c6595d77bd",
      tags: "",
      templateIndex: "-",
      title: "Engagement Contacts",
    },
    {
      category: "DocletTypeNode",
      state: "Diagram",
      key: "fc386d42-4874-4e3e-bb36-2e38430a17f8-3",
      id: "fc386d42-4874-4e3e-bb36-2e38430a17f8",
      tags: "",
      templateIndex: "-",
      title: "Communications Plan",
    },
    {
      category: "DropDocletType",
      key: "append",
      id: "append",
      text: "Append Doclet Type",
    },
  ],
  linkDataArray: [
    {
      from: "prepend",
      to: "1f409525-7df2-4bb6-b406-3e6be8e9b347-0",
    },
    {
      from: "1f409525-7df2-4bb6-b406-3e6be8e9b347-0",
      to: "1f409525-7df2-4bb6-b406-3e6be8e9b347-1",
    },
    {
      from: "1f409525-7df2-4bb6-b406-3e6be8e9b347-1",
      to: "2bb59c76-b54d-4b49-abbd-a0c6595d77bd-2",
    },
    {
      from: "2bb59c76-b54d-4b49-abbd-a0c6595d77bd-2",
      to: "fc386d42-4874-4e3e-bb36-2e38430a17f8-3",
    },
    {
      from: "fc386d42-4874-4e3e-bb36-2e38430a17f8-3",
      to: "append",
    },
  ],
};

Maybe just stick to TreeLayout, place the Blue nodes somewhere on the left, create whatever Links progammatically and let the Layout flow?

Your screenshot must be showing a single Diagram, yet its model has no “neo4j Query” or “Python Script” node data objects, nor links from those nodes to “DropDocletType” or “DocletTypeNode” nodes. So what is the model that you really want to show?

“neo4j Query” or “Python Script” node data objects are in the Palette Model and get dropped into the Diagram… and the Links are created by the user programmatically later on, Links may be created AND removed at user discretion…

Ah, OK. So what is the model for your screenshot?

My screenshot is a Photoshopped rendering of what I am working to accomplish. The screenshot is the goal, not my exact current Diagram working code.

Is the initial diagram always going to be a simple chain of nodes arranged vertically? Can this be modified after initialization by the user or by your code?

What can happen when the user drops a node from the Palette to the main Diagram? How many “neo4J Query” nodes might there be? How many of those blue nodes might there be? Can such nodes be connected with other nodes besides the initial ones in the vertical chain?

It’s hard to make a suggestion unless I have a better idea of what is possible.

  1. If the user drops a White Node it will be added to the existing vertical chain of White Nodes.
  2. The vertical chain of White Nodes and prepend/append Orange Nodes will not change its Layout.
  3. All Blue Nodes will be on the left as shown.
  4. Blue Nodes will never Link with each other, the relationship is 1 Blue Node to many White Nodes.
  5. There can be 1 or many Blue Nodes but we’re expecting that there will be mostly more White Nodes than Blue Nodes.
  6. The initial diagram always going to be a simple chain of White Nodes arranged vertically and if Blue Nodes had been dropped and saved from a previous save then it needs to reload the same way as explained.

Here you go, using your model data, plus a couple ImportNodes that I dropped into the Diagram and connected with Links:

This assumes that those blue ImportNodes are manually positioned.

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Editor</title>
  <!-- Copyright 1998-2024 by Northwoods Software Corporation. -->
</head>
<body>
  <div style="width: 100%; display: flex; justify-content: space-between">
    <div style="display: flex; flex-direction: column; margin: 0 2px 0 0">
      <div id="myPaletteDiv" style="flex-grow: 1; width: 200px; background-color: floralwhite; border: solid 1px black"></div>
    </div>
    <div id="myDiagramDiv" style="flex-grow: 1; height: 400px; border: solid 1px black"></div>
  </div>
  <div>
    <button id="myLoadButton">Load</button>
    <button id="mySaveButton">Save</button>
  </div>
  <textarea id="mySavedModel" style="width:100%;height:200px">
{ "class": "go.GraphLinksModel",
  "nodeDataArray": [
  {
    "category": "DropDocletType",
    "key": "prepend",
    "id": "prepend",
    "text": "Prepend Doclet Type"
  },
  {
    "category": "DocletTypeNode",
    "state": "Diagram",
    "key": "1f409525-7df2-4bb6-b406-3e6be8e9b347-0",
    "id": "1f409525-7df2-4bb6-b406-3e6be8e9b347",
    "tags": "",
    "templateIndex": "-",
    "title": "Description of Work"
  },
  {
    "category": "DocletTypeNode",
    "state": "Diagram",
    "key": "1f409525-7df2-4bb6-b406-3e6be8e9b347-1",
    "id": "1f409525-7df2-4bb6-b406-3e6be8e9b347",
    "tags": "",
    "templateIndex": "-",
    "title": "Description of Work"
  },
  {
    "category": "DocletTypeNode",
    "state": "Diagram",
    "key": "2bb59c76-b54d-4b49-abbd-a0c6595d77bd-2",
    "id": "2bb59c76-b54d-4b49-abbd-a0c6595d77bd",
    "tags": "",
    "templateIndex": "-",
    "title": "Engagement Contacts"
  },
  {
    "category": "DocletTypeNode",
    "state": "Diagram",
    "key": "fc386d42-4874-4e3e-bb36-2e38430a17f8-3",
    "id": "fc386d42-4874-4e3e-bb36-2e38430a17f8",
    "tags": "",
    "templateIndex": "-",
    "title": "Communications Plan"
  },
  {
    "category": "DropDocletType",
    "key": "append",
    "id": "append",
    "text": "Append Doclet Type"
  }
],
"linkDataArray": [
  {
    "from": "prepend",
    "to": "1f409525-7df2-4bb6-b406-3e6be8e9b347-0"
  },
  {
    "from": "1f409525-7df2-4bb6-b406-3e6be8e9b347-0",
    "to": "1f409525-7df2-4bb6-b406-3e6be8e9b347-1"
  },
  {
    "from": "1f409525-7df2-4bb6-b406-3e6be8e9b347-1",
    "to": "2bb59c76-b54d-4b49-abbd-a0c6595d77bd-2"
  },
  {
    "from": "2bb59c76-b54d-4b49-abbd-a0c6595d77bd-2",
    "to": "fc386d42-4874-4e3e-bb36-2e38430a17f8-3"
  },
  {
    "from": "fc386d42-4874-4e3e-bb36-2e38430a17f8-3",
    "to": "append"
  }
]}
  </textarea>

  <script src="go.js"></script>
  <script id="code">
const $ = go.GraphObject.make;

// initialize main Diagram
const myDiagram =
  new go.Diagram("myDiagramDiv",
    {
      layout: $(go.TreeLayout, { angle: 90, layerSpacing: 20 }),
      "undoManager.isEnabled": true
    });

function nodeStyle() {
  return [
    { locationSpot: go.Spot.Center },
    new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify)
  ];
}

myDiagram.nodeTemplate =
  $(go.Node, "Auto", nodeStyle(),
    $(go.Shape, "RoundedRectangle",
      { fill: "white", stroke: "royalblue", portId: "", toLinkable: true }),
    $(go.Panel, "Table",
      { margin: 5 },
      $(go.TextBlock,
        { font: "bold 10pt sans-serif", margin: new go.Margin(2, 2, 0, 2),
          minSize: new go.Size(16, 16), maxSize: new go.Size(160, NaN) },
        new go.Binding("text", "title")),
      $("Button",
        {
          column: 1,
          "ButtonBorder.figure": "Circle"
        },
        $(go.Shape, "XLine", { width: 8, height: 8 }))
    )
  );

myDiagram.nodeTemplateMap.add("DropDocletType",
  $(go.Node, "Auto", nodeStyle(),
    $(go.Shape, "Ellipse",
      { fill: "gold", strokeWidth: 0, portId: "", toLinkable: true }),
    $(go.TextBlock,
      { margin: new go.Margin(5, 5, 3, 5), font: "10pt sans-serif",
        minSize: new go.Size(16, 16), maxSize: new go.Size(120, NaN) },
      new go.Binding("text"))
  ));

myDiagram.nodeTemplateMap.add("ImportNode",
  $(go.Node, "Auto", nodeStyle(),
    { isLayoutPositioned: false },
    $(go.Shape, "RoundedRectangle",
      { fill: "royalblue", strokeWidth: 0, portId: "", fromLinkable: true, cursor: "pointer" }),
    $(go.TextBlock,
      { margin: new go.Margin(5, 5, 3, 5), font: "bold 10pt sans-serif", stroke: "white" },
      new go.Binding("text"))
  ));

myDiagram.linkTemplate =
  $(go.Link,
    { routing: go.Link.Orthogonal, corner: 10 },
    $(go.Shape, { strokeWidth: 2 }),
    $(go.Shape, { toArrow: "OpenTriangle", strokeWidth: 2 })
  );

// initialize Palette
const palMap = myDiagram.nodeTemplateMap.copy();
const importnode = palMap.get("ImportNode").copyTemplate();
importnode.isLayoutPositioned = true;
palMap.add("ImportNode", importnode);
myPalette =
  new go.Palette("myPaletteDiv",
    {
      layout: $(go.GridLayout, { wrappingColumn: 1, alignment: go.GridLayout.Location }),
      initialAutoScale: go.Diagram.UniformToFill,
      nodeTemplateMap: palMap,
      groupTemplate:
        $(go.Group,
          {
            locationSpot: go.Spot.Center,
            layout: $(go.GridLayout, { wrappingColumn: 1 })
          },
          $(go.Placeholder)
        ),
      model: new go.GraphLinksModel([
  {
    "key": 1,
    "text": "Import Nodes",
    isGroup: true,
    "category": "Imports",
  },
  {
    "key": 2,
    isGroup: true,
    "category": "PaletteDocletGroup",
  },
  {
    "category": "ImportNode",
    group: 1,
    isAssistant: true,
    "key": -1,
    "state": "Palette",
    "text": "PCD",
  },
  {
    "category": "ImportNode",
    isAssistant: true,
    group: 1,
    "key": -2,
    "state": "Palette",
    "text": "neo4j Query",
  },
  {
    "category": "ImportNode",
    isAssistant: true,
    group: 1,
    "key": -3,
    "state": "Palette",
    "text": "Python Script",
  },
  {
    "category": "ImportNode",
    isAssistant: true,
    group: 1,
    "key": -4,
    "state": "Palette",
    "text": "R Script",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "a34cc470-584f-491d-852c-e337b03ba9a9",
    "key": "b3dbd719-33f5-45bd-bba1-ad5cd152369f",
    "state": "Palette",
    "tags": "",
    "templateIndex": 0,
    "title": "Approach",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "94358ae0-c808-46f1-bee1-ceb18d65e387",
    "key": "9a444497-0183-4998-b790-011f65a8d8ae",
    "state": "Palette",
    "tags": "",
    "templateIndex": 1,
    "title": "Assumptions",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "eea7c2f2-a5c8-4e27-981e-b99add938e4f",
    "key": "407e8e11-dd29-474d-9bd3-81f61fc83334",
    "state": "Palette",
    "tags": "",
    "templateIndex": 2,
    "title": "Change Order Process",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "6feb527c-d956-46f5-8cc1-42261be3a0ff",
    "key": "91223f02-c8be-4cd4-a344-4e4bdee74f0c",
    "state": "Palette",
    "tags": "",
    "templateIndex": 3,
    "title": "Charges, Expenses and Invoicing",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "fc386d42-4874-4e3e-bb36-2e38430a17f8",
    "key": "adbee4fd-e067-42c1-887a-f60d0460a8d4",
    "state": "Palette",
    "tags": "",
    "templateIndex": 4,
    "title": "Communications Plan",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "c145e9fd-66c7-47d2-9cd9-b1aa5f0e9906",
    "key": "a495b561-c7a6-42ea-b4fc-92999bf3ba39",
    "state": "Palette",
    "tags": "",
    "templateIndex": 5,
    "title": "Deliverables",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "1f409525-7df2-4bb6-b406-3e6be8e9b347",
    "key": "34a15cc6-7e1a-40c1-9c41-791a6f9a71da",
    "state": "Palette",
    "tags": "",
    "templateIndex": 6,
    "title": "Description of Work",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "2bb59c76-b54d-4b49-abbd-a0c6595d77bd",
    "key": "9aa40170-bf05-4b5a-95e3-3d88b43f827e",
    "state": "Palette",
    "tags": "",
    "templateIndex": 7,
    "title": "Engagement Contacts",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "bc98aa1c-8a5a-444c-b41a-191cf5cfa261",
    "key": "1a9fe4a6-2ec3-4e82-9137-dc1ff4cad7d1",
    "state": "Palette",
    "tags": "",
    "templateIndex": 8,
    "title": "Escalation Process",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "46f32999-4fd4-46fd-a49b-d2ffb1e90533",
    "key": "c8523b52-07c2-4750-bf2e-821de65c8553",
    "state": "Palette",
    "tags": "",
    "templateIndex": 9,
    "title": "Initiation of Work",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "e34723c4-efd1-48e5-b134-c16475362833",
    "key": "ede62a24-3d17-49bd-aaf7-ab126e89a3cb",
    "state": "Palette",
    "tags": "",
    "templateIndex": 10,
    "title": "Introduction",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "6c12812b-5cf4-4e6f-bce2-16afccfb91c0",
    "key": "58be694e-7cf7-495f-88ee-412586e04ddd",
    "state": "Palette",
    "tags": "",
    "templateIndex": 11,
    "title": "IT&S Responsibilities",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "c4330a2c-d559-4800-8d41-b178e29ee1f3",
    "key": "1612b684-9cf8-4bb5-b308-3261edb82bb0",
    "state": "Palette",
    "tags": "",
    "templateIndex": 12,
    "title": "Kickoff Meeting",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "91177f3a-3c6d-40ea-bb76-7121fd6580f5",
    "key": "2603513c-02e2-40a7-a150-ef36b320cb8f",
    "state": "Palette",
    "tags": "",
    "templateIndex": 13,
    "title": "Project Dependencies",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "c42d5d77-4adc-40b4-a651-eb44d27958b4",
    "key": "5f7704ea-da1d-4989-969d-1e6581a460f0",
    "state": "Palette",
    "tags": "",
    "templateIndex": 14,
    "title": "Timeline",
  },
  {
    "category": "DocletTypeNode",
    group: 2,
    "id": "b8e39e14-24bc-4b87-af6a-845d56ebf405",
    "key": "a31e75d3-6a15-458c-aa27-443bf85b3119",
    "state": "Palette",
    "tags": "",
    "templateIndex": 15,
    "title": "TOC",
  },
])
    });

// save a model to and load a model from Json text, displayed below the Diagram
function save() {
  const str = myDiagram.model.toJson();
  document.getElementById("mySavedModel").value = str;
}
document.getElementById("mySaveButton").addEventListener("click", save);

function load() {
  const str = document.getElementById("mySavedModel").value;
  myDiagram.model = go.Model.fromJson(str);
}
document.getElementById("myLoadButton").addEventListener("click", load);

load();
  </script>
</body>
</html>

Hello and thank you. I implemented your suggested code but I do not see your code for actually placing the Node programmatically so, this is the steps I’m working on and struggling with.

I typed all detailed steps in the README.md file to make things easier, hopefully.

Here’s the Git repo: Public Repo, branch name: Ale/side-tree-layout

Note that in my sample Diagram.layout is set to a TreeLayout, so that causes the tree structure (well, column).

But the ImportNode template has Part.isLayoutPositioned set to false, so those Nodes are never automatically laid out – the TreeLayout ignores them.

Yes, I know… I explained that in my README file…

It’s worth noting that we’re aiming to use the same Node template for both the Palette and Diagram

You only define the node template once. The other one is copied with isLayoutPositioned set to the opposite value.

Alternatively you could use exactly the same template as the main Diagram’s and add a listener to the Palette that sets isLayoutPositioned to true on those kinds of Nodes.

Ok but still, even when I set isLayoutPositioned: false on the Template, when I Drop it from the Palette, it does not get programmatically positioned to new go.Point(1000, 1000)

The isLayoutPositioned prop is a different issue that as you said, I could toggle accordingly, I can deal with that after I manage to position a Node programmatically.

If the user drag-and-drops a Node, the DraggingTool will assign its location to be wherever it was dropped. A subsequent layout may change its location. But adding a node with isLayoutPositioned false will not invalidate the layout, so the layout won’t be performed again.

But you want all nodes in the Palette to be laid out, which is why it’s important that isLayoutPositioned is true there.

ok. I still don’t understand how to position a Node programmatically based on your reply… Do I have to use the DraggingTool?