From a77796b2714dbad29d1db1969482763cd7948cd8 Mon Sep 17 00:00:00 2001 From: pedesen Date: Tue, 13 Oct 2015 11:07:35 +0200 Subject: [PATCH] fix(modeling): retain connection layout for (data-)associations Closes #380 --- lib/features/modeling/BpmnLayouter.js | 3 + .../modeling/layout/LayoutAssociationSpec.js | 95 +++++++++++++++++++ .../layout/LayoutDataAssociationSpec.js | 93 ++++++++++++++++++ 3 files changed, 191 insertions(+) create mode 100644 test/spec/features/modeling/layout/LayoutAssociationSpec.js create mode 100644 test/spec/features/modeling/layout/LayoutDataAssociationSpec.js diff --git a/lib/features/modeling/BpmnLayouter.js b/lib/features/modeling/BpmnLayouter.js index 81fb0b69..17434601 100644 --- a/lib/features/modeling/BpmnLayouter.js +++ b/lib/features/modeling/BpmnLayouter.js @@ -38,6 +38,9 @@ BpmnLayouter.prototype.layoutConnection = function(connection, layoutHints) { // TODO (nre): support vertical modeling // and invert preferredLayouts accordingly + if ((is(connection, 'bpmn:Association') || is(connection, 'bpmn:DataAssociation')) && waypoints) { + return waypoints; + } // manhattan layout sequence / message flows if (is(connection, 'bpmn:MessageFlow')) { diff --git a/test/spec/features/modeling/layout/LayoutAssociationSpec.js b/test/spec/features/modeling/layout/LayoutAssociationSpec.js new file mode 100644 index 00000000..d1bc370b --- /dev/null +++ b/test/spec/features/modeling/layout/LayoutAssociationSpec.js @@ -0,0 +1,95 @@ +'use strict'; + +var TestHelper = require('../../../../TestHelper'); + +/* global bootstrapModeler, inject */ + +var modelingModule = require('../../../../../lib/features/modeling'), + coreModule = require('../../../../../lib/core'); + +describe('features/modeling - layout association', function() { + + var diagramXML = require('../../../../fixtures/bpmn/basic.bpmn'); + + var testModules = [ coreModule, modelingModule ]; + + var rootShape; + + beforeEach(bootstrapModeler(diagramXML, { modules: testModules })); + + beforeEach(inject(function(canvas){ + rootShape = canvas.getRootElement(); + })); + + it('should layout straight after TextAnnotation creation', inject(function(elementRegistry, modeling) { + + // given + var startEventShape = elementRegistry.get('StartEvent_1'); + + // when + var textAnnotationShape = modeling.createShape({ type: 'bpmn:TextAnnotation' }, { x: 400, y: 400 }, rootShape); + + modeling.connect(textAnnotationShape, startEventShape); + + var waypoints = textAnnotationShape.outgoing[0].waypoints; + + // then + expect(waypoints).to.eql([ + { original: { x: 400, y: 400 }, x: 370, y: 360 }, + { original: { x: 191, y: 120 }, x: 202, y: 134 } + ]); + + })); + + + it('should layout straight after TextAnnotation move', inject(function(elementRegistry, modeling) { + + // given + var startEventShape = elementRegistry.get('StartEvent_1'), + textAnnotationShape = modeling.createShape({ type: 'bpmn:TextAnnotation' }, { x: 400, y: 400 }, rootShape); + + modeling.connect(textAnnotationShape, startEventShape); + + // when + modeling.moveElements([ textAnnotationShape ], { x: 20, y: 0 }, rootShape); + + var waypoints = textAnnotationShape.outgoing[0].waypoints; + + // then + expect(waypoints).to.eql([ + { original: { x: 420, y: 400 }, x: 387, y: 360 }, + { original: { x: 191, y: 120 }, x: 202, y: 134 } + ]); + + })); + + + it('should retain waypoints after TextAnnotation move', inject(function(elementRegistry, modeling) { + + // given + var startEventShape = elementRegistry.get('StartEvent_1'), + textAnnotationShape = modeling.createShape({ type: 'bpmn:TextAnnotation' }, { x: 400, y: 400 }, rootShape); + + var connection = modeling.connect(textAnnotationShape, startEventShape), + waypoints = connection.waypoints; + + // add a waypoint + waypoints.splice(1, 0, { x: 400, y: 300 }); + + modeling.updateWaypoints(connection, waypoints); + + // when + modeling.moveElements([ textAnnotationShape ], { x: 20, y: 0 }, rootShape); + + waypoints = textAnnotationShape.outgoing[0].waypoints; + + // then + expect(waypoints).to.eql([ + { original: { x: 420, y: 400 }, x: 412, y: 360 }, + { x: 400, y: 300 }, + { original: { x: 191, y: 120 }, x: 204, y: 131 } + ]); + + })); + +}); diff --git a/test/spec/features/modeling/layout/LayoutDataAssociationSpec.js b/test/spec/features/modeling/layout/LayoutDataAssociationSpec.js new file mode 100644 index 00000000..6c5ff32f --- /dev/null +++ b/test/spec/features/modeling/layout/LayoutDataAssociationSpec.js @@ -0,0 +1,93 @@ +'use strict'; + +var TestHelper = require('../../../../TestHelper'); + +/* global bootstrapModeler, inject */ + + +var modelingModule = require('../../../../../lib/features/modeling'), + coreModule = require('../../../../../lib/core'); + + +describe('features/modeling - layout data association', function() { + + var diagramXML = require('../../../../fixtures/bpmn/basic.bpmn'); + + var testModules = [ coreModule, modelingModule ]; + + var rootShape, + taskShape; + + beforeEach(bootstrapModeler(diagramXML, { modules: testModules })); + + beforeEach(inject(function(elementRegistry, canvas){ + rootShape = canvas.getRootElement(); + taskShape = elementRegistry.get('Task_1'); + })); + + it('should layout straight after DataObjectReference creation', inject(function(modeling) { + + // when + var dataObjectShape = modeling.createShape({ type: 'bpmn:DataObjectReference' }, { x: 200, y: 400 }, rootShape); + + modeling.connect(dataObjectShape, taskShape); + + var waypoints = dataObjectShape.outgoing[0].waypoints; + + // then + expect(waypoints).to.eql([ + { original: { x: 200, y: 400 }, x: 218, y: 375 }, + { original: { x: 403, y: 120 }, x: 374, y: 160 } + ]); + + })); + + + it('should layout straight after DataObjectReference move', inject(function(modeling) { + + // given + var dataObjectShape = modeling.createShape({ type: 'bpmn:DataObjectReference' }, { x: 200, y: 400 }, rootShape); + + modeling.connect(dataObjectShape, taskShape); + + // when + modeling.moveElements([ dataObjectShape ], { x: 20, y: 0 }, rootShape); + + var waypoints = dataObjectShape.outgoing[0].waypoints; + + // then + expect(waypoints).to.eql([ + { original: { x: 220, y: 400 }, x: 236, y: 375 }, + { original: { x: 403, y: 120 }, x: 377, y: 160 } + ]); + + })); + + + it('should retain waypoints after DataObjectReference move', inject(function(modeling) { + + // given + var dataObjectShape = modeling.createShape({ type: 'bpmn:DataObjectReference' }, { x: 200, y: 400 }, rootShape), + connection = modeling.connect(dataObjectShape, taskShape), + waypoints = connection.waypoints; + + // add a waypoint + waypoints.splice(1, 0, { x: 400, y: 300 }); + + modeling.updateWaypoints(connection, waypoints); + + // when + modeling.moveElements([ dataObjectShape ], { x: 20, y: 0 }, rootShape); + + waypoints = taskShape.incoming[0].waypoints; + + // then + expect(waypoints).to.eql([ + { original: { x: 220, y: 400 }, x: 238, y: 390 }, + { x: 400, y: 300 }, + { original: { x: 403, y: 120 }, x: 402, y: 160 } + ]); + + })); + +});