You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
3.2 KiB
148 lines
3.2 KiB
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; |
|
} |