Swim Lanes subGraphExpandedChanged height problem

when we resize and stretch any lane it distorts the height of other lanes

Image 1


Image 2

Image 3

My Code:

function getLaneGroupTemplate(helper, readonly) {
    var changeResizeObject = function (diagram, node, objectName) {
        diagram.startTransaction();
        node.resizeObjectName = objectName;
        node.removeAdornment("Resizing");
        node.updateAdornments();

        if (node.containingGroup) {
            node.containingGroup.memberParts.each(function (lane) {
                if (!(lane instanceof go.Group)) return;
                lane.resizeObjectName = objectName;
            });
        }

        diagram.commitTransaction("changed resizeObjectName");
    };

    return GO(go.Group, "Spot", groupStyle(),
        {
            name: "Lane",
            zOrder: 1,
            copyable: true,
            selectionObjectName: "SHAPE",  // selecting a lane causes the body of the lane to be highlit, not the label
            resizable: true, resizeObjectName: "SHAPE",  // the custom resizeAdornmentTemplate only permits two kinds of resizing
            computesBoundsAfterDrag: true,  // needed to prevent recomputing Group.placeholder bounds too soon
            computesBoundsIncludingLinks: false,  // to reduce occurrences of links going briefly outside the lane
            computesBoundsIncludingLocation: true,  // to support empty space at top-left corner of lane
            handlesDragDropForMembers: true,  // don't need to define handlers on member Nodes and Links
            mouseDrop: function (e, lane) {  // dropping a copy of some Nodes and Links onto this Group adds them to this Group
                setTimeout(function () {
                    var pool = lane.containingGroup;
                    var multiLanesParts = new go.List();
                    pool.memberParts.each(function (part) {
                        if (part.data && part.data.multiLanes && !multiLanesParts.contains(part)) {
                            multiLanesParts.add(part);
                        }
                    });
                    if (pool.data.isVertical) {
                        multiLanesParts.each(function (part) {
                            pool.memberParts.each(function (lane) {
                                if (lane instanceof go.Group) {
                                    if (lane.key === part.data.multiLanes[1]) {
                                        var partBounds = part.actualBounds;
                                        var laneBounds = lane.actualBounds;
                                        var isShift = part.data.category === "event" || part.data.category === "activity" || part.data.category === "gateway" || part.data.category === "annotation" || part.data.category === "dataobject" || part.data.category === "datastore" || part.data.category === "privateProcess";
                                        if (!isShift && part.data.multiLanes.length <= 2) {
                                            part.move(new go.Point(laneBounds.x + laneBounds.width - partBounds.width / 2, partBounds.y));
                                        }
                                    }
                                }
                            });
                        });
                    } else {
                        multiLanesParts.each(function (part) {
                            pool.memberParts.each(function (lane) {
                                if (lane instanceof go.Group) {
                                    if (lane.key === part.data.multiLanes[1]) {
                                        var partBounds = part.actualBounds;
                                        var laneBounds = lane.actualBounds;
                                        var isShift = part.data.category === "event" || part.data.category === "activity" || part.data.category === "gateway" || part.data.category === "annotation" || part.data.category === "dataobject" || part.data.category === "datastore" || part.data.category === "privateProcess";
                                        if (!isShift && part.data.multiLanes.length <= 2) {
                                            part.move(new go.Point(partBounds.x, laneBounds.y + laneBounds.height - partBounds.height / 2));
                                        }
                                    }
                                }
                            });
                        });
                    }
                }, 0);
            },
            click: function (e, obj) {
                changeResizeObject(e.diagram, obj.part, "SHAPE");
            },
            selectionChanged: function (e) {
                changeResizeObject(e.diagram, e, "SHAPE");
            },
            subGraphExpandedChanged: function (grp) {
                changeResizeObject(grp.diagram, grp, "SHAPE");
                var shp = grp.resizeObject;
                if (grp.diagram.undoManager.isUndoingRedoing) return;
                if (grp.containingGroup.data.isVertical) {
                    if (grp.isSubGraphExpanded) {
                        shp.width = grp._savedBreadth;
                    }
                    else {
                        grp._savedBreadth = shp.width;
                        shp.width = NaN;
                    }
                }
                else {
                    if (grp.isSubGraphExpanded) {
                        shp.height = grp._savedBreadth;
                    }
                    else {
                        grp._savedBreadth = shp.height;
                        shp.height = NaN;
                    }
                }

                grp.data.isSubGraphExpanded = grp.isSubGraphExpanded;

                updateCrossLaneLinks(grp);
                relayoutDiagram(grp.diagram);
            }
        },
        {
            selectionAdorned: true,
            selectionAdornmentTemplate:
                GO(go.Adornment, "Auto",
                    GO(go.Shape, { stroke: "dodgerblue", fill: null }),
                    GO(go.Placeholder, { margin: 0 }))
        },
        {
            resizeAdornmentTemplate: GO(go.Adornment, "Spot",
                GO(go.Placeholder),
                GO(go.Shape,  // for changing the length of a lane
                    {
                        alignment: go.Spot.Right,
                        desiredSize: new go.Size(7, 50),
                        fill: "lightblue", stroke: "dodgerblue",
                        cursor: "col-resize"
                    },
                    new go.Binding("visible", "", function (ad) {
                        if (ad.adornedPart === null) return false;
                        return ad.adornedPart.isSubGraphExpanded && (ad.adornedObject.part.resizeObjectName != "HEADER" || !ad.adornedObject.part.containingGroup.data.isVertical);
                    }).ofObject()),
                GO(go.Shape,  // for changing the breadth of a lane
                    {
                        alignment: go.Spot.Bottom,
                        desiredSize: new go.Size(50, 7),
                        fill: "lightblue", stroke: "dodgerblue",
                        cursor: "row-resize"
                    },
                    new go.Binding("visible", "", function (ad) {
                        if (ad.adornedPart === null) return false;
                        return ad.adornedPart.isSubGraphExpanded && (ad.adornedObject.part.resizeObjectName != "HEADER" || ad.adornedObject.part.containingGroup.data.isVertical);
                    }).ofObject())
            )
        },
        new go.Binding("minLocation", "", function (val, node) {
            return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? new go.Point(-Infinity, NaN) : new go.Point(NaN, -Infinity);
        }),
        new go.Binding("maxLocation", "", function (val, node) {
            return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? new go.Point(Infinity, NaN) : new go.Point(NaN, Infinity);
        }),
        new go.Binding("background", "font", function (val, node) {
            return val && val.backgroundColor ? val.backgroundColor : '#fff';
        }),
        GO(go.Shape, "Rectangle",  // this is the resized object
            { name: "SHAPE", fill: "lightBlue", stroke: "lightBlue", height: 100, margin: new go.Margin(0, 0, 0, 0), strokeWidth: 0 },  // need stroke null here or you gray out some of pool border.
            new go.Binding("stroke", "", function (val) {
                return helper._getBorderColor(val);
            }),
            new go.Binding("fill", "", function (node) {
                var curColor = helper._getBackgroundColor(node.data);

                if (node.isHighlighted) {
                    return curColor ? go.Brush.darkenBy(curColor, 0.05) : "rgba(0,0,0,0.05)"
                }
                return curColor;
            }).ofObject(),
            new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify)
        ),
        // header ın altındaki düz çizgi
        GO(go.Shape, "Rectangle",
            {
                fill: "#AAA",
                strokeWidth: 0,
                //strokeDashArray: [1, 0],
                //strokeDashOffset: 0,
                alignment: go.Spot.BottomLeft,
                alignmentFocus: go.Spot.TopLeft,
                height: 1,
                width: 100
            },
            new go.Binding("alignment", "", function (node) {
                return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.TopRight : go.Spot.BottomLeft;
            }).ofObject(),
            new go.Binding("width", "", function (node) {
                if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                    return 1;
                }
                else {
                    return node.data.headerSize ? node.data.headerSize : 100;
                }
            }).ofObject(),
            new go.Binding("height", "", function (node) {
                if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                    return node.data.headerSize ? node.data.headerSize : 100;
                }
                else {
                    return 1;
                }
            }).ofObject(),
            new go.Binding("fill", "", function (val) {
                return _getLaneBorderVisible(val) ? "#AAA" : "rgba(0,0,0,0.1)";
            }).ofObject()
        ),

        // dash ler
        GO(go.Shape, "Rectangle",
            {
                stroke: "#CCC",
                //strokeWidth: 1,
                //strokeDashArray: [10, 6],
                //strokeDashOffset: 100, // IE9 da dash array görünmediği için kapatıldılar
                alignment: go.Spot.BottomRight,
                alignmentFocus: go.Spot.TopRight,
                height: 0,
                background: "#CCC"
            },
            new go.Binding("alignmentFocus", "", function (node) {
                return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.BottomLeft : go.Spot.TopRight;
            }).ofObject(),
            new go.Binding("width", "", function (node) {
                if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                    return 0;
                }
                else {
                    var s = go.Size.parse(node.data.size);
                    var calc = s.width - (node.data.headerSize ? node.data.headerSize : 100);
                    return calc > 0 ? calc : 0;
                }
            }).ofObject(),
            new go.Binding("height", "", function (node) {
                if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                    var s = go.Size.parse(node.data.size);
                    var calc = s.height - (node.data.headerSize ? node.data.headerSize : 100);
                    return calc > 0 ? calc : 0;
                }
                else {
                    return 0;
                }
            }).ofObject(),

            new go.Binding("opacity", "", function (val) {
                return _getLaneBorderVisible(val) ? 1 : 0;
            }).ofObject()
        ),

        // header
        GO(go.Panel, "Vertical",
            //new go.Binding("desiredSize", "headerSize", go.Size.parse),
            {
                name: "HEADER",
                //width: 100,
                //angle: 270,  // maybe rotate the header to read sideways going up
                alignment: go.Spot.LeftCenter, alignmentFocus: go.Spot.LeftCenter,
                background: "rgba(0,0,0,0.1)",
                stretch: go.GraphObject.Vertical,
                click: function (e, obj) {
                    changeResizeObject(e.diagram, obj.part, "HEADER");

                    e.handled = true;
                },
                doubleClick: function (e, obj) {
                    if (!readonly) {
                        helper.openOrganizationSelection(true, function (data) {
                            if (data) {
                                obj.part.diagram.model.startTransaction("change lane data");
                                obj.part.diagram.model.setDataProperty(obj.part.data, "externalDataLane", data);
                                obj.part.diagram.model.commitTransaction("change lane data");
                            }
                        });
                    }
                },
                contextMenu: GO(go.Adornment, "Spot",
                    {
                        visible: !readonly
                    },
                    GO(go.Placeholder),
                    GO("ContextMenuButton",
                        {
                            alignment: go.Spot.Top,
                            alignmentFocus: go.Spot.Bottom
                        },
                        new go.Binding("alignment", "", function (obj) {
                            var node = obj.part.adornedPart;
                            return node && node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.Left : go.Spot.Top;
                        }).ofObject(),
                        new go.Binding("alignmentFocus", "", function (obj) {
                            var node = obj.part.adornedPart;
                            return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.Right : go.Spot.Bottom;
                        }).ofObject(),
                        GO(go.TextBlock, "+")
                    ),
                    GO("ContextMenuButton",
                        {
                            alignment: go.Spot.Bottom,
                            alignmentFocus: go.Spot.Top
                        },
                        new go.Binding("alignment", "", function (obj) {
                            var node = obj.part.adornedPart;
                            return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.Right : go.Spot.Bottom;
                        }).ofObject(),
                        new go.Binding("alignmentFocus", "", function (obj) {
                            var node = obj.part.adornedPart;
                            return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.Left : go.Spot.Top;
                        }).ofObject(),
                        GO(go.TextBlock, "+")
                    )
                )
            },
            new go.Binding("alignment", "", function (node) {
                return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.TopCenter : go.Spot.LeftCenter;
            }).ofObject(),
            new go.Binding("alignmentFocus", "", function (node) {
                return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.TopCenter : go.Spot.LeftCenter;
            }).ofObject(),
            new go.Binding("stretch", "", function (node) {
                return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.GraphObject.Horizontal : go.GraphObject.Vertical;
            }).ofObject(),
            new go.Binding("background", "", function (val) {
                return !val.isSubGraphExpanded ? "transparent" : "rgba(0,0,0,0.1)";
            }).ofObject(),

            new go.Binding("height", "", function (node) {
                if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                    return node.data.headerSize ? node.data.headerSize : 100;
                }
                else {
                    var s = go.Size.parse(node.data.size);
                    return s.height;
                }
            }).ofObject().makeTwoWay(function (val, node, model) {
                if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                    node.diagram.model.setDataProperty(node.data, "headerSize", val);
                }
            }),
            new go.Binding("width", "", function (node) {
                if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                    var s = go.Size.parse(node.data.size);
                    return s.width;
                }
                else {
                    return node.data.headerSize ? node.data.headerSize : 100;
                }
            }).ofObject().makeTwoWay(function (val, node, model) {
                if (node.containingGroup && node.containingGroup.data && !node.containingGroup.data.isVertical) {
                    node.diagram.model.setDataProperty(node.data, "headerSize", val);
                }
            }),

            GO(go.Panel, "Horizontal",
                new go.Binding("alignment", "", function (node) {
                    return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.Center : node.isSubGraphExpanded ? go.Spot.TopCenter : go.Spot.LeftCenter;
                }).ofObject(),
                new go.Binding("height", "", function (node) {
                    if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                        if (!node.isSubGraphExpanded) {
                            return 25;
                        }
                        return node.data.headerSize ? node.data.headerSize : 100;
                    }
                    else {
                        var s = go.Size.parse(node.data.size);
                        return s.height;
                    }
                }).ofObject(),
                GO("SubGraphExpanderButton", { margin: 5 }),  // but this remains always visible!
                GO(go.TextBlock,  // the lane label
                    {
                        name: "HEADERTEXT",
                        editable: false,
                        verticalAlignment: go.Spot.Center,
                        textAlign: "center",
                        wrap: go.TextBlock.WrapFit,
                        width: 60,
                        margin: new go.Margin(1, 0, 0, 0)
                    },
                    helper._getTextBlockFontOptions(),
                    new go.Binding("width", "", function (node) {
                        if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                            var s = go.Size.parse(node.data.size);
                            return s.width > 20 ? s.width - 20 : s.width;
                        }
                        else {
                            if (node.data.font && node.data.font.angle) {
                                if (node.data.font.angle === 90 || node.data.font.angle === 270) {
                                    if (node.data.size && node.data.size.indexOf(" ") != -1) {
                                        return Number(node.data.size.split(" ")[1]);
                                    }
                                }
                            }

                            return node.data.headerSize ? node.data.headerSize - 20 : 60;
                        }
                    }).ofObject(),
                    new go.Binding("visible", "isSubGraphExpanded").ofObject(),
                    new go.Binding("text", "", function (val) {
                        var _text = "";
                        if (val.externalDataLane) {
                            if (Array.isArray(val.externalDataLane)) {
                                $.each(val.externalDataLane, function (index, item) {
                                    _text += item.text + "\n\n";
                                });
                                _text = _text.slice(0, -2);
                            } else {
                                _text = val.externalDataLane.text;
                            }
                        } else {
                            _text = val.text;
                        }
                        return _text;
                    })
                )
            )
        ),  // end Horizontal Panel

        // header ın sağındaki çizgi
        GO(go.Panel, "Vertical",
            {
                alignment: go.Spot.LeftCenter, alignmentFocus: go.Spot.LeftCenter,
                width: 100,
                //background: "yellow",
            },
            new go.Binding("type", "", function (node) {
                return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Panel.Horizontal : go.Panel.Vertical;
            }).ofObject(),
            new go.Binding("alignment", "", function (node) {
                return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.TopCenter : go.Spot.LeftCenter;
            }).ofObject(),
            new go.Binding("alignmentFocus", "", function (node) {
                return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.TopCenter : go.Spot.LeftCenter;
            }).ofObject(),
            new go.Binding("width", "", function (node) {
                if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                    var s = go.Size.parse(node.data.size);
                    return s.width;
                }
                else {
                    return node.data.headerSize ? node.data.headerSize : 100;
                }
            }).ofObject(),
            new go.Binding("height", "", function (node) {
                if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                    return node.data.headerSize ? node.data.headerSize : 100;
                }
                else {
                    var s = go.Size.parse(node.data.size);
                    return s.height;
                }
            }).ofObject(),

            GO(go.Shape, "Rectangle",
                {
                    fill: "#AAA",
                    strokeWidth: 0,
                    alignment: go.Spot.Right,
                    stretch: go.GraphObject.Vertical,
                    height: 100,
                    width: 1
                },
                new go.Binding("alignment", "", function (node) {
                    return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.Spot.Bottom : go.Spot.Right;
                }).ofObject(),
                new go.Binding("stretch", "", function (node) {
                    return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? go.GraphObject.Horizontal : go.GraphObject.Vertical;
                }).ofObject(),

                new go.Binding("visible", "isSubGraphExpanded").ofObject(),
                new go.Binding("height", "size", function (val, shape) {
                    var findNode = shape.diagram.findNodeForKey(shape.part.data.group);
                    if (findNode && findNode.data && findNode.data.isVertical) {
                        return 1;
                    } else {
                        var s = go.Size.parse(val);
                        return s.height;
                    }
                }),
                new go.Binding("width", "size", function (val, shape) {
                    var findNode = shape.diagram.findNodeForKey(shape.part.data.group);
                    if (findNode && findNode.data && findNode.data.isVertical) {
                        var s = go.Size.parse(val);
                        return s.width;
                    } else {
                        return 1;
                    }
                })
            )
        ),

        GO(go.Placeholder,
            { padding: new go.Margin(10, 10, 10, 110), alignment: go.Spot.TopLeft, alignmentFocus: go.Spot.TopLeft },
            new go.Binding("padding", "", function (node) {
                if (node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical) {
                    return node.data && node.data.headerSize ? new go.Margin(node.data.headerSize + 10, 10, 10, 10) : new go.Margin(110, 10, 10, 10);
                }
                else {
                    return node.data && node.data.headerSize ? new go.Margin(10, 10, 10, node.data.headerSize + 10) : new go.Margin(10, 10, 10, 110);
                }
            }).ofObject()
        ),
        GO(go.Panel, "Horizontal", { alignment: go.Spot.TopLeft, alignmentFocus: go.Spot.TopLeft },
            {
                name: "HEADERCOLLAPSED",
                stretch: go.GraphObject.Vertical
            },
            GO(go.TextBlock,  // this TextBlock is only seen when the swimlane is collapsed
                {
                    name: "LABEL",
                    editable: false, visible: false,
                    angle: 0,
                    stretch: go.GraphObject.Vertical,
                    height: 30,
                    verticalAlignment: go.Spot.Center
                },
                helper._getTextBlockFontOptions(),
                new go.Binding("angle", "", function (node) {
                    return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? 90 : 0;
                }).ofObject(),
                new go.Binding("margin", "", function (node) {
                    return node.containingGroup && node.containingGroup.data && node.containingGroup.data.isVertical ? new go.Margin(28, 1, 0, 0) : new go.Margin(0, 0, 0, 25);
                }).ofObject(),
                new go.Binding("visible", "isSubGraphExpanded", function (e) { return !e; }).ofObject(),
                new go.Binding("text", "", function (val) {
                    var _text = "";
                    if (val.externalDataLane) {
                        if (Array.isArray(val.externalDataLane)) {
                            $.each(val.externalDataLane, function (index, item) {
                                _text += item.text + " / ";
                            });
                            _text = _text.slice(0, -1);
                        } else {
                            _text = val.externalDataLane.text;
                        }
                    } else {
                        _text = val.text;
                    }
                    return _text;
                })
            )
        )
    );
}

That behavior isn’t a problem in the sample, https://gojs.net/latest/samples/swimLanes.html, so I’m wondering what is different. Thanks for providing your code, but that’s a lot of code. It isn’t obvious what’s different.

I am curious why you have that function to change the resizeObjectName. What’s the reason for needing that?