148 lines
3.2 KiB
JavaScript
148 lines
3.2 KiB
JavaScript
import { is } from '../../util/ModelUtil';
|
|
import { isAny } from '../modeling/util/ModelingUtil';
|
|
|
|
import {
|
|
getMid,
|
|
asTRBL,
|
|
getOrientation
|
|
} from 'diagram-js/lib/layout/LayoutUtil';
|
|
|
|
import {
|
|
findFreePosition,
|
|
generateGetNextPosition,
|
|
getConnectedDistance
|
|
} from 'diagram-js/lib/features/auto-place/AutoPlaceUtil';
|
|
|
|
|
|
/**
|
|
* Find the new position for the target element to
|
|
* connect to source.
|
|
*
|
|
* @param {djs.model.Shape} source
|
|
* @param {djs.model.Shape} element
|
|
*
|
|
* @return {Point}
|
|
*/
|
|
export function getNewShapePosition(source, element) {
|
|
|
|
if (is(element, 'bpmn:TextAnnotation')) {
|
|
return getTextAnnotationPosition(source, element);
|
|
}
|
|
|
|
if (isAny(element, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ])) {
|
|
return getDataElementPosition(source, element);
|
|
}
|
|
|
|
if (is(element, 'bpmn:FlowNode')) {
|
|
return getFlowNodePosition(source, element);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Always try to place element right of source;
|
|
* compute actual distance from previous nodes in flow.
|
|
*/
|
|
export function getFlowNodePosition(source, element) {
|
|
|
|
var sourceTrbl = asTRBL(source);
|
|
var sourceMid = getMid(source);
|
|
|
|
var horizontalDistance = getConnectedDistance(source, {
|
|
filter: function(connection) {
|
|
return is(connection, 'bpmn:SequenceFlow');
|
|
}
|
|
});
|
|
|
|
var margin = 30,
|
|
minDistance = 80,
|
|
orientation = 'left';
|
|
|
|
if (is(source, 'bpmn:BoundaryEvent')) {
|
|
orientation = getOrientation(source, source.host, -25);
|
|
|
|
if (orientation.indexOf('top') !== -1) {
|
|
margin *= -1;
|
|
}
|
|
}
|
|
|
|
var position = {
|
|
x: sourceTrbl.right + horizontalDistance + element.width / 2,
|
|
y: sourceMid.y + getVerticalDistance(orientation, minDistance)
|
|
};
|
|
|
|
var nextPositionDirection = {
|
|
y: {
|
|
margin: margin,
|
|
minDistance: minDistance
|
|
}
|
|
};
|
|
|
|
return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
|
|
}
|
|
|
|
|
|
function getVerticalDistance(orientation, minDistance) {
|
|
if (orientation.indexOf('top') != -1) {
|
|
return -1 * minDistance;
|
|
} else if (orientation.indexOf('bottom') != -1) {
|
|
return minDistance;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Always try to place text annotations top right of source.
|
|
*/
|
|
export function getTextAnnotationPosition(source, element) {
|
|
|
|
var sourceTrbl = asTRBL(source);
|
|
|
|
var position = {
|
|
x: sourceTrbl.right + element.width / 2,
|
|
y: sourceTrbl.top - 50 - element.height / 2
|
|
};
|
|
|
|
if (isConnection(source)) {
|
|
position = getMid(source);
|
|
position.x += 100;
|
|
position.y -= 50;
|
|
}
|
|
|
|
var nextPositionDirection = {
|
|
y: {
|
|
margin: -30,
|
|
minDistance: 20
|
|
}
|
|
};
|
|
|
|
return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
|
|
}
|
|
|
|
|
|
/**
|
|
* Always put element bottom right of source.
|
|
*/
|
|
export function getDataElementPosition(source, element) {
|
|
|
|
var sourceTrbl = asTRBL(source);
|
|
|
|
var position = {
|
|
x: sourceTrbl.right - 10 + element.width / 2,
|
|
y: sourceTrbl.bottom + 40 + element.width / 2
|
|
};
|
|
|
|
var nextPositionDirection = {
|
|
x: {
|
|
margin: 30,
|
|
minDistance: 30
|
|
}
|
|
};
|
|
|
|
return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
|
|
}
|
|
|
|
function isConnection(element) {
|
|
return !!element.waypoints;
|
|
} |