From f266064c4ffe179b6cda1797c900b3612127bdb9 Mon Sep 17 00:00:00 2001 From: Martin Stamm Date: Wed, 21 Apr 2021 10:39:24 +0200 Subject: [PATCH] feat(auto-place): scroll canvas to new element related to https://github.com/camunda/camunda-modeler/issues/1249 --- lib/features/auto-place/BpmnAutoPlace.js | 14 +++- lib/features/auto-place/BpmnAutoPlaceUtil.js | 22 ++++++ .../features/auto-place/BpmnAutoPlaceSpec.js | 68 +++++++++++++++++++ 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/lib/features/auto-place/BpmnAutoPlace.js b/lib/features/auto-place/BpmnAutoPlace.js index cd2e117110..5b5d3fa577 100644 --- a/lib/features/auto-place/BpmnAutoPlace.js +++ b/lib/features/auto-place/BpmnAutoPlace.js @@ -1,4 +1,4 @@ -import { getNewShapePosition } from './BpmnAutoPlaceUtil'; +import { getNewShapePosition, getScrollOffset } from './BpmnAutoPlaceUtil'; /** @@ -6,13 +6,21 @@ import { getNewShapePosition } from './BpmnAutoPlaceUtil'; * * @param {EventBus} eventBus */ -export default function AutoPlace(eventBus) { +export default function AutoPlace(eventBus, canvas) { eventBus.on('autoPlace', function(context) { var shape = context.shape, source = context.source; return getNewShapePosition(source, shape); }); + + + eventBus.on('autoPlace.end', function(event) { + var viewBox = canvas.viewbox(); + var shape = event.shape; + + canvas.scroll(getScrollOffset(shape, viewBox)); + }); } -AutoPlace.$inject = [ 'eventBus' ]; \ No newline at end of file +AutoPlace.$inject = [ 'eventBus', 'canvas' ]; \ No newline at end of file diff --git a/lib/features/auto-place/BpmnAutoPlaceUtil.js b/lib/features/auto-place/BpmnAutoPlaceUtil.js index bb7343ecad..a9965df03d 100644 --- a/lib/features/auto-place/BpmnAutoPlaceUtil.js +++ b/lib/features/auto-place/BpmnAutoPlaceUtil.js @@ -135,4 +135,26 @@ export function getDataElementPosition(source, element) { }; return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection)); +} + +/** + * Always have the new element in frame + */ +export function getScrollOffset(element, boundingBox) { + var elementTrbl = asTRBL(element); + var bbTrbl = asTRBL(boundingBox); + + // Bigger padding to accommodate the context pad + var paddingRight = 80; + var padding = 10; + + var dRight = Math.max(0, elementTrbl.right - bbTrbl.right + paddingRight); + var dLeft = Math.min(0, elementTrbl.left - bbTrbl.left - padding); + var dBottom = Math.max(0, elementTrbl.bottom - bbTrbl.bottom + padding); + var dTop = Math.min(0, elementTrbl.top - bbTrbl.top - padding); + + var dx = dRight || dLeft; + var dy = dBottom || dTop; + + return { dx: -dx, dy: -dy }; } \ No newline at end of file diff --git a/test/spec/features/auto-place/BpmnAutoPlaceSpec.js b/test/spec/features/auto-place/BpmnAutoPlaceSpec.js index a672802e12..5dcee85e74 100644 --- a/test/spec/features/auto-place/BpmnAutoPlaceSpec.js +++ b/test/spec/features/auto-place/BpmnAutoPlaceSpec.js @@ -4,6 +4,7 @@ import { } from 'test/TestHelper'; import autoPlaceModule from 'lib/features/auto-place'; +import { getScrollOffset } from 'lib/features/auto-place/BpmnAutoPlaceUtil'; import coreModule from 'lib/core'; import labelEditingModule from 'lib/features/label-editing'; import modelingModule from 'lib/features/modeling'; @@ -255,6 +256,73 @@ describe('features/auto-place', function() { }); + + describe('scroll handling', function() { + + it('scrolls element into view', function() { + + // given + var element = { x: 0, y: 0, width: 20, height: 20 }; + var viewBox = { x: 100, y: 100, width: 100, height: 100 }; + + // when + var scrollArguments = getScrollOffset(element, viewBox); + + // then + expect(scrollArguments.dx).to.equal(110); + expect(scrollArguments.dy).to.equal(110); + + }); + + + it('does not scroll when inside bounds', function() { + + // given + var element = { x: 10, y: 10, width: 10, height: 10 }; + var viewBox = { x: 0, y: 0, width: 100, height: 100 }; + + // when + var scrollArguments = getScrollOffset(element, viewBox); + + // then + expect(scrollArguments.dx).to.equal(0); + expect(scrollArguments.dy).to.equal(0); + + }); + + + it('adds padding', function() { + + // given + var element = { x: 0, y: 0, width: 10, height: 10 }; + var viewBox = { x: 0, y: 0, width: 100, height: 100 }; + + // when + var scrollArguments = getScrollOffset(element, viewBox); + + // then + expect(scrollArguments.dx).to.equal(10); + expect(scrollArguments.dy).to.equal(10); + + }); + + + it('adds more padding on the right', function() { + + // given + var element = { x: 90, y: 10, width: 10, height: 10 }; + var viewBox = { x: 0, y: 0, width: 100, height: 100 }; + + // when + var scrollArguments = getScrollOffset(element, viewBox); + + // then + expect(scrollArguments.dx).to.equal(-80); + + }); + + }); + });