import inherits from 'inherits-browser';
|
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
|
import { pointsAligned } from 'diagram-js/lib/util/Geometry';
|
import { assign } from 'min-dash';
|
import { DEFAULT_CONNECT } from '../../config/constants';
|
import { NodeUtils } from '../../utils/nodeUtil';
|
/**
|
* @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
|
* @typedef {import('diagram-js/lib/features/grid-snapping/GridSnapping').default} GridSnapping
|
* @typedef {import('../../modeling/Modeling').default} Modeling
|
*
|
* @typedef {import('diagram-js/lib/util/Types').Point} Point
|
*/
|
|
const HIGH_PRIORITY = 3000;
|
|
export default function GridSnappingLayoutConnectionBehavior(this: any, eventBus: any, gridSnapping: any, modeling: any, jnpfData: any, injector: any) {
|
CommandInterceptor.call(this, eventBus);
|
this._gridSnapping = gridSnapping;
|
this._injector = injector;
|
const self = this;
|
this.postExecuted(['connection.create', 'connection.layout'], HIGH_PRIORITY, function (event: any) {
|
let context = event.context,
|
connection = context.connection,
|
waypoints = connection.waypoints;
|
let target = connection.target,
|
source = connection.source;
|
// 横向美化
|
if (jnpfData.data?.layout?.value === 'horizontal') {
|
let x = source.x;
|
let y = source.y + source.height / 2;
|
let targetX = target.x + target.width / 2;
|
if (source.x + source.width <= target.x) {
|
// 右侧
|
x = source.x + source.width;
|
if (y === target.y + target.height / 2) {
|
waypoints = [
|
{ x: x, y: y },
|
{ x: target.x, y: target.y + target.height / 2 },
|
];
|
} else if (y >= target.y + target.height && x + 30 > target.x) {
|
waypoints = [
|
{ x: x, y: y },
|
{ x: targetX, y: y },
|
{ x: targetX, y: target.y + target.height },
|
];
|
} else if (y - 10 < target.y && x + 30 > target.x) {
|
waypoints = [
|
{ x: x, y: y },
|
{ x: targetX, y: y },
|
{ x: targetX, y: target.y },
|
];
|
} else {
|
if (target.x - source.x - source.width - DEFAULT_CONNECT / 2 > 0) {
|
waypoints = [
|
{ x: x, y: y },
|
{ x: target.x - DEFAULT_CONNECT / 2, y: y },
|
{ x: target.x - DEFAULT_CONNECT / 2, y: target.y + target.height / 2 },
|
{ x: target.x, y: target.y + target.height / 2 },
|
];
|
} else {
|
waypoints = [
|
{ x: x, y: y },
|
{ x: source.x + source.width + (target.x - source.x - source.width) / 2, y: y },
|
{ x: source.x + source.width + (target.x - source.x - source.width) / 2, y: target.y + target.height / 2 },
|
{ x: target.x, y: target.y + target.height / 2 },
|
];
|
}
|
}
|
} else if (source.x > target.x + target.width) {
|
// 左侧
|
x = target.x + target.width;
|
if (x + 30 > source.x) {
|
if (y - 10 > target.y + target.height) {
|
waypoints = [
|
{ x: source.x, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: target.y + target.height },
|
];
|
} else if (y - 10 < target.y + target.height) {
|
waypoints = [
|
{ x: source.x, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: target.y },
|
];
|
}
|
} else {
|
waypoints = [
|
{ x: source.x, y: source.y + source.height / 2 },
|
{ x: (source.x - x) / 2 + x, y: source.y + source.height / 2 },
|
{ x: (source.x - x) / 2 + x, y: target.y + target.height / 2 },
|
{ x: x, y: target.y + target.height / 2 },
|
];
|
}
|
} else {
|
// 上侧
|
if (target.y < source.y) {
|
if (source.x + source.width / 2 === target.x + target.width / 2) {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y },
|
{ x: target.x + target.width / 2, y: target.y + target.height },
|
];
|
} else if (target.y + target.height > source.y - 20) {
|
if (source.x + source.width / 2 >= target.x + target.width) {
|
// 左上
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y },
|
{ x: source.x + source.width / 2, y: target.y + target.height / 2 },
|
{ x: target.x + target.width, y: target.y + target.height / 2 },
|
];
|
} else if (source.x + source.width / 2 <= target.x) {
|
// 右上
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y },
|
{ x: source.x + source.width / 2, y: target.y + target.height / 2 },
|
{ x: target.x, y: target.y + target.height / 2 },
|
];
|
} else {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y },
|
{ x: source.x + source.width / 2, y: source.y - (source.y - target.y - target.height) / 2 },
|
{ x: target.x + target.width / 2, y: target.y + target.height },
|
];
|
}
|
} else {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y },
|
{ x: source.x + source.width / 2, y: source.y - (source.y - target.y - target.height) / 2 },
|
{ x: target.x + target.width / 2, y: source.y - (source.y - target.y - target.height) / 2 },
|
{ x: target.x + target.width / 2, y: target.y + target.height },
|
];
|
}
|
} else if (target.y + target.height > source.y + source.height) {
|
// 下侧
|
if (source.x + source.width / 2 === target.x + target.width / 2) {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y + source.height },
|
{ x: target.x + target.width / 2, y: target.y },
|
];
|
} else if (target.y - 20 < source.y + source.height) {
|
if (source.x + source.width / 2 >= target.x + target.width) {
|
// 左下
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y + source.height },
|
{ x: source.x + source.width / 2, y: target.y + target.height / 2 },
|
{ x: target.x + target.width, y: target.y + target.height / 2 },
|
];
|
} else if (source.x + source.width / 2 <= target.x) {
|
// 右下
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y + source.height },
|
{ x: source.x + source.width / 2, y: target.y + target.height / 2 },
|
{ x: target.x, y: target.y + target.height / 2 },
|
];
|
} else {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y + source.height },
|
{ x: source.x + source.width / 2, y: target.y - (target.y - source.y - source.height) / 2 },
|
{ x: target.x + target.width / 2, y: target.y - (target.y - source.y - source.height) / 2 },
|
{ x: target.x + target.width / 2, y: target.y },
|
];
|
}
|
} else {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y + source.height },
|
{ x: source.x + source.width / 2, y: target.y - (target.y - source.y - source.height) / 2 },
|
{ x: target.x + target.width / 2, y: target.y - (target.y - source.y - source.height) / 2 },
|
{ x: target.x + target.width / 2, y: target.y },
|
];
|
}
|
}
|
}
|
}
|
if (jnpfData.data?.layout?.value === 'vertical') {
|
if (source.y + source.height < target.y) {
|
if (source.x + source.width / 2 === target.x + target.width / 2) {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y + source.height },
|
{ x: target.x + target.width / 2, y: target.y },
|
];
|
} else {
|
if (source.y + source.height + 20 > target.y && source.x + source.width / 2 < target.x) {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y + source.height },
|
{ x: source.x + source.width / 2, y: target.y + target.height / 2 },
|
{ x: target.x, y: target.y + target.height / 2 },
|
];
|
} else if (source.y + source.height + 20 > target.y && source.x + source.width / 2 > target.x + target.width + 10) {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y + source.height },
|
{ x: source.x + source.width / 2, y: target.y + target.height / 2 },
|
{ x: target.x + target.width, y: target.y + target.height / 2 },
|
];
|
} else
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y + source.height },
|
{ x: source.x + source.width / 2, y: source.y + source.height + (target.y - source.y - source.height) / 2 },
|
{ x: target.x + target.width / 2, y: source.y + source.height + (target.y - source.y - source.height) / 2 },
|
{ x: target.x + target.width / 2, y: target.y },
|
];
|
}
|
} else if (source.y > target.y + target.height) {
|
if (source.x + source.width / 2 === target.x + target.width / 2) {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y },
|
{ x: target.x + target.width / 2, y: target.y + target.height },
|
];
|
} else {
|
if (source.y - 20 < target.y + target.height && source.x + source.width / 2 < target.x) {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y },
|
{ x: source.x + source.width / 2, y: target.y + target.height / 2 },
|
{ x: target.x, y: target.y + target.height / 2 },
|
];
|
} else if (source.y - 20 < target.y + target.height && source.x + source.width / 2 > target.x + target.width + 10) {
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y },
|
{ x: source.x + source.width / 2, y: target.y + target.height / 2 },
|
{ x: target.x + target.width, y: target.y + target.height / 2 },
|
];
|
} else
|
waypoints = [
|
{ x: source.x + source.width / 2, y: source.y },
|
{ x: source.x + source.width / 2, y: source.y - (source.y - target.y - target.height) / 2 },
|
{ x: target.x + target.width / 2, y: source.y - (source.y - target.y - target.height) / 2 },
|
{ x: target.x + target.width / 2, y: target.y + target.height },
|
];
|
}
|
} else if (source.x + source.width / 2 < target.x - 10) {
|
// 右侧
|
if (source.x + source.width >= target.x - 10 && source.y + source.height / 2 >= target.y + target.height - 10) {
|
waypoints = [
|
{ x: source.x + source.width, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: target.y + target.height },
|
];
|
} else if (source.x + source.width >= target.x - 10 && source.y + source.height / 2 + 10 <= target.y) {
|
waypoints = [
|
{ x: source.x + source.width, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: target.y },
|
];
|
} else {
|
waypoints = [
|
{ x: source.x + source.width, y: source.y + source.height / 2 },
|
{ x: source.x + source.width + (target.x - source.x - source.width) / 2, y: source.y + source.height / 2 },
|
{ x: source.x + source.width + (target.x - source.x - source.width) / 2, y: target.y + target.height / 2 },
|
{ x: target.x, y: target.y + target.height / 2 },
|
];
|
}
|
} else if (source.x + source.width / 2 > target.x + target.width - 10) {
|
// 左侧
|
if (source.x < target.x + target.width + 20 && source.y + source.height / 2 >= target.y + target.height - 10) {
|
waypoints = [
|
{ x: source.x, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: target.y + target.height },
|
];
|
} else if (source.x < target.x + target.width + 20 && source.y + source.height / 2 + 10 <= target.y) {
|
waypoints = [
|
{ x: source.x, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: source.y + source.height / 2 },
|
{ x: target.x + target.width / 2, y: target.y },
|
];
|
} else
|
waypoints = [
|
{ x: source.x, y: source.y + source.height / 2 },
|
{ x: target.x + target.width + (source.x - target.x - target.width) / 2, y: source.y + source.height / 2 },
|
{ x: target.x + target.width + (source.x - target.x - target.width) / 2, y: target.y + target.height / 2 },
|
{ x: target.x + target.width, y: target.y + target.height / 2 },
|
];
|
}
|
}
|
// 判断是横向还是纵向 如果是纵向 需要重新修改坐标
|
modeling.updateWaypoints(connection, self.snapMiddleSegments(waypoints));
|
let elementRegistry = injector.get('elementRegistry');
|
let labelCenter = NodeUtils.updateLabelWaypoints(connection, elementRegistry, jnpfData);
|
let connectLabel = connection.label;
|
if (connectLabel) {
|
let label = elementRegistry.get(connectLabel.id);
|
label.x = labelCenter.x;
|
label.y = labelCenter.y;
|
modeling.updateProperties(label, {});
|
}
|
});
|
}
|
|
GridSnappingLayoutConnectionBehavior.$inject = ['eventBus', 'gridSnapping', 'modeling', 'jnpfData', 'injector'];
|
inherits(GridSnappingLayoutConnectionBehavior, CommandInterceptor);
|
/**
|
* Snap middle segments of a given connection.
|
*
|
* @param {Point[]} waypoints
|
*
|
* @return {Point[]}
|
*/
|
GridSnappingLayoutConnectionBehavior.prototype.snapMiddleSegments = function (this: any, waypoints: any[]) {
|
const gridSnapping = this._gridSnapping;
|
waypoints = waypoints.slice();
|
|
for (let i = 1; i < waypoints.length - 2; i++) {
|
const snapped = snapSegment(gridSnapping, waypoints[i], waypoints[i + 1]);
|
waypoints[i] = snapped[0];
|
waypoints[i + 1] = snapped[1];
|
}
|
return waypoints;
|
};
|
|
/**
|
* Check whether a connection has middle segments.
|
*
|
* @param {Point[]} waypoints
|
*
|
* @return {boolean}
|
*/
|
function hasMiddleSegments(waypoints: any[]) {
|
return waypoints.length > 3;
|
}
|
|
/**
|
* Check whether an alignment is horizontal.
|
*
|
* @param {string} aligned
|
*
|
* @return {boolean}
|
*/
|
function horizontallyAligned(aligned: string) {
|
return aligned === 'h';
|
}
|
|
/**
|
* Check whether an alignment is vertical.
|
*
|
* @param {string} aligned
|
*
|
* @return {boolean}
|
*/
|
function verticallyAligned(aligned: string) {
|
return aligned === 'v';
|
}
|
|
/**
|
* Get middle segments from a given connection.
|
*
|
* @param {Point[]} waypoints
|
*
|
* @return {Point[]}
|
*/
|
function snapSegment(gridSnapping: any, segmentStart: any, segmentEnd: any) {
|
const aligned: any = pointsAligned(segmentStart, segmentEnd);
|
const snapped: any = {};
|
|
if (horizontallyAligned(aligned)) {
|
snapped.y = gridSnapping.snapValue(segmentStart.y);
|
}
|
|
if (verticallyAligned(aligned)) {
|
snapped.x = gridSnapping.snapValue(segmentStart.x);
|
}
|
|
if ('x' in snapped || 'y' in snapped) {
|
segmentStart = assign({}, segmentStart, snapped);
|
segmentEnd = assign({}, segmentEnd, snapped);
|
}
|
|
return [segmentStart, segmentEnd];
|
}
|