Spacing when dragging External Objects Into Diagram

Hello,
I am using go.js 2.3.5 from within react components, with chrome.
My question is about panning external objects from an external diagram into my diagram.
Specifically my wish is to be able to control the spacing between my objects as they are panned.

Currently my problem is that the panned objects overlap one another (in 10-20px) and enforce the user to separate them after they are dropped.

The requirement is that already during the panning and after they are dropped, they will be spaced.
However, I do not wish that spacing specification to impact other objects that are already part of my diagram. Their layout must stay intact as it was before the panning.

Already tried:
diagram.model.addChangedListener

this responded in the proper timing, and I saw concrete values for:
e.modelChange, e.change.name, e.model.nodeDataArray
however, when panned more than 1 component, it was triggered separately for each one of them.
In addition, accessing
e.diagram
was a dead end (null)

Also tried:
diagram.addDiagramListener('ExternalObjectsDropped', (e: go.DiagramEvent) => {
this responded but only after dropping the panned objects, which is a little bit late.
Also, it is unclear to me at this stage how to change the spacing between the objects.

So:
What is the correct way to control/enforce panning of new objects from outside into my diagram?

Screenshot:
forForumQuestion

Based on your descriptions, I believe the term you intended to use is “dragging”, not “panning”. I have updated the title accordingly.

Are you just asking to make sure that when the user performs an external drag-and-drop into a diagram that the dropped nodes not overlap with the pre-existing nodes? Something like: Drag Unoccupied

No,
I don’t mind about pre-existing nodes in the target diagram. (Overlapping with them is up to the user).
It’s those “dropped nodes” I care about. I don’t want overlapping among themselves (During dragging and right after dropping), exactly as you can see in the attached screenshot which I hope is visible in the post.
I want to spare the user from the constant need of arranging those nodes after dropping them onto the diagram.

Normally the automatic location of nodes is the responsibility of a Layout, but I suspect you don’t want that. I think you want to either implement an “ExternalObjectsDropped” DiagramEvent listener to arrange the e.subject collection after having been dropped, or else override DraggingTool.computeEffectiveCollection in the source Diagram to call the super method first, arrange the results, and then return the collection.

1 Like

Concerning your 2nd suggestion, can you please provide an example of how to do it?
I see a lot of example which use the following as part of calling the suprt method.
go.DraggingTool.prototype.computeEffectiveCollection.call(this…
but I cannot figure out why in my case I end up with ‘this’ as null or undefined during runtime.

This just cascades the dragged nodes to overlap each other, with a Y offset of 10. Customize the code to arrange them the way that you want.

  $(go.Palette, "myPaletteDiv",
    {
      "draggingTool.computeEffectiveCollection": function(parts, options) {
        const coll = go.DraggingTool.prototype.computeEffectiveCollection.call(this, parts, options);
        // arrange dragged nodes to overlap in Y direction
        const pair = coll.first();
        let y = pair ? pair.key.location.y : 0;
        coll.each(kvp => {  // key-value-pair: key is a Part, value is an Object with location property
          kvp.value.point = new go.Point(kvp.key.location.x, y);
          y += 10;
        });
        return coll;
      },
      "draggingTool.doDeactivate": function() {
        go.DraggingTool.prototype.doDeactivate.call(this);
        this.diagram.layoutDiagram(true);  // restore normal positions for nodes in palette
      },
      nodeTemplateMap: myDiagram.nodeTemplateMap,
      model: new go.GraphLinksModel([
        { text: "red node", color: "red" },
        { text: "green node", color: "green" },
        { text: "blue node", color: "blue" },
        { text: "orange node", color: "orange" }
      ])
    })

OK,
I’ve ended up using ExternalObjectsDropped DiagramEvent which was perfectly fine.
Thank you very much!