Skip to content

Commit

Permalink
fix: move text annotations when a participant is resized
Browse files Browse the repository at this point in the history
  • Loading branch information
jarekdanielak committed Feb 19, 2025
1 parent bf76668 commit 1d6d0e2
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 3 deletions.
46 changes: 45 additions & 1 deletion lib/features/space-tool/BpmnSpaceTool.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import inherits from 'inherits-browser';

import SpaceTool from 'diagram-js/lib/features/space-tool/SpaceTool';

import { getBusinessObject, is } from '../../util/ModelUtil';
import { getEnclosedElements, getBBox } from 'diagram-js/lib/util/Elements';

import { getBusinessObject, is, isAny } from '../../util/ModelUtil';

import { isHorizontal } from '../../util/DiUtil';

Expand Down Expand Up @@ -59,6 +61,33 @@ BpmnSpaceTool.prototype.calculateAdjustments = function(elements, axis, delta, s
return true;
});

// Make sure elements positioned on the root (e.g. text annotations)
// are moved when the participant enclosing them is resized.
const shapesToMove = [ 'bpmn:TextAnnotation' ];

const participants = adjustments.resizingShapes.filter(shape => is(shape, 'bpmn:Participant'));

const movingShapes = participants.reduce((movingShapes, participant) => {

const rootChildren = participant.parent.children;

const elementsToMove = rootChildren.filter(child => isAny(child, shapesToMove));

if (!elementsToMove.length) {
return movingShapes;
}

const bbox = getBBox(participant);

const enclosed = Object.values(getEnclosedElements(elementsToMove, bbox));

const shouldMove = enclosed.filter(el => shouldBeMoved(el, axis, delta, start));

return [ ...movingShapes, ...shouldMove ];
}, []);

adjustments.movingShapes = [ ...adjustments.movingShapes, ...movingShapes ];

return adjustments;
};

Expand All @@ -67,4 +96,19 @@ BpmnSpaceTool.prototype.calculateAdjustments = function(elements, axis, delta, s

function isCollapsedPool(shape) {
return is(shape, 'bpmn:Participant') && !getBusinessObject(shape).processRef;
}

// True if element is in range of the space tool
// Based on the internal logic of SpaceTool#calculateAdjustments
// TODO(@jarekdanielak): Make it available as an internal function of SpaceTool
function shouldBeMoved(element, axis, delta, start) {

const shapeStart = axis === 'x' ? element.x : element.y;
const shapeEnd = axis === 'x' ? element.x + element.width : element.y + element.height;

if ((delta > 0 && shapeStart > start) || (delta < 0 && shapeEnd < start)) {
return true;
}

return false;
}
44 changes: 43 additions & 1 deletion test/spec/features/space-tool/BpmnSpaceTool.participants.bpmn
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_14kk48y" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.12.1">
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_14kk48y" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.32.0">
<bpmn:collaboration id="Collaboration_0ci7cuj">
<bpmn:participant id="Participant_1" name="Expanded Pool" processRef="Process_1" />
<bpmn:participant id="Participant_2" name="Empty Pool" />
<bpmn:participant id="Participant_3" name="Pool with text annotations" processRef="Process_3" />
<bpmn:textAnnotation id="TextAnnotation_1">
<bpmn:text>text 1</bpmn:text>
</bpmn:textAnnotation>
<bpmn:textAnnotation id="TextAnnotation_2">
<bpmn:text>text 2</bpmn:text>
</bpmn:textAnnotation>
<bpmn:textAnnotation id="TextAnnotation_3">
<bpmn:text>text 3</bpmn:text>
</bpmn:textAnnotation>
</bpmn:collaboration>
<bpmn:process id="Process_1" isExecutable="true" />
<bpmn:process id="Process_3" isExecutable="false">
<bpmn:task id="Activity_1" />
<bpmn:association id="Association_180iz30" associationDirection="None" sourceRef="Activity_1" targetRef="TextAnnotation_1" />
<bpmn:association id="Association_08csipe" associationDirection="None" sourceRef="Activity_1" targetRef="TextAnnotation_2" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_0ci7cuj">
<bpmndi:BPMNShape id="Participant_0f6z5qz_di" bpmnElement="Participant_1" isHorizontal="true">
Expand All @@ -15,6 +30,33 @@
<dc:Bounds x="160" y="170" width="600" height="60" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Participant_0lm71nu_di" bpmnElement="Participant_3" isHorizontal="true">
<dc:Bounds x="160" y="250" width="600" height="250" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1g8l8sp_di" bpmnElement="Activity_1">
<dc:Bounds x="310" y="340" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Association_180iz30_di" bpmnElement="Association_180iz30">
<di:waypoint x="410" y="358" />
<di:waypoint x="496" y="320" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Association_08csipe_di" bpmnElement="Association_08csipe">
<di:waypoint x="393" y="420" />
<di:waypoint x="518" y="570" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="TextAnnotation_0kurhwc_di" bpmnElement="TextAnnotation_1">
<dc:Bounds x="480" y="290" width="100" height="30" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="TextAnnotation_0r40zjh_di" bpmnElement="TextAnnotation_2">
<dc:Bounds x="480" y="570" width="100" height="30" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_05zy3rg" bpmnElement="TextAnnotation_3">
<dc:Bounds x="200" y="360" width="100" height="30" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
100 changes: 99 additions & 1 deletion test/spec/features/space-tool/BpmnSpaceToolSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -551,14 +551,110 @@ describe('features/space-tool - BpmnSpaceTool', function() {
});
}));


it('should move text annotations in a participant', inject(function(dragging, elementRegistry, spaceTool) {

// given
var textAnnotation = elementRegistry.get('TextAnnotation_1');
var textAnnotationX = textAnnotation.x;

var task = elementRegistry.get('Activity_1');
var taskMid = getMid(task);
var rightOfTask = task.x + task.width + 10;

// when
var element = elementRegistry.get('Participant_3');
var gfx = elementRegistry.getGraphics(element);
var hover = { element, gfx };

makeSpace({ x: rightOfTask, y: taskMid.y }, { dx: 100 }, false, hover);

// then
expect(textAnnotation.x).to.equal(textAnnotationX + 100);
}));


it('should only move text annotations in space tool range', inject(function(dragging, elementRegistry, spaceTool) {

// given
var textAnnotationToMove = elementRegistry.get('TextAnnotation_1');
var textAnnotationToMove_X = textAnnotationToMove.x;

var textAnnotationToStay = elementRegistry.get('TextAnnotation_3');
var textAnnotationToStay_X = textAnnotationToStay.x;

var task = elementRegistry.get('Activity_1');
var taskMid = getMid(task);
var rightOfTask = task.x + task.width + 10;

// when
var element = elementRegistry.get('Participant_3');
var gfx = elementRegistry.getGraphics(element);
var hover = { element, gfx };

makeSpace({ x: rightOfTask, y: taskMid.y }, { dx: 100 }, false, hover);

// then
expect(textAnnotationToMove.x).to.equal(textAnnotationToMove_X + 100);
expect(textAnnotationToStay.x).to.equal(textAnnotationToStay_X);
}));


it('should only move text annotations in space tool range (inverted)', inject(function(dragging, elementRegistry, spaceTool) {

// given
var textAnnotationToMove = elementRegistry.get('TextAnnotation_3');
var textAnnotationToMove_X = textAnnotationToMove.x;

var textAnnotationToStay = elementRegistry.get('TextAnnotation_1');
var textAnnotationToStay_X = textAnnotationToStay.x;

var task = elementRegistry.get('Activity_1');
var taskMid = getMid(task);
var rightOfTask = task.x + task.width + 10;

// when
var element = elementRegistry.get('Participant_3');
var gfx = elementRegistry.getGraphics(element);
var hover = { element, gfx };

makeSpace({ x: rightOfTask, y: taskMid.y }, { dx: -100 }, true, hover);

// then
expect(textAnnotationToMove.x).to.equal(textAnnotationToMove_X - 100);
expect(textAnnotationToStay.x).to.equal(textAnnotationToStay_X);
}));


it('should not move text annotations outside of participant', inject(function(dragging, elementRegistry, spaceTool) {

// given
var textAnnotation = elementRegistry.get('TextAnnotation_2');
var textAnnotationX = textAnnotation.x;

var task = elementRegistry.get('Activity_1');
var taskMid = getMid(task);
var rightOfTask = task.x + task.width + 10;

// when
var element = elementRegistry.get('Participant_3');
var gfx = elementRegistry.getGraphics(element);
var hover = { element, gfx };

makeSpace({ x: rightOfTask, y: taskMid.y }, { dx: 100 }, false, hover);

// then
expect(textAnnotation.x).to.equal(textAnnotationX);
}));

});

});


// helpers //////////

function makeSpace(start, delta, invert) {
function makeSpace(start, delta, invert, hover) {
var modifier = invert ? invertModifier : {};

var end = {
Expand All @@ -569,6 +665,8 @@ function makeSpace(start, delta, invert) {
return getBpmnJS().invoke(function(spaceTool, dragging) {
spaceTool.activateMakeSpace(canvasEvent(start));

hover && dragging.hover(hover);

dragging.move(canvasEvent(end, modifier));

dragging.end();
Expand Down

0 comments on commit 1d6d0e2

Please sign in to comment.