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