mirror of
https://github.com/sartography/bpmn-js.git
synced 2025-01-27 09:15:01 +00:00
13e3752f94
Until now we did not properly sanitize the IDs we create for colored markers. This would make the marker retrival fail with fill and stroke colors encoded in hex and rgb(a, b, c) form. This commit improves the situation by removing forbidden chars from the marker ID. Closes #981 Related to camunda/camunda-modeler#1342
1913 lines
51 KiB
JavaScript
1913 lines
51 KiB
JavaScript
import inherits from 'inherits';
|
|
|
|
import {
|
|
isObject,
|
|
assign,
|
|
forEach
|
|
} from 'min-dash';
|
|
|
|
import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
|
|
|
|
import {
|
|
isExpanded,
|
|
isEventSubProcess
|
|
} from '../util/DiUtil';
|
|
|
|
import { is } from '../util/ModelUtil';
|
|
|
|
import {
|
|
createLine
|
|
} from 'diagram-js/lib/util/RenderUtil';
|
|
|
|
import {
|
|
isTypedEvent,
|
|
isThrowEvent,
|
|
isCollection,
|
|
getDi,
|
|
getSemantic,
|
|
getCirclePath,
|
|
getRoundRectPath,
|
|
getDiamondPath,
|
|
getRectPath,
|
|
getFillColor,
|
|
getStrokeColor
|
|
} from './BpmnRenderUtil';
|
|
|
|
import {
|
|
query as domQuery
|
|
} from 'min-dom';
|
|
|
|
import {
|
|
append as svgAppend,
|
|
attr as svgAttr,
|
|
create as svgCreate,
|
|
classes as svgClasses
|
|
} from 'tiny-svg';
|
|
|
|
import {
|
|
rotate,
|
|
transform,
|
|
translate
|
|
} from 'diagram-js/lib/util/SvgTransformUtil';
|
|
|
|
import Ids from 'ids';
|
|
|
|
var RENDERER_IDS = new Ids();
|
|
|
|
var TASK_BORDER_RADIUS = 10;
|
|
var INNER_OUTER_DIST = 3;
|
|
|
|
var DEFAULT_FILL_OPACITY = .95,
|
|
HIGH_FILL_OPACITY = .35;
|
|
|
|
|
|
export default function BpmnRenderer(
|
|
config, eventBus, styles, pathMap,
|
|
canvas, textRenderer, priority) {
|
|
|
|
BaseRenderer.call(this, eventBus, priority);
|
|
|
|
var defaultFillColor = config && config.defaultFillColor,
|
|
defaultStrokeColor = config && config.defaultStrokeColor;
|
|
|
|
var rendererId = RENDERER_IDS.next();
|
|
|
|
var markers = {};
|
|
|
|
var computeStyle = styles.computeStyle;
|
|
|
|
function addMarker(id, options) {
|
|
var attrs = assign({
|
|
fill: 'black',
|
|
strokeWidth: 1,
|
|
strokeLinecap: 'round',
|
|
strokeDasharray: 'none'
|
|
}, options.attrs);
|
|
|
|
var ref = options.ref || { x: 0, y: 0 };
|
|
|
|
var scale = options.scale || 1;
|
|
|
|
// fix for safari / chrome / firefox bug not correctly
|
|
// resetting stroke dash array
|
|
if (attrs.strokeDasharray === 'none') {
|
|
attrs.strokeDasharray = [10000, 1];
|
|
}
|
|
|
|
var marker = svgCreate('marker');
|
|
|
|
svgAttr(options.element, attrs);
|
|
|
|
svgAppend(marker, options.element);
|
|
|
|
svgAttr(marker, {
|
|
id: id,
|
|
viewBox: '0 0 20 20',
|
|
refX: ref.x,
|
|
refY: ref.y,
|
|
markerWidth: 20 * scale,
|
|
markerHeight: 20 * scale,
|
|
orient: 'auto'
|
|
});
|
|
|
|
var defs = domQuery('defs', canvas._svg);
|
|
|
|
if (!defs) {
|
|
defs = svgCreate('defs');
|
|
|
|
svgAppend(canvas._svg, defs);
|
|
}
|
|
|
|
svgAppend(defs, marker);
|
|
|
|
markers[id] = marker;
|
|
}
|
|
|
|
function colorEscape(str) {
|
|
return str.replace(/[()\s,#]+/g, '_');
|
|
}
|
|
|
|
function marker(type, fill, stroke) {
|
|
var id = type + '-' + colorEscape(fill) + '-' + colorEscape(stroke) + '-' + rendererId;
|
|
|
|
if (!markers[id]) {
|
|
createMarker(id, type, fill, stroke);
|
|
}
|
|
|
|
return 'url(#' + id + ')';
|
|
}
|
|
|
|
function createMarker(id, type, fill, stroke) {
|
|
|
|
if (type === 'sequenceflow-end') {
|
|
var sequenceflowEnd = svgCreate('path');
|
|
svgAttr(sequenceflowEnd, { d: 'M 1 5 L 11 10 L 1 15 Z' });
|
|
|
|
addMarker(id, {
|
|
element: sequenceflowEnd,
|
|
ref: { x: 11, y: 10 },
|
|
scale: 0.5,
|
|
attrs: {
|
|
fill: stroke,
|
|
stroke: stroke
|
|
}
|
|
});
|
|
}
|
|
|
|
if (type === 'messageflow-start') {
|
|
var messageflowStart = svgCreate('circle');
|
|
svgAttr(messageflowStart, { cx: 6, cy: 6, r: 3.5 });
|
|
|
|
addMarker(id, {
|
|
element: messageflowStart,
|
|
attrs: {
|
|
fill: fill,
|
|
stroke: stroke
|
|
},
|
|
ref: { x: 6, y: 6 }
|
|
});
|
|
}
|
|
|
|
if (type === 'messageflow-end') {
|
|
var messageflowEnd = svgCreate('path');
|
|
svgAttr(messageflowEnd, { d: 'm 1 5 l 0 -3 l 7 3 l -7 3 z' });
|
|
|
|
addMarker(id, {
|
|
element: messageflowEnd,
|
|
attrs: {
|
|
fill: fill,
|
|
stroke: stroke,
|
|
strokeLinecap: 'butt'
|
|
},
|
|
ref: { x: 8.5, y: 5 }
|
|
});
|
|
}
|
|
|
|
if (type === 'association-start') {
|
|
var associationStart = svgCreate('path');
|
|
svgAttr(associationStart, { d: 'M 11 5 L 1 10 L 11 15' });
|
|
|
|
addMarker(id, {
|
|
element: associationStart,
|
|
attrs: {
|
|
fill: 'none',
|
|
stroke: stroke,
|
|
strokeWidth: 1.5
|
|
},
|
|
ref: { x: 1, y: 10 },
|
|
scale: 0.5
|
|
});
|
|
}
|
|
|
|
if (type === 'association-end') {
|
|
var associationEnd = svgCreate('path');
|
|
svgAttr(associationEnd, { d: 'M 1 5 L 11 10 L 1 15' });
|
|
|
|
addMarker(id, {
|
|
element: associationEnd,
|
|
attrs: {
|
|
fill: 'none',
|
|
stroke: stroke,
|
|
strokeWidth: 1.5
|
|
},
|
|
ref: { x: 12, y: 10 },
|
|
scale: 0.5
|
|
});
|
|
}
|
|
|
|
if (type === 'conditional-flow-marker') {
|
|
var conditionalflowMarker = svgCreate('path');
|
|
svgAttr(conditionalflowMarker, { d: 'M 0 10 L 8 6 L 16 10 L 8 14 Z' });
|
|
|
|
addMarker(id, {
|
|
element: conditionalflowMarker,
|
|
attrs: {
|
|
fill: fill,
|
|
stroke: stroke
|
|
},
|
|
ref: { x: -1, y: 10 },
|
|
scale: 0.5
|
|
});
|
|
}
|
|
|
|
if (type === 'conditional-default-flow-marker') {
|
|
var conditionaldefaultflowMarker = svgCreate('path');
|
|
svgAttr(conditionaldefaultflowMarker, { d: 'M 6 4 L 10 16' });
|
|
|
|
addMarker(id, {
|
|
element: conditionaldefaultflowMarker,
|
|
attrs: {
|
|
stroke: stroke
|
|
},
|
|
ref: { x: 0, y: 10 },
|
|
scale: 0.5
|
|
});
|
|
}
|
|
}
|
|
|
|
function drawCircle(parentGfx, width, height, offset, attrs) {
|
|
|
|
if (isObject(offset)) {
|
|
attrs = offset;
|
|
offset = 0;
|
|
}
|
|
|
|
offset = offset || 0;
|
|
|
|
attrs = computeStyle(attrs, {
|
|
stroke: 'black',
|
|
strokeWidth: 2,
|
|
fill: 'white'
|
|
});
|
|
|
|
if (attrs.fill === 'none') {
|
|
delete attrs.fillOpacity;
|
|
}
|
|
|
|
var cx = width / 2,
|
|
cy = height / 2;
|
|
|
|
var circle = svgCreate('circle');
|
|
svgAttr(circle, {
|
|
cx: cx,
|
|
cy: cy,
|
|
r: Math.round((width + height) / 4 - offset)
|
|
});
|
|
svgAttr(circle, attrs);
|
|
|
|
svgAppend(parentGfx, circle);
|
|
|
|
return circle;
|
|
}
|
|
|
|
function drawRect(parentGfx, width, height, r, offset, attrs) {
|
|
|
|
if (isObject(offset)) {
|
|
attrs = offset;
|
|
offset = 0;
|
|
}
|
|
|
|
offset = offset || 0;
|
|
|
|
attrs = computeStyle(attrs, {
|
|
stroke: 'black',
|
|
strokeWidth: 2,
|
|
fill: 'white'
|
|
});
|
|
|
|
var rect = svgCreate('rect');
|
|
svgAttr(rect, {
|
|
x: offset,
|
|
y: offset,
|
|
width: width - offset * 2,
|
|
height: height - offset * 2,
|
|
rx: r,
|
|
ry: r
|
|
});
|
|
svgAttr(rect, attrs);
|
|
|
|
svgAppend(parentGfx, rect);
|
|
|
|
return rect;
|
|
}
|
|
|
|
function drawDiamond(parentGfx, width, height, attrs) {
|
|
|
|
var x_2 = width / 2;
|
|
var y_2 = height / 2;
|
|
|
|
var points = [{ x: x_2, y: 0 }, { x: width, y: y_2 }, { x: x_2, y: height }, { x: 0, y: y_2 }];
|
|
|
|
var pointsString = points.map(function(point) {
|
|
return point.x + ',' + point.y;
|
|
}).join(' ');
|
|
|
|
attrs = computeStyle(attrs, {
|
|
stroke: 'black',
|
|
strokeWidth: 2,
|
|
fill: 'white'
|
|
});
|
|
|
|
var polygon = svgCreate('polygon');
|
|
svgAttr(polygon, {
|
|
points: pointsString
|
|
});
|
|
svgAttr(polygon, attrs);
|
|
|
|
svgAppend(parentGfx, polygon);
|
|
|
|
return polygon;
|
|
}
|
|
|
|
function drawLine(parentGfx, waypoints, attrs) {
|
|
attrs = computeStyle(attrs, [ 'no-fill' ], {
|
|
stroke: 'black',
|
|
strokeWidth: 2,
|
|
fill: 'none'
|
|
});
|
|
|
|
var line = createLine(waypoints, attrs);
|
|
|
|
svgAppend(parentGfx, line);
|
|
|
|
return line;
|
|
}
|
|
|
|
function drawPath(parentGfx, d, attrs) {
|
|
|
|
attrs = computeStyle(attrs, [ 'no-fill' ], {
|
|
strokeWidth: 2,
|
|
stroke: 'black'
|
|
});
|
|
|
|
var path = svgCreate('path');
|
|
svgAttr(path, { d: d });
|
|
svgAttr(path, attrs);
|
|
|
|
svgAppend(parentGfx, path);
|
|
|
|
return path;
|
|
}
|
|
|
|
function drawMarker(type, parentGfx, path, attrs) {
|
|
return drawPath(parentGfx, path, assign({ 'data-marker': type }, attrs));
|
|
}
|
|
|
|
function as(type) {
|
|
return function(parentGfx, element) {
|
|
return handlers[type](parentGfx, element);
|
|
};
|
|
}
|
|
|
|
function renderer(type) {
|
|
return handlers[type];
|
|
}
|
|
|
|
function renderEventContent(element, parentGfx) {
|
|
|
|
var event = getSemantic(element);
|
|
var isThrowing = isThrowEvent(event);
|
|
|
|
if (isTypedEvent(event, 'bpmn:MessageEventDefinition')) {
|
|
return renderer('bpmn:MessageEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:TimerEventDefinition')) {
|
|
return renderer('bpmn:TimerEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:ConditionalEventDefinition')) {
|
|
return renderer('bpmn:ConditionalEventDefinition')(parentGfx, element);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:SignalEventDefinition')) {
|
|
return renderer('bpmn:SignalEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:CancelEventDefinition') &&
|
|
isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: false })) {
|
|
return renderer('bpmn:MultipleEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:CancelEventDefinition') &&
|
|
isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: true })) {
|
|
return renderer('bpmn:ParallelMultipleEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:EscalationEventDefinition')) {
|
|
return renderer('bpmn:EscalationEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:LinkEventDefinition')) {
|
|
return renderer('bpmn:LinkEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:ErrorEventDefinition')) {
|
|
return renderer('bpmn:ErrorEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:CancelEventDefinition')) {
|
|
return renderer('bpmn:CancelEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:CompensateEventDefinition')) {
|
|
return renderer('bpmn:CompensateEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
if (isTypedEvent(event, 'bpmn:TerminateEventDefinition')) {
|
|
return renderer('bpmn:TerminateEventDefinition')(parentGfx, element, isThrowing);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function renderLabel(parentGfx, label, options) {
|
|
|
|
options = assign({
|
|
size: {
|
|
width: 100
|
|
}
|
|
}, options);
|
|
|
|
var text = textRenderer.createText(label || '', options);
|
|
|
|
svgClasses(text).add('djs-label');
|
|
|
|
svgAppend(parentGfx, text);
|
|
|
|
return text;
|
|
}
|
|
|
|
function renderEmbeddedLabel(parentGfx, element, align) {
|
|
var semantic = getSemantic(element);
|
|
|
|
return renderLabel(parentGfx, semantic.name, {
|
|
box: element,
|
|
align: align,
|
|
padding: 5,
|
|
style: {
|
|
fill: getStrokeColor(element, defaultStrokeColor)
|
|
}
|
|
});
|
|
}
|
|
|
|
function renderExternalLabel(parentGfx, element) {
|
|
var semantic = getSemantic(element);
|
|
var box = {
|
|
width: 90,
|
|
height: 30,
|
|
x: element.width / 2 + element.x,
|
|
y: element.height / 2 + element.y
|
|
};
|
|
|
|
return renderLabel(parentGfx, semantic.name, {
|
|
box: box,
|
|
fitBox: true,
|
|
style: assign(
|
|
{},
|
|
textRenderer.getExternalStyle(),
|
|
{
|
|
fill: getStrokeColor(element, defaultStrokeColor)
|
|
}
|
|
)
|
|
});
|
|
}
|
|
|
|
function renderLaneLabel(parentGfx, text, element) {
|
|
var textBox = renderLabel(parentGfx, text, {
|
|
box: {
|
|
height: 30,
|
|
width: element.height
|
|
},
|
|
align: 'center-middle',
|
|
style: {
|
|
fill: getStrokeColor(element, defaultStrokeColor)
|
|
}
|
|
});
|
|
|
|
var top = -1 * element.height;
|
|
|
|
transform(textBox, 0, -top, 270);
|
|
}
|
|
|
|
function createPathFromConnection(connection) {
|
|
var waypoints = connection.waypoints;
|
|
|
|
var pathData = 'm ' + waypoints[0].x + ',' + waypoints[0].y;
|
|
for (var i = 1; i < waypoints.length; i++) {
|
|
pathData += 'L' + waypoints[i].x + ',' + waypoints[i].y + ' ';
|
|
}
|
|
return pathData;
|
|
}
|
|
|
|
var handlers = this.handlers = {
|
|
'bpmn:Event': function(parentGfx, element, attrs) {
|
|
|
|
if (!('fillOpacity' in attrs)) {
|
|
attrs.fillOpacity = DEFAULT_FILL_OPACITY;
|
|
}
|
|
|
|
return drawCircle(parentGfx, element.width, element.height, attrs);
|
|
},
|
|
'bpmn:StartEvent': function(parentGfx, element) {
|
|
var attrs = {
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
};
|
|
|
|
var semantic = getSemantic(element);
|
|
|
|
if (!semantic.isInterrupting) {
|
|
attrs = {
|
|
strokeDasharray: '6',
|
|
strokeLinecap: 'round',
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
};
|
|
}
|
|
|
|
var circle = renderer('bpmn:Event')(parentGfx, element, attrs);
|
|
|
|
renderEventContent(element, parentGfx);
|
|
|
|
return circle;
|
|
},
|
|
'bpmn:MessageEventDefinition': function(parentGfx, element, isThrowing) {
|
|
var pathData = pathMap.getScaledPath('EVENT_MESSAGE', {
|
|
xScaleFactor: 0.9,
|
|
yScaleFactor: 0.9,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.235,
|
|
my: 0.315
|
|
}
|
|
});
|
|
|
|
var fill = isThrowing ? getStrokeColor(element, defaultStrokeColor) : getFillColor(element, defaultFillColor);
|
|
var stroke = isThrowing ? getFillColor(element, defaultFillColor) : getStrokeColor(element, defaultStrokeColor);
|
|
|
|
var messagePath = drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: fill,
|
|
stroke: stroke
|
|
});
|
|
|
|
return messagePath;
|
|
},
|
|
'bpmn:TimerEventDefinition': function(parentGfx, element) {
|
|
var circle = drawCircle(parentGfx, element.width, element.height, 0.2 * element.height, {
|
|
strokeWidth: 2,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
var pathData = pathMap.getScaledPath('EVENT_TIMER_WH', {
|
|
xScaleFactor: 0.75,
|
|
yScaleFactor: 0.75,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.5,
|
|
my: 0.5
|
|
}
|
|
});
|
|
|
|
drawPath(parentGfx, pathData, {
|
|
strokeWidth: 2,
|
|
strokeLinecap: 'square',
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
for (var i = 0;i < 12; i++) {
|
|
|
|
var linePathData = pathMap.getScaledPath('EVENT_TIMER_LINE', {
|
|
xScaleFactor: 0.75,
|
|
yScaleFactor: 0.75,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.5,
|
|
my: 0.5
|
|
}
|
|
});
|
|
|
|
var width = element.width / 2;
|
|
var height = element.height / 2;
|
|
|
|
drawPath(parentGfx, linePathData, {
|
|
strokeWidth: 1,
|
|
strokeLinecap: 'square',
|
|
transform: 'rotate(' + (i * 30) + ',' + height + ',' + width + ')',
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
}
|
|
|
|
return circle;
|
|
},
|
|
'bpmn:EscalationEventDefinition': function(parentGfx, event, isThrowing) {
|
|
var pathData = pathMap.getScaledPath('EVENT_ESCALATION', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: event.width,
|
|
containerHeight: event.height,
|
|
position: {
|
|
mx: 0.5,
|
|
my: 0.2
|
|
}
|
|
});
|
|
|
|
var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
|
|
|
|
return drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: fill,
|
|
stroke: getStrokeColor(event, defaultStrokeColor)
|
|
});
|
|
},
|
|
'bpmn:ConditionalEventDefinition': function(parentGfx, event) {
|
|
var pathData = pathMap.getScaledPath('EVENT_CONDITIONAL', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: event.width,
|
|
containerHeight: event.height,
|
|
position: {
|
|
mx: 0.5,
|
|
my: 0.222
|
|
}
|
|
});
|
|
|
|
return drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
stroke: getStrokeColor(event, defaultStrokeColor)
|
|
});
|
|
},
|
|
'bpmn:LinkEventDefinition': function(parentGfx, event, isThrowing) {
|
|
var pathData = pathMap.getScaledPath('EVENT_LINK', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: event.width,
|
|
containerHeight: event.height,
|
|
position: {
|
|
mx: 0.57,
|
|
my: 0.263
|
|
}
|
|
});
|
|
|
|
var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
|
|
|
|
return drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: fill,
|
|
stroke: getStrokeColor(event, defaultStrokeColor)
|
|
});
|
|
},
|
|
'bpmn:ErrorEventDefinition': function(parentGfx, event, isThrowing) {
|
|
var pathData = pathMap.getScaledPath('EVENT_ERROR', {
|
|
xScaleFactor: 1.1,
|
|
yScaleFactor: 1.1,
|
|
containerWidth: event.width,
|
|
containerHeight: event.height,
|
|
position: {
|
|
mx: 0.2,
|
|
my: 0.722
|
|
}
|
|
});
|
|
|
|
var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
|
|
|
|
return drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: fill,
|
|
stroke: getStrokeColor(event, defaultStrokeColor)
|
|
});
|
|
},
|
|
'bpmn:CancelEventDefinition': function(parentGfx, event, isThrowing) {
|
|
var pathData = pathMap.getScaledPath('EVENT_CANCEL_45', {
|
|
xScaleFactor: 1.0,
|
|
yScaleFactor: 1.0,
|
|
containerWidth: event.width,
|
|
containerHeight: event.height,
|
|
position: {
|
|
mx: 0.638,
|
|
my: -0.055
|
|
}
|
|
});
|
|
|
|
var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
|
|
|
|
var path = drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: fill,
|
|
stroke: getStrokeColor(event, defaultStrokeColor)
|
|
});
|
|
|
|
rotate(path, 45);
|
|
|
|
return path;
|
|
},
|
|
'bpmn:CompensateEventDefinition': function(parentGfx, event, isThrowing) {
|
|
var pathData = pathMap.getScaledPath('EVENT_COMPENSATION', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: event.width,
|
|
containerHeight: event.height,
|
|
position: {
|
|
mx: 0.22,
|
|
my: 0.5
|
|
}
|
|
});
|
|
|
|
var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
|
|
|
|
return drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: fill,
|
|
stroke: getStrokeColor(event, defaultStrokeColor)
|
|
});
|
|
},
|
|
'bpmn:SignalEventDefinition': function(parentGfx, event, isThrowing) {
|
|
var pathData = pathMap.getScaledPath('EVENT_SIGNAL', {
|
|
xScaleFactor: 0.9,
|
|
yScaleFactor: 0.9,
|
|
containerWidth: event.width,
|
|
containerHeight: event.height,
|
|
position: {
|
|
mx: 0.5,
|
|
my: 0.2
|
|
}
|
|
});
|
|
|
|
var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
|
|
|
|
return drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: fill,
|
|
stroke: getStrokeColor(event, defaultStrokeColor)
|
|
});
|
|
},
|
|
'bpmn:MultipleEventDefinition': function(parentGfx, event, isThrowing) {
|
|
var pathData = pathMap.getScaledPath('EVENT_MULTIPLE', {
|
|
xScaleFactor: 1.1,
|
|
yScaleFactor: 1.1,
|
|
containerWidth: event.width,
|
|
containerHeight: event.height,
|
|
position: {
|
|
mx: 0.222,
|
|
my: 0.36
|
|
}
|
|
});
|
|
|
|
var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
|
|
|
|
return drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: fill
|
|
});
|
|
},
|
|
'bpmn:ParallelMultipleEventDefinition': function(parentGfx, event) {
|
|
var pathData = pathMap.getScaledPath('EVENT_PARALLEL_MULTIPLE', {
|
|
xScaleFactor: 1.2,
|
|
yScaleFactor: 1.2,
|
|
containerWidth: event.width,
|
|
containerHeight: event.height,
|
|
position: {
|
|
mx: 0.458,
|
|
my: 0.194
|
|
}
|
|
});
|
|
|
|
return drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: getStrokeColor(event, defaultStrokeColor),
|
|
stroke: getStrokeColor(event, defaultStrokeColor)
|
|
});
|
|
},
|
|
'bpmn:EndEvent': function(parentGfx, element) {
|
|
var circle = renderer('bpmn:Event')(parentGfx, element, {
|
|
strokeWidth: 4,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
renderEventContent(element, parentGfx, true);
|
|
|
|
return circle;
|
|
},
|
|
'bpmn:TerminateEventDefinition': function(parentGfx, element) {
|
|
var circle = drawCircle(parentGfx, element.width, element.height, 8, {
|
|
strokeWidth: 4,
|
|
fill: getStrokeColor(element, defaultStrokeColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return circle;
|
|
},
|
|
'bpmn:IntermediateEvent': function(parentGfx, element) {
|
|
var outer = renderer('bpmn:Event')(parentGfx, element, {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
/* inner */
|
|
drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, 'none'),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
renderEventContent(element, parentGfx);
|
|
|
|
return outer;
|
|
},
|
|
'bpmn:IntermediateCatchEvent': as('bpmn:IntermediateEvent'),
|
|
'bpmn:IntermediateThrowEvent': as('bpmn:IntermediateEvent'),
|
|
|
|
'bpmn:Activity': function(parentGfx, element, attrs) {
|
|
|
|
attrs = attrs || {};
|
|
|
|
if (!('fillOpacity' in attrs)) {
|
|
attrs.fillOpacity = DEFAULT_FILL_OPACITY;
|
|
}
|
|
|
|
return drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, attrs);
|
|
},
|
|
|
|
'bpmn:Task': function(parentGfx, element) {
|
|
var attrs = {
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
};
|
|
|
|
var rect = renderer('bpmn:Activity')(parentGfx, element, attrs);
|
|
|
|
renderEmbeddedLabel(parentGfx, element, 'center-middle');
|
|
attachTaskMarkers(parentGfx, element);
|
|
|
|
return rect;
|
|
},
|
|
'bpmn:ServiceTask': function(parentGfx, element) {
|
|
var task = renderer('bpmn:Task')(parentGfx, element);
|
|
|
|
var pathDataBG = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
|
|
abspos: {
|
|
x: 12,
|
|
y: 18
|
|
}
|
|
});
|
|
|
|
/* service bg */ drawPath(parentGfx, pathDataBG, {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
var fillPathData = pathMap.getScaledPath('TASK_TYPE_SERVICE_FILL', {
|
|
abspos: {
|
|
x: 17.2,
|
|
y: 18
|
|
}
|
|
});
|
|
|
|
/* service fill */ drawPath(parentGfx, fillPathData, {
|
|
strokeWidth: 0,
|
|
fill: getFillColor(element, defaultFillColor)
|
|
});
|
|
|
|
var pathData = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
|
|
abspos: {
|
|
x: 17,
|
|
y: 22
|
|
}
|
|
});
|
|
|
|
/* service */ drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return task;
|
|
},
|
|
'bpmn:UserTask': function(parentGfx, element) {
|
|
var task = renderer('bpmn:Task')(parentGfx, element);
|
|
|
|
var x = 15;
|
|
var y = 12;
|
|
|
|
var pathData = pathMap.getScaledPath('TASK_TYPE_USER_1', {
|
|
abspos: {
|
|
x: x,
|
|
y: y
|
|
}
|
|
});
|
|
|
|
/* user path */ drawPath(parentGfx, pathData, {
|
|
strokeWidth: 0.5,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
var pathData2 = pathMap.getScaledPath('TASK_TYPE_USER_2', {
|
|
abspos: {
|
|
x: x,
|
|
y: y
|
|
}
|
|
});
|
|
|
|
/* user2 path */ drawPath(parentGfx, pathData2, {
|
|
strokeWidth: 0.5,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
var pathData3 = pathMap.getScaledPath('TASK_TYPE_USER_3', {
|
|
abspos: {
|
|
x: x,
|
|
y: y
|
|
}
|
|
});
|
|
|
|
/* user3 path */ drawPath(parentGfx, pathData3, {
|
|
strokeWidth: 0.5,
|
|
fill: getStrokeColor(element, defaultStrokeColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return task;
|
|
},
|
|
'bpmn:ManualTask': function(parentGfx, element) {
|
|
var task = renderer('bpmn:Task')(parentGfx, element);
|
|
|
|
var pathData = pathMap.getScaledPath('TASK_TYPE_MANUAL', {
|
|
abspos: {
|
|
x: 17,
|
|
y: 15
|
|
}
|
|
});
|
|
|
|
/* manual path */ drawPath(parentGfx, pathData, {
|
|
strokeWidth: 0.5, // 0.25,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return task;
|
|
},
|
|
'bpmn:SendTask': function(parentGfx, element) {
|
|
var task = renderer('bpmn:Task')(parentGfx, element);
|
|
|
|
var pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: 21,
|
|
containerHeight: 14,
|
|
position: {
|
|
mx: 0.285,
|
|
my: 0.357
|
|
}
|
|
});
|
|
|
|
/* send path */ drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: getStrokeColor(element, defaultStrokeColor),
|
|
stroke: getFillColor(element, defaultFillColor)
|
|
});
|
|
|
|
return task;
|
|
},
|
|
'bpmn:ReceiveTask' : function(parentGfx, element) {
|
|
var semantic = getSemantic(element);
|
|
|
|
var task = renderer('bpmn:Task')(parentGfx, element);
|
|
var pathData;
|
|
|
|
if (semantic.instantiate) {
|
|
drawCircle(parentGfx, 28, 28, 20 * 0.22, { strokeWidth: 1 });
|
|
|
|
pathData = pathMap.getScaledPath('TASK_TYPE_INSTANTIATING_SEND', {
|
|
abspos: {
|
|
x: 7.77,
|
|
y: 9.52
|
|
}
|
|
});
|
|
} else {
|
|
|
|
pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
|
|
xScaleFactor: 0.9,
|
|
yScaleFactor: 0.9,
|
|
containerWidth: 21,
|
|
containerHeight: 14,
|
|
position: {
|
|
mx: 0.3,
|
|
my: 0.4
|
|
}
|
|
});
|
|
}
|
|
|
|
/* receive path */ drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return task;
|
|
},
|
|
'bpmn:ScriptTask': function(parentGfx, element) {
|
|
var task = renderer('bpmn:Task')(parentGfx, element);
|
|
|
|
var pathData = pathMap.getScaledPath('TASK_TYPE_SCRIPT', {
|
|
abspos: {
|
|
x: 15,
|
|
y: 20
|
|
}
|
|
});
|
|
|
|
/* script path */ drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return task;
|
|
},
|
|
'bpmn:BusinessRuleTask': function(parentGfx, element) {
|
|
var task = renderer('bpmn:Task')(parentGfx, element);
|
|
|
|
var headerPathData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_HEADER', {
|
|
abspos: {
|
|
x: 8,
|
|
y: 8
|
|
}
|
|
});
|
|
|
|
var businessHeaderPath = drawPath(parentGfx, headerPathData);
|
|
svgAttr(businessHeaderPath, {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, '#aaaaaa'),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
var headerData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_MAIN', {
|
|
abspos: {
|
|
x: 8,
|
|
y: 8
|
|
}
|
|
});
|
|
|
|
var businessPath = drawPath(parentGfx, headerData);
|
|
svgAttr(businessPath, {
|
|
strokeWidth: 1,
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return task;
|
|
},
|
|
'bpmn:SubProcess': function(parentGfx, element, attrs) {
|
|
attrs = assign({
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
}, attrs);
|
|
|
|
var rect = renderer('bpmn:Activity')(parentGfx, element, attrs);
|
|
|
|
var expanded = isExpanded(element);
|
|
|
|
if (isEventSubProcess(element)) {
|
|
svgAttr(rect, {
|
|
strokeDasharray: '1,2'
|
|
});
|
|
}
|
|
|
|
renderEmbeddedLabel(parentGfx, element, expanded ? 'center-top' : 'center-middle');
|
|
|
|
if (expanded) {
|
|
attachTaskMarkers(parentGfx, element);
|
|
} else {
|
|
attachTaskMarkers(parentGfx, element, ['SubProcessMarker']);
|
|
}
|
|
|
|
return rect;
|
|
},
|
|
'bpmn:AdHocSubProcess': function(parentGfx, element) {
|
|
return renderer('bpmn:SubProcess')(parentGfx, element);
|
|
},
|
|
'bpmn:Transaction': function(parentGfx, element) {
|
|
var outer = renderer('bpmn:SubProcess')(parentGfx, element);
|
|
|
|
var innerAttrs = styles.style([ 'no-fill', 'no-events' ], {
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
/* inner path */ drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS - 2, INNER_OUTER_DIST, innerAttrs);
|
|
|
|
return outer;
|
|
},
|
|
'bpmn:CallActivity': function(parentGfx, element) {
|
|
return renderer('bpmn:SubProcess')(parentGfx, element, {
|
|
strokeWidth: 5
|
|
});
|
|
},
|
|
'bpmn:Participant': function(parentGfx, element) {
|
|
|
|
var attrs = {
|
|
fillOpacity: DEFAULT_FILL_OPACITY,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
};
|
|
|
|
var lane = renderer('bpmn:Lane')(parentGfx, element, attrs);
|
|
|
|
var expandedPool = isExpanded(element);
|
|
|
|
if (expandedPool) {
|
|
drawLine(parentGfx, [
|
|
{ x: 30, y: 0 },
|
|
{ x: 30, y: element.height }
|
|
], {
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
var text = getSemantic(element).name;
|
|
renderLaneLabel(parentGfx, text, element);
|
|
} else {
|
|
// Collapsed pool draw text inline
|
|
var text2 = getSemantic(element).name;
|
|
renderLabel(parentGfx, text2, {
|
|
box: element, align: 'center-middle',
|
|
style: {
|
|
fill: getStrokeColor(element, defaultStrokeColor)
|
|
}
|
|
});
|
|
}
|
|
|
|
var participantMultiplicity = !!(getSemantic(element).participantMultiplicity);
|
|
|
|
if (participantMultiplicity) {
|
|
renderer('ParticipantMultiplicityMarker')(parentGfx, element);
|
|
}
|
|
|
|
return lane;
|
|
},
|
|
'bpmn:Lane': function(parentGfx, element, attrs) {
|
|
var rect = drawRect(parentGfx, element.width, element.height, 0, assign({
|
|
fill: getFillColor(element, defaultFillColor),
|
|
fillOpacity: HIGH_FILL_OPACITY,
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
}, attrs));
|
|
|
|
var semantic = getSemantic(element);
|
|
|
|
if (semantic.$type === 'bpmn:Lane') {
|
|
var text = semantic.name;
|
|
renderLaneLabel(parentGfx, text, element);
|
|
}
|
|
|
|
return rect;
|
|
},
|
|
'bpmn:InclusiveGateway': function(parentGfx, element) {
|
|
var diamond = renderer('bpmn:Gateway')(parentGfx, element);
|
|
|
|
/* circle path */
|
|
drawCircle(parentGfx, element.width, element.height, element.height * 0.24, {
|
|
strokeWidth: 2.5,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return diamond;
|
|
},
|
|
'bpmn:ExclusiveGateway': function(parentGfx, element) {
|
|
var diamond = renderer('bpmn:Gateway')(parentGfx, element);
|
|
|
|
var pathData = pathMap.getScaledPath('GATEWAY_EXCLUSIVE', {
|
|
xScaleFactor: 0.4,
|
|
yScaleFactor: 0.4,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.32,
|
|
my: 0.3
|
|
}
|
|
});
|
|
|
|
if ((getDi(element).isMarkerVisible)) {
|
|
drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: getStrokeColor(element, defaultStrokeColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
}
|
|
|
|
return diamond;
|
|
},
|
|
'bpmn:ComplexGateway': function(parentGfx, element) {
|
|
var diamond = renderer('bpmn:Gateway')(parentGfx, element);
|
|
|
|
var pathData = pathMap.getScaledPath('GATEWAY_COMPLEX', {
|
|
xScaleFactor: 0.5,
|
|
yScaleFactor:0.5,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.46,
|
|
my: 0.26
|
|
}
|
|
});
|
|
|
|
/* complex path */ drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: getStrokeColor(element, defaultStrokeColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return diamond;
|
|
},
|
|
'bpmn:ParallelGateway': function(parentGfx, element) {
|
|
var diamond = renderer('bpmn:Gateway')(parentGfx, element);
|
|
|
|
var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
|
|
xScaleFactor: 0.6,
|
|
yScaleFactor:0.6,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.46,
|
|
my: 0.2
|
|
}
|
|
});
|
|
|
|
/* parallel path */ drawPath(parentGfx, pathData, {
|
|
strokeWidth: 1,
|
|
fill: getStrokeColor(element, defaultStrokeColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return diamond;
|
|
},
|
|
'bpmn:EventBasedGateway': function(parentGfx, element) {
|
|
|
|
var semantic = getSemantic(element);
|
|
|
|
var diamond = renderer('bpmn:Gateway')(parentGfx, element);
|
|
|
|
/* outer circle path */ drawCircle(parentGfx, element.width, element.height, element.height * 0.20, {
|
|
strokeWidth: 1,
|
|
fill: 'none',
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
var type = semantic.eventGatewayType;
|
|
var instantiate = !!semantic.instantiate;
|
|
|
|
function drawEvent() {
|
|
|
|
var pathData = pathMap.getScaledPath('GATEWAY_EVENT_BASED', {
|
|
xScaleFactor: 0.18,
|
|
yScaleFactor: 0.18,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.36,
|
|
my: 0.44
|
|
}
|
|
});
|
|
|
|
var attrs = {
|
|
strokeWidth: 2,
|
|
fill: getFillColor(element, 'none'),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
};
|
|
|
|
/* event path */ drawPath(parentGfx, pathData, attrs);
|
|
}
|
|
|
|
if (type === 'Parallel') {
|
|
|
|
var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
|
|
xScaleFactor: 0.4,
|
|
yScaleFactor:0.4,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.474,
|
|
my: 0.296
|
|
}
|
|
});
|
|
|
|
var parallelPath = drawPath(parentGfx, pathData);
|
|
svgAttr(parallelPath, {
|
|
strokeWidth: 1,
|
|
fill: 'none'
|
|
});
|
|
} else if (type === 'Exclusive') {
|
|
|
|
if (!instantiate) {
|
|
var innerCircle = drawCircle(parentGfx, element.width, element.height, element.height * 0.26);
|
|
svgAttr(innerCircle, {
|
|
strokeWidth: 1,
|
|
fill: 'none',
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
}
|
|
|
|
drawEvent();
|
|
}
|
|
|
|
|
|
return diamond;
|
|
},
|
|
'bpmn:Gateway': function(parentGfx, element) {
|
|
var attrs = {
|
|
fill: getFillColor(element, defaultFillColor),
|
|
fillOpacity: DEFAULT_FILL_OPACITY,
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
};
|
|
|
|
return drawDiamond(parentGfx, element.width, element.height, attrs);
|
|
},
|
|
'bpmn:SequenceFlow': function(parentGfx, element) {
|
|
var pathData = createPathFromConnection(element);
|
|
|
|
var fill = getFillColor(element, defaultFillColor),
|
|
stroke = getStrokeColor(element, defaultStrokeColor);
|
|
|
|
var attrs = {
|
|
strokeLinejoin: 'round',
|
|
markerEnd: marker('sequenceflow-end', fill, stroke),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
};
|
|
|
|
var path = drawPath(parentGfx, pathData, attrs);
|
|
|
|
var sequenceFlow = getSemantic(element);
|
|
|
|
var source;
|
|
|
|
if (element.source) {
|
|
source = element.source.businessObject;
|
|
|
|
// conditional flow marker
|
|
if (sequenceFlow.conditionExpression && source.$instanceOf('bpmn:Activity')) {
|
|
svgAttr(path, {
|
|
markerStart: marker('conditional-flow-marker', fill, stroke)
|
|
});
|
|
}
|
|
|
|
// default marker
|
|
if (source.default && (source.$instanceOf('bpmn:Gateway') || source.$instanceOf('bpmn:Activity')) &&
|
|
source.default === sequenceFlow) {
|
|
svgAttr(path, {
|
|
markerStart: marker('conditional-default-flow-marker', fill, stroke)
|
|
});
|
|
}
|
|
}
|
|
|
|
return path;
|
|
},
|
|
'bpmn:Association': function(parentGfx, element, attrs) {
|
|
|
|
var semantic = getSemantic(element);
|
|
|
|
var fill = getFillColor(element, defaultFillColor),
|
|
stroke = getStrokeColor(element, defaultStrokeColor);
|
|
|
|
attrs = assign({
|
|
strokeDasharray: '0.5, 5',
|
|
strokeLinecap: 'round',
|
|
strokeLinejoin: 'round',
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
}, attrs || {});
|
|
|
|
if (semantic.associationDirection === 'One' ||
|
|
semantic.associationDirection === 'Both') {
|
|
attrs.markerEnd = marker('association-end', fill, stroke);
|
|
}
|
|
|
|
if (semantic.associationDirection === 'Both') {
|
|
attrs.markerStart = marker('association-start', fill, stroke);
|
|
}
|
|
|
|
return drawLine(parentGfx, element.waypoints, attrs);
|
|
},
|
|
'bpmn:DataInputAssociation': function(parentGfx, element) {
|
|
var fill = getFillColor(element, defaultFillColor),
|
|
stroke = getStrokeColor(element, defaultStrokeColor);
|
|
|
|
return renderer('bpmn:Association')(parentGfx, element, {
|
|
markerEnd: marker('association-end', fill, stroke)
|
|
});
|
|
},
|
|
'bpmn:DataOutputAssociation': function(parentGfx, element) {
|
|
var fill = getFillColor(element, defaultFillColor),
|
|
stroke = getStrokeColor(element, defaultStrokeColor);
|
|
|
|
return renderer('bpmn:Association')(parentGfx, element, {
|
|
markerEnd: marker('association-end', fill, stroke)
|
|
});
|
|
},
|
|
'bpmn:MessageFlow': function(parentGfx, element) {
|
|
|
|
var semantic = getSemantic(element),
|
|
di = getDi(element);
|
|
|
|
var fill = getFillColor(element, defaultFillColor),
|
|
stroke = getStrokeColor(element, defaultStrokeColor);
|
|
|
|
var pathData = createPathFromConnection(element);
|
|
|
|
var attrs = {
|
|
markerEnd: marker('messageflow-end', fill, stroke),
|
|
markerStart: marker('messageflow-start', fill, stroke),
|
|
strokeDasharray: '10, 12',
|
|
strokeLinecap: 'round',
|
|
strokeLinejoin: 'round',
|
|
strokeWidth: '1.5px',
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
};
|
|
|
|
var path = drawPath(parentGfx, pathData, attrs);
|
|
|
|
if (semantic.messageRef) {
|
|
var midPoint = path.getPointAtLength(path.getTotalLength() / 2);
|
|
|
|
var markerPathData = pathMap.getScaledPath('MESSAGE_FLOW_MARKER', {
|
|
abspos: {
|
|
x: midPoint.x,
|
|
y: midPoint.y
|
|
}
|
|
});
|
|
|
|
var messageAttrs = { strokeWidth: 1 };
|
|
|
|
if (di.messageVisibleKind === 'initiating') {
|
|
messageAttrs.fill = 'white';
|
|
messageAttrs.stroke = 'black';
|
|
} else {
|
|
messageAttrs.fill = '#888';
|
|
messageAttrs.stroke = 'white';
|
|
}
|
|
|
|
drawPath(parentGfx, markerPathData, messageAttrs);
|
|
}
|
|
|
|
return path;
|
|
},
|
|
'bpmn:DataObject': function(parentGfx, element) {
|
|
var pathData = pathMap.getScaledPath('DATA_OBJECT_PATH', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.474,
|
|
my: 0.296
|
|
}
|
|
});
|
|
|
|
var elementObject = drawPath(parentGfx, pathData, {
|
|
fill: getFillColor(element, defaultFillColor),
|
|
fillOpacity: DEFAULT_FILL_OPACITY,
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
var semantic = getSemantic(element);
|
|
|
|
if (isCollection(semantic)) {
|
|
renderDataItemCollection(parentGfx, element);
|
|
}
|
|
|
|
return elementObject;
|
|
},
|
|
'bpmn:DataObjectReference': as('bpmn:DataObject'),
|
|
'bpmn:DataInput': function(parentGfx, element) {
|
|
|
|
var arrowPathData = pathMap.getRawPath('DATA_ARROW');
|
|
|
|
// page
|
|
var elementObject = renderer('bpmn:DataObject')(parentGfx, element);
|
|
|
|
/* input arrow path */ drawPath(parentGfx, arrowPathData, { strokeWidth: 1 });
|
|
|
|
return elementObject;
|
|
},
|
|
'bpmn:DataOutput': function(parentGfx, element) {
|
|
var arrowPathData = pathMap.getRawPath('DATA_ARROW');
|
|
|
|
// page
|
|
var elementObject = renderer('bpmn:DataObject')(parentGfx, element);
|
|
|
|
/* output arrow path */ drawPath(parentGfx, arrowPathData, {
|
|
strokeWidth: 1,
|
|
fill: 'black'
|
|
});
|
|
|
|
return elementObject;
|
|
},
|
|
'bpmn:DataStoreReference': function(parentGfx, element) {
|
|
var DATA_STORE_PATH = pathMap.getScaledPath('DATA_STORE', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0,
|
|
my: 0.133
|
|
}
|
|
});
|
|
|
|
var elementStore = drawPath(parentGfx, DATA_STORE_PATH, {
|
|
strokeWidth: 2,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
fillOpacity: DEFAULT_FILL_OPACITY,
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
return elementStore;
|
|
},
|
|
'bpmn:BoundaryEvent': function(parentGfx, element) {
|
|
|
|
var semantic = getSemantic(element),
|
|
cancel = semantic.cancelActivity;
|
|
|
|
var attrs = {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
};
|
|
|
|
if (!cancel) {
|
|
attrs.strokeDasharray = '6';
|
|
attrs.strokeLinecap = 'round';
|
|
}
|
|
|
|
// apply fillOpacity
|
|
var outerAttrs = assign({}, attrs, {
|
|
fillOpacity: 1
|
|
});
|
|
|
|
// apply no-fill
|
|
var innerAttrs = assign({}, attrs, {
|
|
fill: 'none'
|
|
});
|
|
|
|
var outer = renderer('bpmn:Event')(parentGfx, element, outerAttrs);
|
|
|
|
/* inner path */ drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, innerAttrs);
|
|
|
|
renderEventContent(element, parentGfx);
|
|
|
|
return outer;
|
|
},
|
|
'bpmn:Group': function(parentGfx, element) {
|
|
var semantic = getSemantic(element),
|
|
di = getDi(element);
|
|
|
|
var group = drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, {
|
|
strokeWidth: 1,
|
|
strokeDasharray: '8,3,1,3',
|
|
fill: 'none',
|
|
pointerEvents: 'none'
|
|
});
|
|
|
|
var categoryValueRef = semantic.categoryValueRef || {};
|
|
|
|
if (categoryValueRef.value) {
|
|
var box = di.label ? di.label.bounds : element;
|
|
|
|
renderLabel(parentGfx, categoryValueRef.value, {
|
|
box: box,
|
|
style: {
|
|
fill: getStrokeColor(element, defaultStrokeColor)
|
|
}
|
|
});
|
|
}
|
|
|
|
return group;
|
|
},
|
|
'label': function(parentGfx, element) {
|
|
return renderExternalLabel(parentGfx, element);
|
|
},
|
|
'bpmn:TextAnnotation': function(parentGfx, element) {
|
|
var style = {
|
|
'fill': 'none',
|
|
'stroke': 'none'
|
|
};
|
|
|
|
var textElement = drawRect(parentGfx, element.width, element.height, 0, 0, style);
|
|
|
|
var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.0,
|
|
my: 0.0
|
|
}
|
|
});
|
|
|
|
drawPath(parentGfx, textPathData, {
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
var text = getSemantic(element).text || '';
|
|
renderLabel(parentGfx, text, {
|
|
box: element,
|
|
align: 'left-top',
|
|
padding: 5,
|
|
style: {
|
|
fill: getStrokeColor(element, defaultStrokeColor)
|
|
}
|
|
});
|
|
|
|
return textElement;
|
|
},
|
|
'ParticipantMultiplicityMarker': function(parentGfx, element) {
|
|
var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: ((element.width / 2) / element.width),
|
|
my: (element.height - 15) / element.height
|
|
}
|
|
});
|
|
|
|
drawMarker('participant-multiplicity', parentGfx, markerPath, {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
},
|
|
'SubProcessMarker': function(parentGfx, element) {
|
|
var markerRect = drawRect(parentGfx, 14, 14, 0, {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
|
|
// Process marker is placed in the middle of the box
|
|
// therefore fixed values can be used here
|
|
translate(markerRect, element.width / 2 - 7.5, element.height - 20);
|
|
|
|
var markerPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', {
|
|
xScaleFactor: 1.5,
|
|
yScaleFactor: 1.5,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: (element.width / 2 - 7.5) / element.width,
|
|
my: (element.height - 20) / element.height
|
|
}
|
|
});
|
|
|
|
drawMarker('sub-process', parentGfx, markerPath, {
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
},
|
|
'ParallelMarker': function(parentGfx, element, position) {
|
|
var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: ((element.width / 2 + position.parallel) / element.width),
|
|
my: (element.height - 20) / element.height
|
|
}
|
|
});
|
|
|
|
drawMarker('parallel', parentGfx, markerPath, {
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
},
|
|
'SequentialMarker': function(parentGfx, element, position) {
|
|
var markerPath = pathMap.getScaledPath('MARKER_SEQUENTIAL', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: ((element.width / 2 + position.seq) / element.width),
|
|
my: (element.height - 19) / element.height
|
|
}
|
|
});
|
|
|
|
drawMarker('sequential', parentGfx, markerPath, {
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
},
|
|
'CompensationMarker': function(parentGfx, element, position) {
|
|
var markerMath = pathMap.getScaledPath('MARKER_COMPENSATION', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: ((element.width / 2 + position.compensation) / element.width),
|
|
my: (element.height - 13) / element.height
|
|
}
|
|
});
|
|
|
|
drawMarker('compensation', parentGfx, markerMath, {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
},
|
|
'LoopMarker': function(parentGfx, element, position) {
|
|
var markerPath = pathMap.getScaledPath('MARKER_LOOP', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: ((element.width / 2 + position.loop) / element.width),
|
|
my: (element.height - 7) / element.height
|
|
}
|
|
});
|
|
|
|
drawMarker('loop', parentGfx, markerPath, {
|
|
strokeWidth: 1,
|
|
fill: getFillColor(element, defaultFillColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor),
|
|
strokeLinecap: 'round',
|
|
strokeMiterlimit: 0.5
|
|
});
|
|
},
|
|
'AdhocMarker': function(parentGfx, element, position) {
|
|
var markerPath = pathMap.getScaledPath('MARKER_ADHOC', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: ((element.width / 2 + position.adhoc) / element.width),
|
|
my: (element.height - 15) / element.height
|
|
}
|
|
});
|
|
|
|
drawMarker('adhoc', parentGfx, markerPath, {
|
|
strokeWidth: 1,
|
|
fill: getStrokeColor(element, defaultStrokeColor),
|
|
stroke: getStrokeColor(element, defaultStrokeColor)
|
|
});
|
|
}
|
|
};
|
|
|
|
function attachTaskMarkers(parentGfx, element, taskMarkers) {
|
|
var obj = getSemantic(element);
|
|
|
|
var subprocess = taskMarkers && taskMarkers.indexOf('SubProcessMarker') !== -1;
|
|
var position;
|
|
|
|
if (subprocess) {
|
|
position = {
|
|
seq: -21,
|
|
parallel: -22,
|
|
compensation: -42,
|
|
loop: -18,
|
|
adhoc: 10
|
|
};
|
|
} else {
|
|
position = {
|
|
seq: -3,
|
|
parallel: -6,
|
|
compensation: -27,
|
|
loop: 0,
|
|
adhoc: 10
|
|
};
|
|
}
|
|
|
|
forEach(taskMarkers, function(marker) {
|
|
renderer(marker)(parentGfx, element, position);
|
|
});
|
|
|
|
if (obj.isForCompensation) {
|
|
renderer('CompensationMarker')(parentGfx, element, position);
|
|
}
|
|
|
|
if (obj.$type === 'bpmn:AdHocSubProcess') {
|
|
renderer('AdhocMarker')(parentGfx, element, position);
|
|
}
|
|
|
|
var loopCharacteristics = obj.loopCharacteristics,
|
|
isSequential = loopCharacteristics && loopCharacteristics.isSequential;
|
|
|
|
if (loopCharacteristics) {
|
|
|
|
if (isSequential === undefined) {
|
|
renderer('LoopMarker')(parentGfx, element, position);
|
|
}
|
|
|
|
if (isSequential === false) {
|
|
renderer('ParallelMarker')(parentGfx, element, position);
|
|
}
|
|
|
|
if (isSequential === true) {
|
|
renderer('SequentialMarker')(parentGfx, element, position);
|
|
}
|
|
}
|
|
}
|
|
|
|
function renderDataItemCollection(parentGfx, element) {
|
|
|
|
var yPosition = (element.height - 16) / element.height;
|
|
|
|
var pathData = pathMap.getScaledPath('DATA_OBJECT_COLLECTION_PATH', {
|
|
xScaleFactor: 1,
|
|
yScaleFactor: 1,
|
|
containerWidth: element.width,
|
|
containerHeight: element.height,
|
|
position: {
|
|
mx: 0.451,
|
|
my: yPosition
|
|
}
|
|
});
|
|
|
|
/* collection path */ drawPath(parentGfx, pathData, {
|
|
strokeWidth: 2
|
|
});
|
|
}
|
|
|
|
|
|
// extension API, use at your own risk
|
|
this._drawPath = drawPath;
|
|
|
|
}
|
|
|
|
|
|
inherits(BpmnRenderer, BaseRenderer);
|
|
|
|
BpmnRenderer.$inject = [
|
|
'config.bpmnRenderer',
|
|
'eventBus',
|
|
'styles',
|
|
'pathMap',
|
|
'canvas',
|
|
'textRenderer'
|
|
];
|
|
|
|
|
|
BpmnRenderer.prototype.canRender = function(element) {
|
|
return is(element, 'bpmn:BaseElement');
|
|
};
|
|
|
|
BpmnRenderer.prototype.drawShape = function(parentGfx, element) {
|
|
var type = element.type;
|
|
var h = this.handlers[type];
|
|
|
|
/* jshint -W040 */
|
|
return h(parentGfx, element);
|
|
};
|
|
|
|
BpmnRenderer.prototype.drawConnection = function(parentGfx, element) {
|
|
var type = element.type;
|
|
var h = this.handlers[type];
|
|
|
|
/* jshint -W040 */
|
|
return h(parentGfx, element);
|
|
};
|
|
|
|
BpmnRenderer.prototype.getShapePath = function(element) {
|
|
|
|
if (is(element, 'bpmn:Event')) {
|
|
return getCirclePath(element);
|
|
}
|
|
|
|
if (is(element, 'bpmn:Activity')) {
|
|
return getRoundRectPath(element, TASK_BORDER_RADIUS);
|
|
}
|
|
|
|
if (is(element, 'bpmn:Gateway')) {
|
|
return getDiamondPath(element);
|
|
}
|
|
|
|
return getRectPath(element);
|
|
};
|