From 8815b735995845155bfa40af331df92592ea612a Mon Sep 17 00:00:00 2001 From: Philipp Fromme Date: Mon, 3 Jun 2019 15:31:54 +0200 Subject: [PATCH] feat(grid-snapping): snap width and height on create first participant Closes #1061 --- .../behavior/CreateParticipantBehavior.js | 36 ++++++++++++ lib/features/grid-snapping/behavior/index.js | 5 +- .../behavior/CreateParticipantBehavior.js | 17 ++++-- .../behavior/CreateParticipantBehavior.bpmn | 56 +++++++++++++++++++ .../behavior/CreateParticipantBehaviorSpec.js | 52 +++++++++++++++++ 5 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 lib/features/grid-snapping/behavior/CreateParticipantBehavior.js create mode 100644 test/spec/features/grid-snapping/behavior/CreateParticipantBehavior.bpmn create mode 100644 test/spec/features/grid-snapping/behavior/CreateParticipantBehaviorSpec.js diff --git a/lib/features/grid-snapping/behavior/CreateParticipantBehavior.js b/lib/features/grid-snapping/behavior/CreateParticipantBehavior.js new file mode 100644 index 00000000..b20ee0a1 --- /dev/null +++ b/lib/features/grid-snapping/behavior/CreateParticipantBehavior.js @@ -0,0 +1,36 @@ +import { is } from '../../../util/ModelUtil'; + +var HIGHER_PRIORITY = 1750; + + +export default function CreateParticipantBehavior(canvas, eventBus, gridSnapping) { + eventBus.on([ + 'create.start', + 'shape.move.start' + ], HIGHER_PRIORITY, function(event) { + var context = event.context, + shape = context.shape, + rootElement = canvas.getRootElement(); + + if (!is(shape, 'bpmn:Participant') || + !is(rootElement, 'bpmn:Process') || + !rootElement.children.length) { + return; + } + + var createConstraints = context.createConstraints; + + if (!createConstraints) { + return; + } + + shape.width = gridSnapping.snapValue(shape.width, { min: shape.width }); + shape.height = gridSnapping.snapValue(shape.height, { min: shape.height }); + }); +} + +CreateParticipantBehavior.$inject = [ + 'canvas', + 'eventBus', + 'gridSnapping' +]; \ No newline at end of file diff --git a/lib/features/grid-snapping/behavior/index.js b/lib/features/grid-snapping/behavior/index.js index fef085f4..cd1800c5 100644 --- a/lib/features/grid-snapping/behavior/index.js +++ b/lib/features/grid-snapping/behavior/index.js @@ -1,11 +1,14 @@ import AutoPlaceBehavior from './AutoPlaceBehavior'; +import CreateParticipantBehavior from './CreateParticipantBehavior'; import LayoutConnectionBehavior from './LayoutConnectionBehavior'; export default { __init__: [ + 'gridSnappingAutoPlaceBehavior', + 'gridSnappingCreateParticipantBehavior', 'gridSnappingLayoutConnectionBehavior', - 'gridSnappingAutoPlaceBehavior' ], gridSnappingAutoPlaceBehavior: [ 'type', AutoPlaceBehavior ], + gridSnappingCreateParticipantBehavior: [ 'type', CreateParticipantBehavior ], gridSnappingLayoutConnectionBehavior: [ 'type', LayoutConnectionBehavior ] }; \ No newline at end of file diff --git a/lib/features/modeling/behavior/CreateParticipantBehavior.js b/lib/features/modeling/behavior/CreateParticipantBehavior.js index ed383e7f..ec2fff75 100644 --- a/lib/features/modeling/behavior/CreateParticipantBehavior.js +++ b/lib/features/modeling/behavior/CreateParticipantBehavior.js @@ -10,9 +10,12 @@ import { getBBox } from 'diagram-js/lib/util/Elements'; import { assign } from 'min-dash'; +import { asTRBL } from 'diagram-js/lib/layout/LayoutUtil'; + var HORIZONTAL_PARTICIPANT_PADDING = 20, - VERTICAL_PARTICIPANT_PADDING = 20, - PARTICIPANT_BORDER_WIDTH = 30; + VERTICAL_PARTICIPANT_PADDING = 20; + +export var PARTICIPANT_BORDER_WIDTH = 30; var HIGH_PRIORITY = 2000; @@ -167,11 +170,13 @@ function getParticipantBounds(shape, childrenBBox) { } function getParticipantCreateConstraints(shape, childrenBBox) { + childrenBBox = asTRBL(childrenBBox); + return { - bottom: childrenBBox.y + shape.height / 2 - VERTICAL_PARTICIPANT_PADDING, - left: childrenBBox.x + childrenBBox.width - shape.width / 2 + HORIZONTAL_PARTICIPANT_PADDING, - top: childrenBBox.y + childrenBBox.height - shape.height / 2 + VERTICAL_PARTICIPANT_PADDING, - right: childrenBBox.x + shape.width / 2 - HORIZONTAL_PARTICIPANT_PADDING - PARTICIPANT_BORDER_WIDTH + bottom: childrenBBox.top + shape.height / 2 - VERTICAL_PARTICIPANT_PADDING, + left: childrenBBox.right - shape.width / 2 + HORIZONTAL_PARTICIPANT_PADDING, + top: childrenBBox.bottom - shape.height / 2 + VERTICAL_PARTICIPANT_PADDING, + right: childrenBBox.left + shape.width / 2 - HORIZONTAL_PARTICIPANT_PADDING - PARTICIPANT_BORDER_WIDTH }; } diff --git a/test/spec/features/grid-snapping/behavior/CreateParticipantBehavior.bpmn b/test/spec/features/grid-snapping/behavior/CreateParticipantBehavior.bpmn new file mode 100644 index 00000000..cb74dce6 --- /dev/null +++ b/test/spec/features/grid-snapping/behavior/CreateParticipantBehavior.bpmn @@ -0,0 +1,56 @@ + + + + + SequenceFlow_1 + + + + SequenceFlow_1 + SequenceFlow_2 + + + SequenceFlow_2 + + + + SequenceFlow_3 + + + SequenceFlow_3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/spec/features/grid-snapping/behavior/CreateParticipantBehaviorSpec.js b/test/spec/features/grid-snapping/behavior/CreateParticipantBehaviorSpec.js new file mode 100644 index 00000000..a4b99910 --- /dev/null +++ b/test/spec/features/grid-snapping/behavior/CreateParticipantBehaviorSpec.js @@ -0,0 +1,52 @@ +import { + bootstrapModeler, + inject +} from 'test/TestHelper'; + +import coreModule from 'lib/core'; +import createModule from 'diagram-js/lib/features/create'; +import gridSnappingModule from 'lib/features/grid-snapping'; +import modelingModule from 'lib/features/modeling'; + +import { createCanvasEvent as canvasEvent } from '../../../../util/MockEvents'; + + +describe('features/grid-snapping - create participant', function() { + + var diagramXML = require('./CreateParticipantBehavior.bpmn'); + + beforeEach(bootstrapModeler(diagramXML, { + modules: [ + coreModule, + createModule, + gridSnappingModule, + modelingModule + ] + })); + + + it('should snap width and height', inject( + function(create, dragging, elementFactory, elementRegistry) { + + // given + var process = elementRegistry.get('Process_1'), + processGfx = elementRegistry.getGraphics(process); + + var participant = elementFactory.createParticipantShape(); + + // when + create.start(canvasEvent({ x: 100, y: 100 }), participant); + + dragging.hover({ element: process, gfx: processGfx }); + + dragging.move(canvasEvent({ x: 100, y: 100 })); + + dragging.end(); + + // then + expect(participant.width).to.equal(610); + expect(participant.height).to.equal(340); + } + )); + +}); \ No newline at end of file