chore(connect-snapping): snap correctly

This commit is contained in:
Philipp Fromme 2019-11-05 12:47:11 +01:00 committed by Nico Rehwaldt
parent ef5a72d722
commit bdc3b70b2a
1 changed files with 70 additions and 61 deletions

View File

@ -11,22 +11,19 @@ import {
import { is } from '../../util/ModelUtil';
import {
some
} from 'min-dash';
import { isAny } from '../modeling/util/ModelingUtil';
import { some } from 'min-dash';
var HIGHER_PRIORITY = 1250;
var BOUNDARY_TO_HOST_THRESHOLD = 40;
var TARGET_BOUNDS_PADDING = 20;
var TARGET_BOUNDS_PADDING = 20,
TASK_BOUNDS_PADDING = 10;
var TARGET_CENTER_PADDING = 20;
var TASK_BOUNDS_PADDING = 10;
var AXES = [ 'x', 'y' ];
var abs = Math.abs;
@ -44,66 +41,67 @@ export default function BpmnConnectSnapping(eventBus, rules) {
'connect.end',
], HIGHER_PRIORITY, function(event) {
var context = event.context,
canExecute = context.canExecute,
start = context.start,
hover = context.hover,
source = context.source,
target = context.target;
// do NOT snap on CMD
if (event.originalEvent && isCmd(event.originalEvent)) {
return;
}
if (!context.initialSourcePosition) {
context.initialSourcePosition = context.sourcePosition;
if (!context.initialConnectionStart) {
context.initialConnectionStart = context.connectionStart;
}
var connectionAttrs = rules.allowed('connection.create', {
source: source,
target: target
});
if (target && connectionAttrs) {
snapInsideTarget(event, target, getTargetBoundsPadding(target));
// snap hover
if (canExecute && hover) {
snapToShape(event, hover, getTargetBoundsPadding(hover));
}
if (target && isAnyType(connectionAttrs, [
if (hover && isAnyType(canExecute, [
'bpmn:Association',
'bpmn:DataInputAssociation',
'bpmn:DataOutputAssociation',
'bpmn:SequenceFlow'
])) {
context.connectionStart = mid(start);
// snap source
context.sourcePosition = mid(source);
if (isAny(target, [ 'bpmn:Event', 'bpmn:Gateway' ])) {
snapToPosition(event, mid(target));
// snap hover
if (isAny(hover, [ 'bpmn:Event', 'bpmn:Gateway' ])) {
snapToPosition(event, mid(hover));
}
if (isAny(target, [ 'bpmn:Task', 'bpmn:SubProcess' ])) {
snapToTaskMid(event, target);
// snap hover
if (isAny(hover, [ 'bpmn:Task', 'bpmn:SubProcess' ])) {
snapToTargetMid(event, hover);
}
// snap source and target
if (is(source, 'bpmn:BoundaryEvent') && target === source.host) {
snapBoundaryEventLoop(event, source, target);
snapBoundaryEventLoop(event);
}
} else if (isType(connectionAttrs, 'bpmn:MessageFlow')) {
} else if (isType(canExecute, 'bpmn:MessageFlow')) {
if (is(source, 'bpmn:Event')) {
if (is(start, 'bpmn:Event')) {
// snap source
context.sourcePosition = mid(source);
// snap start
context.connectionStart = mid(start);
}
if (is(target, 'bpmn:Event')) {
if (is(hover, 'bpmn:Event')) {
// snap target
snapToPosition(event, mid(target));
// snap hover
snapToPosition(event, mid(hover));
}
} else {
// un-snap source
context.sourcePosition = context.initialSourcePosition;
context.connectionStart = context.initialConnectionStart;
}
});
}
@ -113,58 +111,64 @@ BpmnConnectSnapping.$inject = [
'rules'
];
function snapInsideTarget(event, target, padding) {
// helpers //////////
// snap to target if event in target
function snapToShape(event, target, padding) {
AXES.forEach(function(axis) {
var matchingTargetDimension = getDimensionForAxis(axis, target),
newCoordinate;
var dimensionForAxis = getDimensionForAxis(axis, target);
if (event[axis] < target[axis] + padding) {
newCoordinate = target[axis] + padding;
} else if (event[axis] > target[axis] + matchingTargetDimension - padding) {
newCoordinate = target[axis] + matchingTargetDimension - padding;
}
if (newCoordinate) {
setSnapped(event, axis, newCoordinate);
if (event[ axis ] < target[ axis ] + padding) {
setSnapped(event, axis, target[ axis ] + padding);
} else if (event[ axis ] > target[ axis ] + dimensionForAxis - padding) {
setSnapped(event, axis, target[ axis ] + dimensionForAxis - padding);
}
});
}
// snap to target mid if event in center
function snapToTaskMid(event, target) {
// snap to target mid if event in target mid
function snapToTargetMid(event, target) {
var targetMid = mid(target);
AXES.forEach(function(axis) {
if (isCenter(event, target, axis)) {
if (isMid(event, target, axis)) {
setSnapped(event, axis, targetMid[ axis ]);
}
});
}
// snap outside of Boundary Event surroundings
function snapBoundaryEventLoop(event, source, target) {
// snap to prevent loop overlapping boundary event
function snapBoundaryEventLoop(event) {
var context = event.context,
source = context.source,
target = context.target;
if (isReverse(context)) {
return;
}
var sourceMid = mid(source),
orientation = getOrientation(sourceMid, target, -10),
snappingAxes = [];
axes = [];
if (/top|bottom/.test(orientation)) {
snappingAxes.push('x');
axes.push('x');
}
if (/left|right/.test(orientation)) {
snappingAxes.push('y');
axes.push('y');
}
snappingAxes.forEach(function(axis) {
var coordinate = event[axis], newCoordinate;
axes.forEach(function(axis) {
var coordinate = event[ axis ], newCoordinate;
if (abs(coordinate - sourceMid[axis]) < BOUNDARY_TO_HOST_THRESHOLD) {
if (coordinate > sourceMid[axis]) {
newCoordinate = sourceMid[axis] + BOUNDARY_TO_HOST_THRESHOLD;
if (abs(coordinate - sourceMid[ axis ]) < BOUNDARY_TO_HOST_THRESHOLD) {
if (coordinate > sourceMid[ axis ]) {
newCoordinate = sourceMid[ axis ] + BOUNDARY_TO_HOST_THRESHOLD;
}
else {
newCoordinate = sourceMid[axis] - BOUNDARY_TO_HOST_THRESHOLD;
newCoordinate = sourceMid[ axis ] - BOUNDARY_TO_HOST_THRESHOLD;
}
setSnapped(event, axis, newCoordinate);
@ -172,8 +176,6 @@ function snapBoundaryEventLoop(event, source, target) {
});
}
// helpers //////////
function snapToPosition(event, position) {
setSnapped(event, 'x', position.x);
setSnapped(event, 'y', position.y);
@ -201,7 +203,14 @@ function getTargetBoundsPadding(target) {
}
}
function isCenter(event, target, axis) {
function isMid(event, target, axis) {
return event[ axis ] > target[ axis ] + TARGET_CENTER_PADDING
&& event[ axis ] < target[ axis ] + getDimensionForAxis(axis, target) - TARGET_CENTER_PADDING;
}
function isReverse(context) {
var hover = context.hover,
source = context.source;
return hover && source && hover === source;
}