From 6d61ac22887e47801dbc0ff3636f8405395b2209 Mon Sep 17 00:00:00 2001 From: Beatriz Mendes Date: Thu, 9 Nov 2023 19:09:57 +0100 Subject: [PATCH] feat(context-pad): position in connection last waypoint --- lib/features/context-pad/ContextPad.js | 15 ++++ .../features/context-pad/ContextPadSpec.js | 76 +++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/lib/features/context-pad/ContextPad.js b/lib/features/context-pad/ContextPad.js index ad1a30aec..287154488 100644 --- a/lib/features/context-pad/ContextPad.js +++ b/lib/features/context-pad/ContextPad.js @@ -23,6 +23,9 @@ import { escapeCSS } from '../../util/EscapeUtil'; +import { isConnection } from '../../util/ModelUtil'; + + /** * @typedef {import('../../model/Types').Element} Element * @@ -507,12 +510,20 @@ ContextPad.prototype.isShown = function() { /** * Get contex pad position. * + * If target is a connection, the context pad will be placed according to the + * cnnection's last waypoint. + * + * If multiple targets, the context pad will be placed according to the bounding + * box containing all targets. + * * @param {ContextPadTarget} target * * @return {Rect} */ ContextPad.prototype._getPosition = function(target) { + target = isConnection(target) ? getLastWaypoint(target) : target; + var elements = isArray(target) ? target : [ target ]; var bBox = getBBox(elements); @@ -545,4 +556,8 @@ function addClasses(element, classNames) { */ function includes(array, item) { return array.indexOf(item) !== -1; +} + +function getLastWaypoint(connection) { + return connection.waypoints[connection.waypoints.length - 1]; } \ No newline at end of file diff --git a/test/spec/features/context-pad/ContextPadSpec.js b/test/spec/features/context-pad/ContextPadSpec.js index 7c27c9edb..06a402319 100755 --- a/test/spec/features/context-pad/ContextPadSpec.js +++ b/test/spec/features/context-pad/ContextPadSpec.js @@ -16,6 +16,8 @@ import { classes as domClasses } from 'min-dom'; +import { getBBox } from 'lib/util/Elements'; + import contextPadModule from 'lib/features/context-pad'; import selectionModule from 'lib/features/selection'; @@ -1356,4 +1358,78 @@ describe('features/context-pad', function() { })); }); + + describe('position', function() { + + beforeEach(bootstrapDiagram({ + modules: [ + contextPadModule + ] + })); + + + describe('single element', function() { + + it('shape', inject(function(canvas, contextPad) { + + // given + var shape = { id: 's1', width: 100, height: 100, x: 10, y: 10 }; + + canvas.addShape(shape); + + // when + const pad = contextPad.getPad(shape); + + // then + var bBox = getBBox(shape); + expect(pad.position).to.eql({ + left: bBox.x + bBox.width + 12, + top: bBox.y - 12 / 2 + }); + })); + + + it('connection', inject(function(canvas, contextPad) { + + // given + var connection = { id: 'c1', waypoints: [ { x: 0, y: 0 }, { x: 100, y: 100 } ] }; + + canvas.addConnection(connection); + + // when + const pad = contextPad.getPad(connection); + + // then + var bBox = getBBox(connection.waypoints[connection.waypoints.length - 1]); + expect(pad.position).to.eql({ + left: bBox.x + bBox.width + 12, + top: bBox.y - 12 / 2 + }); + })); + + }); + + + it('multi element', inject(function(canvas, contextPad) { + + // given + var shape1 = { id: 's1', width: 100, height: 100, x: 10, y: 10 }; + var shape2 = { id: 's2', width: 100, height: 100, x: 210, y: 10 }; + + canvas.addShape(shape1); + canvas.addShape(shape2); + + // when + const pad = contextPad.getPad([ shape1, shape2 ]); + + // then + var bBox = getBBox([ shape1, shape2 ]); + expect(pad.position).to.eql({ + left: bBox.x + bBox.width + 12, + top: bBox.y - 12 / 2 + }); + })); + + }); + });