Calling SpaceTool programatically: calculating the correct position

Hi,

I want to use the SpaceTool so I can automatically place swimlanes and activities in a grid layout.

I was using this solution but it seems like zooming in and out breaks it. My guess is that I would have to use the viewbox and its scale too but I’m not sure in which way.

I’d appreciate if someone could help to find the correct formula.

At the moment, this is the code I am using which is a little closer but still off.

makeSpace is the function that I call with the position of the Shapes from the elementRegistry while space is the amount of vertical space I want to add to the position.
As the position, I make sure to get the shape just before calling the function and I go to the bottom of the shape by adding its y and height and then adding a little margin to be safe.

function createCanvasEvent(pos){
  return bpmnModeler.invoke((canvas) => {
    var clientRect = canvas._container.getBoundingClientRect();
    const viewport = canvas._cachedViewbox;
    var position = {
      x: (pos.x - viewport.x + clientRect.left) * viewport.scale,
      y: (pos.y - viewport.y + clientRect.top) * viewport.scale
    };
    var target = canvas._svg;
    return bpmnModeler.invoke((eventBus) => {
      const data = {
        target: target,
        clientX: position.x,
        clientY: position.y,
        offsetX: position.x,
        offsetY: position.y
      };
      return eventBus.createEvent(data);
    });

  });
}
function makeSpace(startPosition, space) {
  var event_start = createCanvasEvent(startPosition);
  var event_end = createCanvasEvent({
    x: startPosition.x,
    y: startPosition.y + space,
  });
  spaceTool.activateMakeSpace(event_start);
  spaceTool._dragging.move(event_end);
  spaceTool._dragging.end();
  spaceTool._dragging.cancel();
}

I came up with a dirty solution but I’m still interested if someone knows how to properly do it

function makeSpace(startPosition, space) {
  const zoom = canvas.zoom();
  canvas.zoom(1);

  var event_start = createCanvasEvent(startPosition);
  var event_end = createCanvasEvent({
    x: startPosition.x,
    y: startPosition.y + space,
  });
  spaceTool.activateMakeSpace(event_start);
  spaceTool._dragging.move(event_end);
  spaceTool._dragging.end();
  spaceTool._dragging.cancel();
  
  canvas.zoom(zoom);
}

I think it could be cleaner to call modeling.createSpace directly. This is the method used internally by the space tool and does not require mocking start and end events. However, this expects that you already know which shapes you want to move.