Alignment spread to all nodes

Hi Walter. I have a problem with dragging panel inside adornment. To dragging I change alignment value but if I change it value on one node according values change on other node too. I think problem with copyNodeDataFunction in model. I setted it (data) => JSON.parse(JSON.stringify(data)) but it not helped me.

function to dragging

const handleMoveAdornmentPanel = (evt, obj) => {
  const { position } = obj.part;
  const { documentPoint } = evt;
  let dx = Math.abs(position.x - documentPoint.x);
  let dy = Math.abs(position.y - documentPoint.y);
  if (documentPoint.x - position.x < 0) {
    dx = (-1) * dx;
  }
  if (documentPoint.y - position.y < 0) {
    dy = (-1) * dy;
  }
  const newSpot = new go.Spot(0, 0, dx, dy);
  obj.alignment = newSpot;
};

Node data model

{
  key: 1,
  adornmentList: [
    {
      _id: '',
     path: '',
    sittings: {
      alignment: '0, 0, 0, 0'
      }
    }
  ],
}

My adornment

const MyAdornment = () => $(
  go.Adornment,
  'Spot',
  {
    zOrder: 2,
  },
  $(
    go.Panel,
    'Auto',
    $(go.Shape, {
      fill: null,
      strokeWidth: 0,
      stroke: 'black',
    }),
    $(go.Placeholder, { margin: 75 }),
  ),
  new go.Binding('itemArray', 'adornmentList'),
  {
    itemTemplateMap: adornmentTemplateMap,
  },
);

When a node data object is copied, by default it makes a shallow copy. In simple cases, perhaps you can just set Model.copiesArrays and Model.copiesArrayObjects to true, but I suspect that won’t work for you because that wouldn’t copy the “sittings” Object.

So you’ll need to define a function that copies the data the way that you want, and assign that to Model.copyNodeDataFunction. Remember not to copy the “__gohashid” property.

Are there any examples or finally resolve in gojs?

not run when I dragging panel in Adornment.

I would not expect movement to cause any copying of nodes, unless the user is using the DraggingTool and the user is holding down the control key to force a copy operation.

So, do you have a custom Tool that implements movement of Panels within an Adornment? Is handleMoveAdornmentPanel called by this new tool? But it does not copy any node data, and I would not expect it to do so.

No, I did not have custom tool. handleMoveAdornmentPanel is set in some item of adornmentTemplateMap on mouseMove event.

Ah, I see that you are trying to use ActionTool, by setting isActionable to true and implementing action… event handlers.

That should work if you are careful. Here’s an example:

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Sample</title>
  <!-- Copyright 1998-2022 by Northwoods Software Corporation. -->
</head>
<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
  <textarea id="mySavedModel" style="width:100%;height:250px"></textarea>

  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
const $ = go.GraphObject.make;

const myDiagram =
  $(go.Diagram, "myDiagramDiv",
    {
      "undoManager.isEnabled": true,
      "ModelChanged": e => {     // just for demonstration purposes,
        if (e.isTransactionFinished) {  // show the model data in the page's TextArea
          document.getElementById("mySavedModel").textContent = e.model.toJson();
        }
      }
    });

myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    $(go.Shape,
      { fill: "white" },
      new go.Binding("fill", "color")),
    $(go.TextBlock,
      { margin: 28 },
      new go.Binding("text")),
    {
      selectionAdornmentTemplate:
        $(go.Adornment, "Spot",
          $(go.Placeholder, { background: "rgba(255,255,255,0.3)" }),
          new go.Binding("itemArray", "spots"),
          {
            itemTemplate:
              $(go.Panel,
                new go.Binding("alignment", "a", v => {
                    const p = go.Point.parse(v);
                    return new go.Spot(0, 0, p.x, p.y);
                  }).makeTwoWay(s => go.Point.stringify(new go.Point(s.offsetX, s.offsetY))),
                $(go.Shape, "Circle", { width: 8, height: 8, strokeWidth: 0 },
                  new go.Binding("fill", "c")),
                {
                  isActionable: true,
                  actionDown: (e, pan) => e.diagram.startTransaction(),
                  actionUp: (e, pan) => e.diagram.commitTransaction("moved adornment item"),
                  actionCancel: (e, pan) => e.diagram.rollbackTransaction(),
                  actionMove: (e, pan) => {
                    const p = pan.part.adornedObject.getDocumentPoint(go.Spot.TopLeft);
                    const q = e.documentPoint;
                    pan.alignment = new go.Spot(0, 0, q.x - p.x, q.y - p.y);
                  }
                }
              )
          }
        )
    }
  );

myDiagram.model = new go.GraphLinksModel(
  {
    copiesArrays: true,  // copy "spots" Array
    copiesArrayObjects: true,  // copy item descriptors in "spots" Array
    nodeDataArray:
      [
        { key: 1, text: "Alpha", color: "lightblue", spots: [ { a: "0 0", c: "red" }, { a: "20 10", c: "green" }, { a: "50 30", c: "blue" } ] },
        { key: 2, text: "Beta", color: "lightgreen", spots: [ { a: "30 50", c: "green" } ] }
      ]
  });
  </script>
</body>
</html>