JointJS+ SwimlaneTransform

You may see the name Rappid in our documentation, code and other materials. Rappid has been replaced by a new brand, JointJS+. This change has no effect on functionality. To avoid confusion, please consider Rappid and JointJS+ as synonyms. Read more here.

elementTools.SwimlaneTransform

The SwimlaneTransform element tool allows you to resize lanes in bpmn2.Pool or bpmn2.HeaderedPool shape, from the UI. It renders 4 handles around selected lane which you drag and use to resize lane in particular direction. It accepts a few additional arguments, which can be passed as an object to the element tool constructor:

laneId string Specifies the lane group for which the tool should be rendered.
padding number|object Specifies how much the boundary area of handles should be visually inflated. Default is 10 ({ left: 10, top: 10, right: 10, bottom: 10 }).
minSize number Specifies the minimal height of the lane after which the tool will not allow it to shrink further. Default is 30.
constraintsPadding number Specifies the padding around constraint points. Default is 10.
minSizeConstraints function Callback function that is expected to return an array of minimal constraint points (in the form: { x: number, y: number }), relative to the paper. Minimal constraint points are points that should always be kept inside selected lane when resizing. If this option is left undefined, the default minSizeConstraints function is used instead which creates those points automatically from embedded shapes. Callback is called each time a handle starts to be dragged, the arguments passed are:

model dia.Element Pool shape that the tool was added to.
laneId string Id of the lane that the tool was initialized with.
handleSide "left" | "top" | "right" | "bottom" Position of the dragged handle (relative to the lane).
maxSizeConstraints function Callback function that is expected to return an array of maximum constraint points (in the form: { x: number, y: number }), relative to the paper. Maximum constraint points are points that should always be kept outside selected lane when resizing. If this option is left undefined, the default maxSizeConstraints function is used instead which creates those points automatically from embedded shapes. Callback is called each time a handle starts to be dragged, the arguments passed are:

model dia.Element Pool shape that the tool was added to.
laneId string Id of the lane that the tool was initialized with.
handleSide "left" | "top" | "right" | "bottom" Position of the dragged handle (relative to the lane).
stopPropagation boolean Should be events stopped from propagating to the paper? Default is true.

Example:

const transformTool = new joint.elementTools.SwimlaneTransform({
    laneId: 'customLaneId',
    padding: 8,
    minSize: 50,
    focusOpacity: 0.5
    constraintsPadding: 20,
});

Example with custom constraint points:

graph.on('change:parent', function(element, parentId) {
    if (parentId) {
        const pool = graph.getCell(parentId);
        const [laneId] = pool.getLanesFromPoint(element.getBBox().center());
        element.prop('laneId', laneId);
    } else {
        element.prop('laneId', null);
    }
});

const transformTool = new joint.elementTools.SwimlaneTransform({
    laneId: 'customLaneId',
    constraintsPadding: 30,
    minSizeConstraints: (model, laneId, handleSide) => {
        const minPoints = [];
        const embedCells = model.getEmbeddedCells();

        if (embedCells.length === 0) return;

        embedCells.forEach(cell => {
            if (cell.prop('laneId') === laneId) {
                const cellBBox = cell.getBBox();
                minPoints.push(cellBBox.topLeft());
                minPoints.push(cellBBox.topRight());
                minPoints.push(cellBBox.bottomLeft());
                minPoints.push(cellBBox.bottomRight());
            }
        });

        if (handleSide === 'left' || handleSide === 'right') {
            const embedsBBox = model.graph.getCellsBBox(embedCells);
            // add left most and right most points
            minPoints.push(embedsBBox.origin());
            minPoints.push(embedsBBox.corner());
        }

        return minPoints;
    },
    maxSizeConstraints: (model, laneId) => {
        const maxPoints = [];
        const embedCells = model.getEmbeddedCells();

        if (embedCells.length === 0) return;

        embedCells.forEach(cell => {
            if (cell.prop('laneId') !== laneId) {
                const cellBBox = cell.getBBox();
                maxPoints.push(cellBBox.topLeft());
                maxPoints.push(cellBBox.topRight());
                maxPoints.push(cellBBox.bottomLeft());
                maxPoints.push(cellBBox.bottomRight());
            }
        });

        return maxPoints;
    }
});