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.
1928 lines
52 KiB
1928 lines
52 KiB
import inherits from 'inherits-browser'; |
|
|
|
import { |
|
isObject, |
|
assign, |
|
forEach |
|
} from 'min-dash'; |
|
|
|
import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer'; |
|
|
|
import { |
|
isExpanded, |
|
isEventSubProcess |
|
} from '../util/DiUtil'; |
|
|
|
import { |
|
getLabel |
|
} from '../features/label-editing/LabelUtil'; |
|
|
|
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, |
|
getLabelColor |
|
} 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'; |
|
|
|
import { black } from './BpmnRenderUtil'; |
|
|
|
var RENDERER_IDS = new Ids(); |
|
|
|
var TASK_BORDER_RADIUS = 10; |
|
var INNER_OUTER_DIST = 3; |
|
|
|
var DEFAULT_FILL_OPACITY = .95, |
|
HIGH_FILL_OPACITY = .35; |
|
|
|
var ELEMENT_LABEL_DISTANCE = 10; |
|
|
|
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, |
|
defaultLabelColor = config && config.defaultLabelColor; |
|
|
|
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) { |
|
|
|
// only allow characters and numbers |
|
return str.replace(/[^0-9a-zA-z]+/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 renderer(type) { |
|
return handlers[type]; |
|
} |
|
|
|
function as(type) { |
|
return function(parentGfx, element) { |
|
return renderer(type)(parentGfx, element); |
|
}; |
|
} |
|
|
|
function renderEventContent(element, parentGfx) { |
|
|
|
var event = getSemantic(element); |
|
var isThrowing = isThrowEvent(event); |
|
|
|
if (event.eventDefinitions && event.eventDefinitions.length > 1) { |
|
if (event.parallelMultiple) { |
|
return renderer('bpmn:ParallelMultipleEventDefinition')(parentGfx, element, isThrowing); |
|
} |
|
else { |
|
return renderer('bpmn:MultipleEventDefinition')(parentGfx, element, isThrowing); |
|
} |
|
} |
|
|
|
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: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: getLabelColor(element, defaultLabelColor, defaultStrokeColor) |
|
} |
|
}); |
|
} |
|
|
|
function renderExternalLabel(parentGfx, element) { |
|
|
|
var box = { |
|
width: 90, |
|
height: 30, |
|
x: element.width / 2 + element.x, |
|
y: element.height / 2 + element.y |
|
}; |
|
|
|
return renderLabel(parentGfx, getLabel(element), { |
|
box: box, |
|
fitBox: true, |
|
style: assign( |
|
{}, |
|
textRenderer.getExternalStyle(), |
|
{ |
|
fill: getLabelColor(element, defaultLabelColor, defaultStrokeColor) |
|
} |
|
) |
|
}); |
|
} |
|
|
|
function renderLaneLabel(parentGfx, text, element) { |
|
var textBox = renderLabel(parentGfx, text, { |
|
box: { |
|
height: 30, |
|
width: element.height |
|
}, |
|
align: 'center-middle', |
|
style: { |
|
fill: getLabelColor(element, defaultLabelColor, 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: getLabelColor(element, defaultLabelColor, 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'; |
|
} |
|
|
|
var message = drawPath(parentGfx, markerPathData, messageAttrs); |
|
|
|
var labelText = semantic.messageRef.name; |
|
var label = renderLabel(parentGfx, labelText, { |
|
align: 'center-top', |
|
fitBox: true, |
|
style: { |
|
fill: getStrokeColor(element, defaultLabelColor, defaultStrokeColor) |
|
} |
|
}); |
|
|
|
var messageBounds = message.getBBox(), |
|
labelBounds = label.getBBox(); |
|
|
|
var translateX = midPoint.x - labelBounds.width / 2, |
|
translateY = midPoint.y + messageBounds.height / 2 + ELEMENT_LABEL_DISTANCE; |
|
|
|
transform(label, translateX, translateY, 0); |
|
|
|
} |
|
|
|
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 group = drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, { |
|
stroke: getStrokeColor(element, defaultStrokeColor), |
|
strokeWidth: 1, |
|
strokeDasharray: '8,3,1,3', |
|
fill: 'none', |
|
pointerEvents: 'none' |
|
}); |
|
|
|
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: getLabelColor(element, defaultLabelColor, 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: 2, |
|
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 - 18) / element.height; |
|
|
|
var pathData = pathMap.getScaledPath('DATA_OBJECT_COLLECTION_PATH', { |
|
xScaleFactor: 1, |
|
yScaleFactor: 1, |
|
containerWidth: element.width, |
|
containerHeight: element.height, |
|
position: { |
|
mx: 0.33, |
|
my: yPosition |
|
} |
|
}); |
|
|
|
/* collection path */ drawPath(parentGfx, pathData, { |
|
strokeWidth: 2 |
|
}); |
|
} |
|
|
|
|
|
// extension API, use at your own risk |
|
this._drawPath = drawPath; |
|
|
|
this._renderer = renderer; |
|
} |
|
|
|
|
|
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._renderer(type); |
|
|
|
/* jshint -W040 */ |
|
return h(parentGfx, element); |
|
}; |
|
|
|
BpmnRenderer.prototype.drawConnection = function(parentGfx, element) { |
|
var type = element.type; |
|
var h = this._renderer(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); |
|
};
|
|
|