bpmn-js/lib/features/modeling/BpmnLayouter.js

167 lines
3.8 KiB
JavaScript
Raw Normal View History

'use strict';
var inherits = require('inherits');
var assign = require('lodash/object/assign');
var BaseLayouter = require('diagram-js/lib/layout/BaseLayouter'),
ManhattanLayout = require('diagram-js/lib/layout/ManhattanLayout');
var LayoutUtil = require('diagram-js/lib/layout/LayoutUtil');
var getMid = LayoutUtil.getMid,
getOrientation = LayoutUtil.getOrientation;
var is = require('../../util/ModelUtil').is;
function BpmnLayouter() {}
inherits(BpmnLayouter, BaseLayouter);
module.exports = BpmnLayouter;
BpmnLayouter.prototype.layoutConnection = function(connection, layoutHints) {
var source = connection.source,
target = connection.target,
waypoints = connection.waypoints,
start,
end;
var manhattanOptions,
updatedWaypoints;
start = getConnectionDocking(waypoints, 0, source);
end = getConnectionDocking(waypoints, waypoints && waypoints.length - 1, target);
// TODO (nre): support vertical modeling
// and invert preferredLayouts accordingly
if (is(connection, 'bpmn:Association') ||
is(connection, 'bpmn:DataAssociation')) {
if (waypoints && !isCompensationAssociation(connection)) {
return waypoints;
}
}
// manhattan layout sequence / message flows
if (is(connection, 'bpmn:MessageFlow')) {
manhattanOptions = {
preferredLayouts: [ 'v:v' ]
};
if (is(target, 'bpmn:Participant')) {
manhattanOptions = {
preferredLayouts: [ 'straight', 'v:v' ]
};
}
if (is(source, 'bpmn:Participant') && is(target, 'bpmn:FlowNode')) {
manhattanOptions = {
preferredLayouts: [ 'straight', 'v:v' ],
moveSource: true
};
}
if (is(target, 'bpmn:Event')) {
manhattanOptions = {
preferredLayouts: [ 'v:v' ]
};
}
} else
// layout all connection between flow elements h:h,
//
// except for
//
// (1) outgoing of BoundaryEvents -> layout h:v or v:h based on attach orientation
// (2) incoming / outgoing of Gateway -> v:h (outgoing), h:v (incoming)
//
if (is(connection, 'bpmn:SequenceFlow') ||
isCompensationAssociation(connection)) {
// make sure boundary event connections do
// not look ugly =:>
if (is(source, 'bpmn:BoundaryEvent')) {
var orientation = getAttachOrientation(source);
if (/left|right/.test(orientation)) {
manhattanOptions = {
preferredLayouts: [ 'h:v' ]
};
} else
if (/top|bottom/.test(orientation)) {
manhattanOptions = {
preferredLayouts: [ 'v:h' ]
};
}
} else
if (is(source, 'bpmn:Gateway')) {
manhattanOptions = {
preferredLayouts: [ 'v:h' ]
};
} else
if (is(target, 'bpmn:Gateway')) {
manhattanOptions = {
preferredLayouts: [ 'h:v' ]
};
}
// apply horizontal love <3
else {
manhattanOptions = {
preferredLayouts: [ 'h:h' ]
};
}
}
if (manhattanOptions) {
manhattanOptions = assign(manhattanOptions, layoutHints);
updatedWaypoints =
ManhattanLayout.repairConnection(
source, target,
start, end,
waypoints,
manhattanOptions);
}
return updatedWaypoints || [ start, end ];
};
function getAttachOrientation(attachedElement) {
var hostElement = attachedElement.host,
padding = -10;
return getOrientation(getMid(attachedElement), hostElement, padding);
}
function getConnectionDocking(waypoints, idx, shape) {
var point = waypoints && waypoints[idx];
return point ? (point.original || point) : getMid(shape);
}
function isCompensationAssociation(connection) {
var source = connection.source,
target = connection.target;
return is(target, 'bpmn:Activity') &&
is(source, 'bpmn:BoundaryEvent') &&
target.businessObject.isForCompensation;
}