Group resize breaks group

We’re having a problem manually resizing groups in our diagram. If a group is resized, the nodes inside of it can then be placed outside the bounds of the group without it growing to fit. The nodes still move with the group when it’s dragged around, so they seem to still be members of it, but they’re no longer contained within its borders.

The “Regrouping Demo” is very similar to the kinds of graphs we need to make and if I take that sample and add “ungroupable: true” and “resizable: true” I can reproduce the problem.

Is there something else we need to do after resize? Could the problem be related to using padding in our groups?

Thanks

Have you customized the ResizingTool so that when resizing a Group it prevents it from getting smaller than the area needed to cover the member parts?

For example, see the override of ResizingTool.computeMinSize in the GroupResizingTool of the SwimLanes sample, and the functions that it calls.

Yes, I’m using a modified version of the code from the SwimLanes example with this.adornedObject being passed into computeMinPlaceholderSize since I want the min size of only the group currently being resized, not of all groups in the diagram.

        function computeMinPlaceholderSize(group) {
            var minWidth = MINLENGTH;
            var minHeight = MINBREADTH;
            var sz = group.placeholder.actualBounds;
            return new go.Size(Math.max(minWidth, sz.width), Math.max(minHeight, sz.height));
        }


        GroupResizingTool.prototype.computeMinSize = function() {
            var msz = computePlaceholderSize(null);  // get the minimum size
            var sz = computeMinPlaceholderSize(this.adornedObject);
            msz.width = Math.max(msz.width, sz.width);
            msz.height = Math.max(msz.height, sz.height);
            return msz;
        }


        myDiagram = $(go.Diagram, "myDiagram", {
           resizingTool: new GroupResizingTool()
        });

This does keep the group from being made smaller than the nodes within it, but does not keep the nodes from being removable from the group once it’s been manually resized.

This property on the node template:
dragComputation: stayInGroup
prevents users from moving nodes out of their own groups. stayInGroup is a function defined earlier in the file.

Using stayInGroup causes the node to stop at the border of the group instead of growing the group dimensions with the node movement the way it does by default for groups with padding.

Is it possible to allow users to manually adjust the group size without allowing nodes to be removed from the group while still maintaining the behavior of growing the group in the direction of the node being dragged?

Oh, I thought that was what you wanted. OK, if you don’t want to constrain the movement of the nodes, don’t specify the dragComputation property (or the minLocation or maxLocation properties).

But I don’t understand what you want. If the user explicitly resizes a group, do you want movement of one of its nodes to automatically discard that sizing so that the group becomes the size it would naturally want to be to cover all of its members? If so, you don’t want to set Group.computesBoundsAfterDrag to true, and you might want to customize the DraggingTool so that it resets the desiredSize of the group (or more likely, of the resizeObject of the group) so that the size of the group as determined by the Placeholder is no longer constrained by the artificial desiredSize determined by the last resizing. You accomplish that by setting desiredSize to new go.Size(NaN, NaN).

I think I’m starting to understand the different sizes and how they affect the group, but I’m still having trouble getting the correct behavior. If I manually resize the group (say larger) and then set desiredSize to go.Size(NaN, NaN) in our custom DraggingTool (the stayInGroup function) it jumps back to its original, smaller size when I move a node. Is there something I need to set to the new, manually sized width and height before setting desiredSize back to NaN to make it stay the size the user manually set it to?

The ResizingTool sets the desiredSize of the Part.resizeObject, which is the GraphObject named by Part.resizeObjectName, to a “real” Size.

The stayInGroup function is completely unrelated to the (perhaps custom) ResizingTool. I am guessing that you do not need this function, because my current impression is that you want to allow users to move nodes as far as they want. The Group will automatically get bigger and smaller as its member Nodes are moved around, because the Group has a Placeholder.

The user’s resizing of a group and the user’s movement of a group’s member node(s) inherently conflict in the determination of the size of the group. I still do not understand what policy you want to have to manage this conflict.

If possible, we want two mechanisms to change the group size in a single diagram:

  1. The user is moving a node, hits the edge of the group and the group automatically grows as the node is dragged. I believe this is the default behavior we see for groups with padding.

  2. The user resizes the group by selecting the edge of the group and dragging it to the desired size.

Once they were done manually resizing the group by dragging the border (option 2), we’d still like for them to also continue being able to resize the group by moving nodes (option 1). Can these coexist in the same diagram or must we use one method or the other?

Yes, they can coexist, but you need to decide how.

For example, one obvious solution would be to have the effective size be the union of the desiredSize (due to resizing) and the computed bounds (due to the Placeholder). But note then that the size would never get smaller unless the user positioned the nodes to be in a small area and then explicitly resized to be smaller. This might be OK for your app, or you might consider that burdensome for your users.

In case it wasn’t clear from my last post, that is about what the Swim Lanes sample does, except that it does impose the dragComputation limitation implemented by that stayInGroup function. Just remove that assignment of Node.dragComputation.

Note that the Swim Lanes sample also adds a Diagram.mouseDrop event handler that cancels the dragging operation. This prevents users from moving a node onto the background of the diagram, i.e. outside of a Group/lane. You can just remove the assignment of Diagram.mouseDrop if you don’t like that movement restriction.

That helps, thanks. I’ll check out Swim Lanes in more detail.

@dmgillha I am looking for exactly same solution. Were you able to implement this ? If yes, can you please share a snippet of code ?