diff --git a/lib/draw/BpmnRenderer.js b/lib/draw/BpmnRenderer.js index 896eaf0e..bbe20ff8 100644 --- a/lib/draw/BpmnRenderer.js +++ b/lib/draw/BpmnRenderer.js @@ -1501,6 +1501,110 @@ function BpmnRenderer(events, styles, pathMap) { return (event.$type === 'bpmn:IntermediateThrowEvent') || (event.$type === 'bpmn:EndEvent'); } + + /////// cropping path customizations ///////////////////////// + + function componentsToPath(elements) { + return elements.join(',').replace(/,?([A-z]),?/g, '$1'); + } + + function getCirclePath(shape) { + + var cx = shape.x + shape.width / 2, + cy = shape.y + shape.height / 2, + radius = shape.width / 2; + + var circlePath = [ + ['M', cx, cy], + ['m', 0, -radius], + ['a', radius, radius, 0, 1, 1, 0, 2 * radius], + ['a', radius, radius, 0, 1, 1, 0, -2 * radius], + ['z'] + ]; + + return componentsToPath(circlePath); + } + + function getRoundRectPath(shape) { + + var radius = TASK_BORDER_RADIUS, + x = shape.x, + y = shape.y, + width = shape.width, + height = shape.height; + + var roundRectPath = [ + ['M', x + radius, y], + ['l', width - radius * 2, 0], + ['a', radius, radius, 0, 0, 1, radius, radius], + ['l', 0, height - radius * 2], + ['a', radius, radius, 0, 0, 1, -radius, radius], + ['l', radius * 2 - width, 0], + ['a', radius, radius, 0, 0, 1, -radius, -radius], + ['l', 0, radius * 2 - height], + ['a', radius, radius, 0, 0, 1, radius, -radius], + ['z'] + ]; + + return componentsToPath(roundRectPath); + } + + function getDiamondPath(shape) { + + var width = shape.width, + height = shape.height, + x = shape.x, + y = shape.y, + halfWidth = width / 2, + halfHeight = height / 2; + + var diamondPath = [ + ['M', x + halfWidth, y], + ['l', halfWidth, halfHeight], + ['l', -halfWidth, halfHeight], + ['l', -halfWidth, -halfHeight], + ['z'] + ]; + + return componentsToPath(diamondPath); + } + + function getRectPath(shape) { + var x = shape.x, + y = shape.y, + width = shape.width, + height = shape.height; + + var rectPath = [ + ['M', x, y], + ['l', width, 0], + ['l', 0, height], + ['l', -width, 0], + ['z'] + ]; + + return componentsToPath(rectPath); + } + + function getShapePath(element) { + var obj = getSemantic(element); + + if (obj.$instanceOf('bpmn:Event')) { + return getCirclePath(element); + } + + if (obj.$instanceOf('bpmn:Activity')) { + return getRoundRectPath(element); + } + + if (obj.$instanceOf('bpmn:Gateway')) { + return getDiamondPath(element); + } + + return getRectPath(element); + } + + // hook onto canvas init event to initialize // connection start/end markers on svg events.on('canvas.init', function(event) { @@ -1509,6 +1613,8 @@ function BpmnRenderer(events, styles, pathMap) { this.drawShape = drawShape; this.drawConnection = drawConnection; + + this.getShapePath = getShapePath; } inherits(BpmnRenderer, DefaultRenderer); diff --git a/test/fixtures/bpmn/simple-cropping.bpmn b/test/fixtures/bpmn/simple-cropping.bpmn new file mode 100644 index 00000000..d3e0efcd --- /dev/null +++ b/test/fixtures/bpmn/simple-cropping.bpmn @@ -0,0 +1,84 @@ + + + + + SequenceFlow_1 + + + SequenceFlow_1 + SequenceFlow_2 + + + + SequenceFlow_2 + + SequenceFlow_3 + + + SequenceFlow_3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/fixtures/bpmn/simple-resizable.bpmn b/test/fixtures/bpmn/simple-resizable.bpmn new file mode 100644 index 00000000..a7b6ee5b --- /dev/null +++ b/test/fixtures/bpmn/simple-resizable.bpmn @@ -0,0 +1,50 @@ + + + + + SequenceFlow_1 + + + SequenceFlow_1 + SequenceFlow_2 + + + + SequenceFlow_2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/spec/draw/BpmnRendererSpec.js b/test/spec/draw/BpmnRendererSpec.js index 8c889ec7..b35ea624 100644 --- a/test/spec/draw/BpmnRendererSpec.js +++ b/test/spec/draw/BpmnRendererSpec.js @@ -1,8 +1,12 @@ 'use strict'; -var TestHelper = require('../../TestHelper'); +var Matchers = require('../../Matchers'), + TestHelper = require('../../TestHelper'); -/* global bootstrapViewer */ +var coreModule = require('../../../lib/core'), + rendererModule = require('../../../lib/draw'); + +/* global bootstrapViewer, bootstrapModeler, inject */ describe('draw - bpmn renderer', function() { @@ -146,3 +150,73 @@ describe('draw - bpmn renderer', function() { }); }); + +describe('path - bpmn renderer', function () { + + beforeEach(Matchers.addDeepEquals); + + + var diagramXML = require('../../fixtures/bpmn/simple-cropping.bpmn'); + + var testModules = [ coreModule, rendererModule ]; + + beforeEach(bootstrapModeler(diagramXML, { modules: testModules })); + + describe('circle', function () { + + + it('should return a circle path', inject(function(canvas, elementRegistry, renderer) { + + // given + var eventElement = elementRegistry.get('StartEvent_1'); + + // when + var startPath = renderer.getShapePath(eventElement); + + // then + expect(startPath).toEqual('M247,343m0,-18a18,18,0,1,1,0,36a18,18,0,1,1,0,-36z'); + })); + + + it('should return a diamond path', inject(function(canvas, elementRegistry, renderer) { + + // given + var gatewayElement = elementRegistry.get('ExclusiveGateway_1'); + + // when + var gatewayPath = renderer.getShapePath(gatewayElement); + + // then + expect(gatewayPath).toEqual('M418,318l25,25l-25,25l-25,-25z'); + })); + + + it('should return a rounded rectangular path', inject(function(canvas, elementRegistry, renderer) { + + // given + var subProcessElement = elementRegistry.get('SubProcess_1'); + + // when + var subProcessPath = renderer.getShapePath(subProcessElement); + + // then + expect(subProcessPath).toEqual('M584,243l330,0a10,10,0,0,1,10,10l0,180a10,10,0,0,1,-10,10' + + 'l-330,0a10,10,0,0,1,-10,-10l0,-180a10,10,0,0,1,10,-10z'); + })); + + + it('should return a rectangular path', inject(function(canvas, elementRegistry, renderer) { + + // given + var TextAnnotationElement = elementRegistry.get('TextAnnotation_1'); + + // when + var TextAnnotationPath = renderer.getShapePath(TextAnnotationElement); + + // then + expect(TextAnnotationPath).toEqual('M368,156l100,0l0,80l-100,0z'); + })); + + }); + +}); diff --git a/test/spec/features/modeling/ResizeShapeSpec.js b/test/spec/features/modeling/ResizeShapeSpec.js new file mode 100644 index 00000000..42202a39 --- /dev/null +++ b/test/spec/features/modeling/ResizeShapeSpec.js @@ -0,0 +1,73 @@ +'use strict'; + +var Matchers = require('../../../Matchers'), + TestHelper = require('../../../TestHelper'); + +/* global bootstrapModeler, inject */ + + +var modelingModule = require('../../../../lib/features/modeling'), + coreModule = require('../../../../lib/core'); + + +describe('features/modeling - resize shape', function() { + + beforeEach(Matchers.addDeepEquals); + + + var diagramXML = require('../../../fixtures/bpmn/simple-resizable.bpmn'); + + var testModules = [ coreModule, modelingModule ]; + + beforeEach(bootstrapModeler(diagramXML, { modules: testModules })); + + + describe('shape', function() { + + + it('should resize', inject(function(elementRegistry, modeling) { + + // given + var subProcessElement = elementRegistry.get('SubProcess_1'); + + var sequenceFlowElement = elementRegistry.get('SequenceFlow_2'), + sequenceFlow = sequenceFlowElement.businessObject; + + // when + + // Decreasing width by 100px + modeling.resizeShape(subProcessElement, { x: 339, y: 142, width: 250, height: 200 }); + + // then + + // expect flow layout + expect(sequenceFlow.di.waypoint).toDeepEqual([ + { $type: 'dc:Point', x: 589, y: 242 }, + { $type: 'dc:Point', x: 821, y: 242 } + ]); + })); + + + it('should move', inject(function(elementRegistry, modeling) { + + // given + var subProcessElement = elementRegistry.get('SubProcess_1'); + + var sequenceFlowElement = elementRegistry.get('SequenceFlow_2'), + sequenceFlow = sequenceFlowElement.businessObject; + + // when + modeling.moveShape(subProcessElement, { x: -50, y: 0 }); + + // then + + // expect flow layout + expect(sequenceFlow.di.waypoint).toDeepEqual([ + { $type: 'dc:Point', x: 639, y: 242 }, + { $type: 'dc:Point', x: 821, y: 242 } + ]); + })); + + }); + +}); diff --git a/test/spec/features/modeling/SpaceToolSpec.js b/test/spec/features/modeling/SpaceToolSpec.js index 7e13266b..222a0134 100644 --- a/test/spec/features/modeling/SpaceToolSpec.js +++ b/test/spec/features/modeling/SpaceToolSpec.js @@ -221,5 +221,7 @@ describe('features/modeling - create/remove space', function() { expect(task.di.bounds.x).toBe(taskOldPos.x + 50); expect(task.di.bounds.y).toBe(taskOldPos.y); })); + }); + });