From 540d05d6f2705a30b8cc29b03d58b6523a20b930 Mon Sep 17 00:00:00 2001 From: Beatriz Mendes Date: Thu, 9 Nov 2023 19:09:57 +0100 Subject: [PATCH 1/2] 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..c811e2c91 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 + * connection'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 + }); + })); + + }); + }); From 8ea3bd00f7a0926cd496493700da2d7f7acc854a Mon Sep 17 00:00:00 2001 From: Beatriz Mendes Date: Thu, 9 Nov 2023 19:29:09 +0100 Subject: [PATCH 2/2] feat(outline): connection outline only in multi-select --- assets/diagram-js.css | 5 ++++ .../selection/SelectionVisualsSpec.js | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/assets/diagram-js.css b/assets/diagram-js.css index aa73088be..ada938d74 100644 --- a/assets/diagram-js.css +++ b/assets/diagram-js.css @@ -121,8 +121,13 @@ stroke: var(--element-selected-outline-stroke-color); } +.djs-connection.selected .djs-outline { + display: none; +} + .djs-multi-select .djs-element.selected .djs-outline { stroke: var(--element-selected-outline-secondary-stroke-color); + display: block; } .djs-shape.connect-ok .djs-visual > :nth-child(1) { diff --git a/test/spec/features/selection/SelectionVisualsSpec.js b/test/spec/features/selection/SelectionVisualsSpec.js index a105ed7c5..0c240afe8 100755 --- a/test/spec/features/selection/SelectionVisualsSpec.js +++ b/test/spec/features/selection/SelectionVisualsSpec.js @@ -88,6 +88,21 @@ describe('features/selection/SelectionVisuals', function() { expect(domClasses(element).has('djs-multi-select')); })); + + it('should not show box for connection', inject(function(selection, canvas) { + + // when + // debugger; + selection.select(connection); + + // then + var gfx = canvas.getGraphics(connection), + outline = domQuery('.djs-outline', gfx); + + expect(outline).to.exist; + expect(getComputedStyle(outline).display).to.equal('none'); + })); + }); @@ -192,6 +207,15 @@ describe('features/selection/SelectionVisuals', function() { })); + + it('should show box for connection', inject(function(canvas) { + var gfx = canvas.getGraphics(connection), + outlineShape = domQuery('.djs-outline', gfx); + + expect(outlineShape).to.exist; + expect(getComputedStyle(outlineShape).display).to.not.equal('none'); + })); + }); });