Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] Render vertical lanes #573

Merged
merged 10 commits into from
Sep 2, 2020
10 changes: 6 additions & 4 deletions src/component/mxgraph/config/StyleConfigurator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { MarkerIdentifier, StyleDefault, StyleIdentifier } from '../StyleUtils';
import Shape from '../../../model/bpmn/shape/Shape';
import Edge from '../../../model/bpmn/edge/Edge';
import Bounds from '../../../model/bpmn/Bounds';
import {
import ShapeBpmnElement, {
ShapeBpmnActivity,
ShapeBpmnBoundaryEvent,
ShapeBpmnCallActivity,
Expand Down Expand Up @@ -174,9 +174,11 @@ export default class StyleConfigurator {
private configureLaneStyle(): void {
const style = this.cloneDefaultVertexStyle();
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_SWIMLANE;

// TODO Remove when the bounds of the lane label is implemented
style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;
style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;
style[mxConstants.STYLE_HORIZONTAL] = false;

style[mxConstants.STYLE_SWIMLANE_LINE] = 0; // hide the line between the title region and the content area

// TODO manage lane text area rendering. there is no Label neither the size available (we have only attribute name="Text of the Label")
Expand Down Expand Up @@ -305,9 +307,9 @@ export default class StyleConfigurator {
if (markers.length > 0) {
styleValues.set(StyleIdentifier.BPMN_STYLE_MARKERS, markers.join(','));
}
} else if (bpmnElement.kind === ShapeBpmnElementKind.POOL) {
} else if (ShapeUtil.isPoolOrLane((bpmnElement as ShapeBpmnElement).kind)) {
// mxConstants.STYLE_HORIZONTAL is for the label
// In BPMN, isHorizontal is for the Pool
// In BPMN, isHorizontal is for the Shape
styleValues.set(mxConstants.STYLE_HORIZONTAL, bpmnCell.isHorizontal ? '0' : '1');
}
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/component/parser/json/converter/DiagramConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { BPMNDiagram, BPMNEdge, BPMNLabel, BPMNLabelStyle, BPMNShape } from '../
import { Point } from '../../xml/bpmn-json-model/DC';
import { ensureIsArray } from './ConverterUtil';
import { ShapeBpmnElementKind, ShapeBpmnMarkerKind } from '../../../../model/bpmn/shape';
import ShapeUtil from '../../../../model/bpmn/shape/ShapeUtil';

function findProcessElement(participantId: string): ShapeBpmnElement | undefined {
const participant = findProcessRefParticipant(participantId);
Expand Down Expand Up @@ -135,7 +136,7 @@ export default class DiagramConverter {
}

let isHorizontal;
if (bpmnElement.kind === ShapeBpmnElementKind.POOL) {
if (ShapeUtil.isPoolOrLane(bpmnElement.kind)) {
isHorizontal = shape.isHorizontal !== undefined ? shape.isHorizontal : true;
}

Expand Down
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 5 additions & 5 deletions test/e2e/bpmn.rendering.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ describe('no visual regression', () => {
const imageSnapshotThresholdConfig = new Map<string, ImageSnapshotThresholdConfig>([
[
'labels.01.general', // minimal threshold to make test pass on Github Workflow
// ubuntu: Expected image to match or be a close match to snapshot but was 0.00036826842172432706%
// ubuntu: Expected image to match or be a close match to snapshot but was 0.019162386876825366%
// macOS: Expected image to match or be a close match to snapshot but was 0.556652966856197%
// windows: Expected image to match or be a close match to snapshot but was 0.40964885362031467%
{
linux: 0.00005,
linux: 0.0002,
macos: 0.006,
windows: 0.005,
},
Expand Down Expand Up @@ -108,20 +108,20 @@ describe('no visual regression', () => {
// macOS: Expected image to match or be a close match to snapshot but was 0.14776609441433664%
// windows: Expected image to match or be a close match to snapshot but was 0.1182792778311903%
[
'pools.02.vertical',
'pools.02.vertical.with-lanes',
{
linux: 0.0014,
macos: 0.0015,
windows: 0.002,
},
],
// ubuntu: Expected image to match or be a close match to snapshot but was 0.00032007070301931506% different from snapshot
// ubuntu: Expected image to match or be a close match to snapshot but was 0.0043243364134193385% different from snapshot
// macOS: Expected image to match or be a close match to snapshot but was 0.07646269456225152% different from snapshot
// windows: Expected image to match or be a close match to snapshot but was 0.11539494876845469% different from snapshot
[
'pools.03.black-box',
{
linux: 0.000004,
linux: 0.00005,
macos: 0.0008,
windows: 0.0012,
},
Expand Down
24 changes: 21 additions & 3 deletions test/e2e/mxGraph.model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface ExpectedShapeModelElement {
styleShape?: string;
markers?: ShapeBpmnMarkerKind[];
isInstantiating?: boolean;
isHorizontal?: boolean;
}

export interface ExpectedEventModelElement extends ExpectedShapeModelElement {
Expand Down Expand Up @@ -206,11 +207,13 @@ describe('mxGraph model', () => {
}

function expectModelContainsPool(cellId: string, modelElement: ExpectedShapeModelElement): void {
expectModelContainsShape(cellId, { ...modelElement, kind: ShapeBpmnElementKind.POOL, styleShape: mxConstants.SHAPE_SWIMLANE });
const mxCell = expectModelContainsShape(cellId, { ...modelElement, kind: ShapeBpmnElementKind.POOL, styleShape: mxConstants.SHAPE_SWIMLANE });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 for adding model tests for both vertical pool and lanes

expect(mxCell.style).toContain(`${mxConstants.STYLE_HORIZONTAL}=${modelElement.isHorizontal ? '0' : '1'}`);
}

function expectModelContainsLane(cellId: string, modelElement: ExpectedShapeModelElement): void {
expectModelContainsShape(cellId, { ...modelElement, kind: ShapeBpmnElementKind.LANE, styleShape: mxConstants.SHAPE_SWIMLANE });
const mxCell = expectModelContainsShape(cellId, { ...modelElement, kind: ShapeBpmnElementKind.LANE, styleShape: mxConstants.SHAPE_SWIMLANE });
expect(mxCell.style).toContain(`${mxConstants.STYLE_HORIZONTAL}=${modelElement.isHorizontal ? '0' : '1'}`);
}

it('bpmn elements should be available in the mxGraph model', async () => {
Expand All @@ -228,7 +231,7 @@ describe('mxGraph model', () => {
};

// pool
const minimalPoolModelElement: ExpectedShapeModelElement = { kind: null };
const minimalPoolModelElement: ExpectedShapeModelElement = { kind: null, isHorizontal: true };
expectModelContainsPool('participant_1_id', { ...minimalPoolModelElement, label: 'Pool 1' });
expectModelContainsPool('participant_2_id', minimalPoolModelElement);
expectModelContainsPool('participant_3_id', { ...minimalPoolModelElement, label: 'Black Box Process' });
Expand Down Expand Up @@ -946,4 +949,19 @@ describe('mxGraph model', () => {
];
expectModelContainsCellWithGeometry('MessageFlow_1', undefined, messageFlowMxGeometry);
});

it('vertical pool, with vertical lanes & sub-lanes', async () => {
bpmnVisualization.load(readFileSync('../fixtures/bpmn/model-vertical-pool-lanes-sub_lanes.bpmn'));

// pool
const minimalPoolModelElement: ExpectedShapeModelElement = { kind: null, isHorizontal: false };
expectModelContainsPool('Participant_Vertical_With_Lanes', { ...minimalPoolModelElement, label: 'Vertical Pool With Lanes' });

// lane
expectModelContainsLane('Lane_Vertical_3', { ...minimalPoolModelElement });
expectModelContainsLane('Lane_Vertical_1', { ...minimalPoolModelElement, label: 'Lane' });
expectModelContainsLane('Lane_Vertical_With_Sub_Lane', { ...minimalPoolModelElement, label: 'Lane with Sub-Lanes' });
expectModelContainsLane('SubLane_Vertical_1', { ...minimalPoolModelElement, label: 'Sub-Lane 1', parentId: 'Lane_Vertical_With_Sub_Lane' });
expectModelContainsLane('SubLane_Vertical_2', { ...minimalPoolModelElement, label: 'Sub-Lane 2', parentId: 'Lane_Vertical_With_Sub_Lane' });
});
});
40 changes: 40 additions & 0 deletions test/fixtures/bpmn/model-vertical-pool-lanes-sub_lanes.bpmn
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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" id="Definitions_1bo1yrl" targetNamespace="http://bpmn.io/schema/bpmn" exporter="bpmn-js (https://demo.bpmn.io)" exporterVersion="7.2.0">
<bpmn:collaboration id="Collaboration_0005yoe">
<bpmn:participant id="Participant_Vertical_With_Lanes" name="Vertical Pool With Lanes" processRef="Process_Vertical_With_Lanes" />
</bpmn:collaboration>
<bpmn:process id="Process_Vertical_With_Lanes">
<bpmn:laneSet>
<bpmn:lane id="Lane_Vertical_3" />
<bpmn:lane id="Lane_Vertical_With_Sub_Lane" name="Lane with Sub-Lanes">
<bpmn:childLaneSet>
<bpmn:lane id="SubLane_Vertical_2" name="Sub-Lane 2" />
<bpmn:lane id="SubLane_Vertical_1" name="Sub-Lane 1" />
</bpmn:childLaneSet>
</bpmn:lane>
<bpmn:lane id="Lane_Vertical_1" name="Lane" />
</bpmn:laneSet>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_0005yoe">
<bpmndi:BPMNShape id="Participant_Vertical_With_Lanes_di" bpmnElement="Participant_Vertical_With_Lanes" isHorizontal="false">
<dc:Bounds x="80" y="160" width="370" height="600" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Lane_Vertical_3_di" bpmnElement="Lane_Vertical_3" isHorizontal="false">
<dc:Bounds x="366" y="190" width="84" height="570" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Lane_Vertical_With_Sub_Lane_di" bpmnElement="Lane_Vertical_With_Sub_Lane" isHorizontal="false">
<dc:Bounds x="163" y="190" width="203" height="570" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="SubLane_Vertical_2_di" bpmnElement="SubLane_Vertical_2" isHorizontal="false">
<dc:Bounds x="246" y="220" width="120" height="540" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="SubLane_Vertical_1_di" bpmnElement="SubLane_Vertical_1" isHorizontal="false">
<dc:Bounds x="163" y="220" width="83" height="540" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Lane_Vertical_1_di" bpmnElement="Lane_Vertical_1" isHorizontal="false">
<dc:Bounds x="80" y="190" width="83" height="570" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
</bpmn:collaboration>
<bpmn:process id="Process_1m47u99">
<bpmn:laneSet id="LaneSet_012cmfs">
<bpmn:lane id="Lane_0bpyqm2" name="Vertical Lane 2" />
<bpmn:lane id="Lane_0bpyqm2" name="Vertical Lane 2">
<bpmn:childLaneSet id="LaneSet_0c3xavp">
<bpmn:lane id="Lane_0oyiu99" name="sublane 2.1" />
<bpmn:lane id="Lane_0l0a48n" />
</bpmn:childLaneSet>
</bpmn:lane>
<bpmn:lane id="Lane_14h9zcu" name="Vertical Lane 1" />
</bpmn:laneSet>
</bpmn:process>
Expand All @@ -20,6 +25,12 @@
<bpmndi:BPMNShape id="Lane_14h9zcu_di" bpmnElement="Lane_14h9zcu" isHorizontal="false">
<dc:Bounds x="160" y="110" width="300" height="220" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Lane_0oyiu99_di" bpmnElement="Lane_0oyiu99" isHorizontal="false">
<dc:Bounds x="460" y="140" width="150" height="190" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Lane_0l0a48n_di" bpmnElement="Lane_0l0a48n" isHorizontal="false">
<dc:Bounds x="610" y="140" width="150" height="190" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
10 changes: 10 additions & 0 deletions test/unit/component/mxgraph/config/StyleConfigurator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,16 @@ describe('mxgraph renderer', () => {
});
});

describe('compute style - lane', () => {
it.each([
['vertical', false, '1'],
['horizontal', true, '0'],
])('%s lane', (title, isHorizontal: boolean, expected: string) => {
const shape = newShape(newShapeBpmnElement(ShapeBpmnElementKind.LANE), undefined, isHorizontal);
expect(computeStyle(shape)).toEqual(`lane;horizontal=${expected}`);
});
});

describe.each([
[ShapeBpmnElementKind.CALL_ACTIVITY],
[ShapeBpmnElementKind.SUB_PROCESS],
Expand Down
Loading