144 lines
2.8 KiB
JavaScript
144 lines
2.8 KiB
JavaScript
import inherits from 'inherits';
|
|
|
|
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 LayoutConnectionBehavior(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) {
|
|
return;
|
|
}
|
|
|
|
if (!hasMiddleSegments(waypoints)) {
|
|
return;
|
|
}
|
|
|
|
modeling.updateWaypoints(connection, self.snapMiddleSegments(waypoints));
|
|
});
|
|
}
|
|
|
|
LayoutConnectionBehavior.$inject = [
|
|
'eventBus',
|
|
'gridSnapping',
|
|
'modeling'
|
|
];
|
|
|
|
inherits(LayoutConnectionBehavior, CommandInterceptor);
|
|
|
|
/**
|
|
* Snap middle segments of a given connection.
|
|
*
|
|
* @param {Array<Point>} waypoints
|
|
*
|
|
* @returns {Array<Point>}
|
|
*/
|
|
LayoutConnectionBehavior.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 ];
|
|
} |