From 2e4cd7e0a93bd64ba94ef1180c3abf9aca188aaf Mon Sep 17 00:00:00 2001 From: Nico Rehwaldt Date: Fri, 15 Dec 2017 09:35:18 +0100 Subject: [PATCH] chore(auto-place): factor out deconflict position into method --- lib/features/auto-place/AutoPlaceUtil.js | 133 +++++++++++++++-------- 1 file changed, 89 insertions(+), 44 deletions(-) diff --git a/lib/features/auto-place/AutoPlaceUtil.js b/lib/features/auto-place/AutoPlaceUtil.js index 54e25673..5a4cf86e 100644 --- a/lib/features/auto-place/AutoPlaceUtil.js +++ b/lib/features/auto-place/AutoPlaceUtil.js @@ -34,21 +34,14 @@ function getFlowNodePosition(source, element) { y: sourceMid.y }; - var existingTarget; + var escapeDirection = { + y: { + margin: 30, + rowSize: 80 + } + }; - // make sure we don't place targets a - while ((existingTarget = getConnectedAtPosition(source, position, element))) { - - position = { - x: position.x, - y: Math.max( - existingTarget.y + existingTarget.height + 30 + element.height / 2, - position.y + 80 - ) - }; - } - - return position; + return deconflictPosition(source, element, position, escapeDirection); } module.exports.getFlowNodePosition = getFlowNodePosition; @@ -153,27 +146,19 @@ function getTextAnnotationPosition(source, element) { var sourceTrbl = asTRBL(source); - // todo: adaptive var position = { x: sourceTrbl.right + 30 + element.width / 2, y: sourceTrbl.top - 50 - element.height / 2 }; - var existingTarget; + var escapeDirection = { + y: { + margin: -30, + rowSize: 30 + } + }; - while ((existingTarget = getConnectedAtPosition(source, position, element))) { - - // escape to top - position = { - x: position.x, - y: Math.min( - existingTarget.y - 30 - element.height / 2, - position.y - 30 - ) - }; - } - - return position; + return deconflictPosition(source, element, position, escapeDirection); } module.exports.getTextAnnotationPosition = getTextAnnotationPosition; @@ -191,21 +176,14 @@ function getDataElementPosition(source, element) { y: sourceTrbl.bottom + 40 + element.width / 2 }; - var existingTarget; + var escapeDirection = { + x: { + margin: 30, + rowSize: 80 + } + }; - while ((existingTarget = getConnectedAtPosition(source, position, element))) { - - // escape to right - position = { - x: Math.min( - existingTarget.x + existingTarget.width + 30 + element.width / 2, - position.x + 80 - ), - y: position.y - }; - } - - return position; + return deconflictPosition(source, element, position, escapeDirection); } module.exports.getDataElementPosition = getDataElementPosition; @@ -259,4 +237,71 @@ function getConnectedAtPosition(source, position, element) { }); } -module.exports.getConnectedAtPosition = getConnectedAtPosition; \ No newline at end of file +module.exports.getConnectedAtPosition = getConnectedAtPosition; + + +/** + * Returns a new, position for the given element + * based on the given element that is not occupied + * by any element connected to source. + * + * Take into account the escapeDirection (where to move + * on positining clashes) in the computation. + * + * @param {djs.model.Shape} source + * @param {djs.model.Shape} element + * @param {Point} position + * @param {Object} escapeDelta + * + * @return {Point} + */ +function deconflictPosition(source, element, position, escapeDelta) { + + function nextPosition(existingElement) { + + var newPosition = { + x: position.x, + y: position.y + }; + + [ 'x', 'y' ].forEach(function(axis) { + + var axisDelta = escapeDelta[axis]; + + if (!axisDelta) { + return; + } + + var dimension = axis === 'x' ? 'width' : 'height'; + + var margin = axisDelta.margin, + rowSize = axisDelta.rowSize; + + if (margin < 0) { + newPosition[axis] = Math.min( + existingElement[axis] + margin - element[dimension] / 2, + position[axis] - rowSize + margin + ); + } else { + newPosition[axis] = Math.max( + existingTarget[axis] + existingTarget[dimension] + margin + element[dimension] / 2, + position[axis] + rowSize + margin + ); + } + }); + + return newPosition; + } + + var existingTarget; + + + // deconflict position until free slot is found + while ((existingTarget = getConnectedAtPosition(source, position, element))) { + position = nextPosition(existingTarget); + } + + return position; +} + +module.exports.deconflictPosition = deconflictPosition; \ No newline at end of file