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.
144 lines
2.9 KiB
144 lines
2.9 KiB
2 years ago
|
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';
|
||
|
|
||
|
var HIGH_PRIORITY = 3000;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Snaps connections with Manhattan layout.
|
||
|
*/
|
||
|
export default function GridSnappingLayoutConnectionBehavior(eventBus, gridSnapping, modeling) {
|
||
|
CommandInterceptor.call(this, eventBus);
|
||
|
|
||
|
this._gridSnapping = gridSnapping;
|
||
|
|
||
|
var self = this;
|
||
|
|
||
|
this.postExecuted([
|
||
|
'connection.create',
|
||
|
'connection.layout'
|
||
|
], HIGH_PRIORITY, function(event) {
|
||
|
var context = event.context,
|
||
|
connection = context.connection,
|
||
|
hints = context.hints || {},
|
||
|
waypoints = connection.waypoints;
|
||
|
|
||
|
if (hints.connectionStart || hints.connectionEnd || hints.createElementsBehavior === false) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!hasMiddleSegments(waypoints)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
modeling.updateWaypoints(connection, self.snapMiddleSegments(waypoints));
|
||
|
});
|
||
|
}
|
||
|
|
||
|
GridSnappingLayoutConnectionBehavior.$inject = [
|
||
|
'eventBus',
|
||
|
'gridSnapping',
|
||
|
'modeling'
|
||
|
];
|
||
|
|
||
|
inherits(GridSnappingLayoutConnectionBehavior, CommandInterceptor);
|
||
|
|
||
|
/**
|
||
|
* Snap middle segments of a given connection.
|
||
|
*
|
||
|
* @param {Array<Point>} waypoints
|
||
|
*
|
||
|
* @returns {Array<Point>}
|
||
|
*/
|
||
|
GridSnappingLayoutConnectionBehavior.prototype.snapMiddleSegments = function(waypoints) {
|
||
|
var gridSnapping = this._gridSnapping,
|
||
|
snapped;
|
||
|
|
||
|
waypoints = waypoints.slice();
|
||
|
|
||
|
for (var i = 1; i < waypoints.length - 2; i++) {
|
||
|
|
||
|
snapped = snapSegment(gridSnapping, waypoints[i], waypoints[i + 1]);
|
||
|
|
||
|
waypoints[i] = snapped[0];
|
||
|
waypoints[i + 1] = snapped[1];
|
||
|
}
|
||
|
|
||
|
return waypoints;
|
||
|
};
|
||
|
|
||
|
|
||
|
// helpers //////////
|
||
|
|
||
|
/**
|
||
|
* Check whether a connection has a middle segments.
|
||
|
*
|
||
|
* @param {Array} waypoints
|
||
|
*
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
function hasMiddleSegments(waypoints) {
|
||
|
return waypoints.length > 3;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check whether an alignment is horizontal.
|
||
|
*
|
||
|
* @param {string} aligned
|
||
|
*
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
function horizontallyAligned(aligned) {
|
||
|
return aligned === 'h';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check whether an alignment is vertical.
|
||
|
*
|
||
|
* @param {string} aligned
|
||
|
*
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
function verticallyAligned(aligned) {
|
||
|
return aligned === 'v';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get middle segments from a given connection.
|
||
|
*
|
||
|
* @param {Array} waypoints
|
||
|
*
|
||
|
* @returns {Array}
|
||
|
*/
|
||
|
function snapSegment(gridSnapping, segmentStart, segmentEnd) {
|
||
|
|
||
|
var aligned = pointsAligned(segmentStart, segmentEnd);
|
||
|
|
||
|
var snapped = {};
|
||
|
|
||
|
if (horizontallyAligned(aligned)) {
|
||
|
|
||
|
// snap horizontally
|
||
|
snapped.y = gridSnapping.snapValue(segmentStart.y);
|
||
|
}
|
||
|
|
||
|
if (verticallyAligned(aligned)) {
|
||
|
|
||
|
// snap vertically
|
||
|
snapped.x = gridSnapping.snapValue(segmentStart.x);
|
||
|
}
|
||
|
|
||
|
if ('x' in snapped || 'y' in snapped) {
|
||
|
segmentStart = assign({}, segmentStart, snapped);
|
||
|
segmentEnd = assign({}, segmentEnd, snapped);
|
||
|
}
|
||
|
|
||
|
return [ segmentStart, segmentEnd ];
|
||
|
}
|