Overriding draggingTool.moveParts

Hello!

I am struggeling with the following task:

In my diagram, it is possible to group objects. This is done by giving each selected element a groupId. I need this grouping for various reasons, for example exporting parts of the diagram, naming groups etc.

All those things work already in the way intented, however, it also should be possible to move the whole group, even if only one part of the group is selected.

Untitled

In this example, element “2” is selected. Moving element “2” should make “1” and “2” move too.

Also, if “2” and “4” where selected, it would mean to move all elements that are in either group, which basically means to move all 6 elements.

I saw that there is a grouping functionality in goJS:https://gojs.net/latest/intro/groups.html
However, I found this only recently and am already nearly finished with my own approach. The only part missing is to extend the “moveParts” method. Here is the code I came up with until now:
image

Basically, I need to add other parts to the “parts” map, but i dont know which values I should provide here.
Note that by just adding to “parts”, the actual selected node gets added too, which means it is in the map a second time.

Thank you for your help in advance.

Best regards,
Martin

Ah, you want to override DraggingTool.computeEffectiveCollection, which is what determines which Parts are dragged. https://gojs.net/latest/api/symbols/DraggingTool.html#computeEffectiveCollection
For example, the DraggingTool.dragsTree property controls which additional nodes and links (the subtree) are dragged along. In your case you want to include all of the other group members.

I don’t think we have an existing sample that does exactly what you want, but one that is very similar is the Seating Chart sample: https://gojs.net/latest/samples/seatingChart.html

Edit:

I found the problem, thats the way it is supposed to be:

Thank you for your fast reply. This is indeed the functionality I am looking for.

Interestingly, extending this method does produce errors:

The method is called and the breakpoint inside the “computeEffectiveCollection” is hit

Every subsequent events result in this error, the breakpoint is not hit anymore:

Did I misunderstand something? Maybe it has to do with the following:

Thats why I tried it by using the commandHandler directly:

However, this results in the same exact behaviour and errors.

Thank you so much for your help, everything is working perfectly fine!

This is the code I used:

image

There are two flaws though, which I don’t know if they are a problem:

  • I am using “node.location.copy()”. I looked into this:https://gojs.net/latest/api/symbols/Point.html , but I did not find anything like “node.location.move”. It still works, however.
  • I am not excluding the elements which are in the map already, but this also does not seem to do any harm.

Anyways, thanks for your help! Problem solved.

Meanwhile I developed a sample for you. I think the override of DraggingTool.computeEffectiveCollection can be simpler than that:

<!DOCTYPE html>
<html>
<head>
<title>Minimal GoJS Sample</title>
<!-- Copyright 1998-2019 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="go.js"></script>
<script id="code">
  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
          {
            "undoManager.isEnabled": true,
            "draggingTool.computeEffectiveCollection": function(parts, options) {
              var all = new go.List();
              parts.each(function(p) {
                all.add(p);
                if (p.containingGroup !== null && !(p instanceof go.Link)) {
                  all.add(p.containingGroup);
                }
              });
              return go.DraggingTool.prototype.computeEffectiveCollection.call(this, all, options);
            }
          });

    myDiagram.nodeTemplate =
      $(go.Node, "Auto",
        { width: 100, height: 100, resizable: true },
        $(go.Shape,
          { fill: "green" },
          new go.Binding("fill", "color")),
        $(go.TextBlock,
          { margin: 8 },
          new go.Binding("text"))
      );

    myDiagram.groupTemplate =
      $(go.Group, "Vertical",
        $(go.TextBlock,
          { font: "14pt sans-serif" },
          new go.Binding("text")),
        $(go.Placeholder),
        {
          layout: $(go.GridLayout, { wrappingColumn: 1, cellSize: new go.Size(1, 1), spacing: new go.Size(10, 10) })
        }
      );

    myDiagram.model = new go.GraphLinksModel(
    [
      { key: -1, text: "Group1", isGroup: true },
      { key: -2, text: "Group2", isGroup: true },
      { key: 1, text: "Alpha", group: -1 },
      { key: 2, text: "Beta", color: "orange", group: -1 },
      { key: 3, text: "Gamma", color: "lightgreen", group: -1 },
      { key: 4, text: "Delta", color: "pink", group: -2 },
      { key: 4, text: "Epsilon", color: "yellow", group: -2 }
    ]);
  }
</script>
</head>
<body onload="init()">
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
</body>
</html>

Hello walter, I have to come back to this topice once more.

As you saw in the code I posted, I now alter the collection of moved objects by extending “computeEffectiveCollection”. This works perfectly fine.

However, there is a problem. Refer to the image for understanding

The left two squares are group 1, the right two squares are group 2. Grid snapping is enabled.

If I move any of the elements in group 1, the other element also moves. Because of grid snapping, Both elements always jump by 5 units.

However, group 2 is different. the element “x” is not snapped to the grid (see gap “A”), because, in my application, I can always disable gridsnapping, move them by 1 unit with the arrow keys, or use intelligent snapping (Snapping to other objects).
If I move the element “y” to the right for example, the following will happen:

  • The element “y” will not move until the mouse moved at least enough to the right to trigger the snapping on the next grid-line “B”
    -The element “x”, because it is grouped, will also move to the right. Because “x” is already closer to line “C” than “y” is to line “B”, it will snap sooner:
    image

This means that the fine adjustment is lost as soon as I move any group with objects that are not snapped to the grid. (while gridsnapping is enabled, naturally)

So in order to prevent that, I need to flag all other elements in “computeEffectiveCollection” in a way so that they are not affected by gridsnapping, but by the position of the element which is dragged itself. Any clues on how to achieve this kind of behaviour?

You can control dynamically for each Part being dragged whether to snap to grid or not. Either specify a smarter https://gojs.net/latest/api/symbols/Part.html#dragComputation or override https://gojs.net/latest/api/symbols/DraggingTool.html#computeMove.