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
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 ]; |
|
} |