//import ColorRenderer from '../colors/ColorRenderer'; import BpmnRenderer from 'bpmn-js/lib/draw/BpmnRenderer'; //import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer'; //import { getBusinessObject } from 'bpmn-js/lib/util/ModelUtil'; import { getFillColor, getStrokeColor } from 'bpmn-js/lib/draw/BpmnRenderUtil'; import { append as svgAppend, attr as svgAttr, classes as svgClasses, create as svgCreate, remove as svgRemove } from 'tiny-svg'; import { isObject, forEach, assign } from 'min-dash'; import { //rotate, transform, //translate } from 'diagram-js/lib/util/SvgTransformUtil'; import { createLine } from 'diagram-js/lib/util/RenderUtil'; import { isExpanded, isEventSubProcess } from 'bpmn-js/lib/util/DiUtil'; const HIGH_PRIORITY = 2500, TASK_BORDER_RADIUS = 2; export default class MultilangRenderer extends BpmnRenderer { constructor(config, eventBus, styles, pathMap, canvas, textRenderer, injector) { super(config, eventBus, styles, pathMap, canvas, textRenderer, HIGH_PRIORITY); var DEFAULT_FILL_OPACITY = .95, HIGH_FILL_OPACITY = .35; var defaultFillColor = config && config.defaultFillColor, defaultStrokeColor = config && config.defaultStrokeColor, computeStyle = styles.computeStyle, handlers = this.handlers, me = this; eventBus.on('diagram.clear', function() { me.elCount = 0; me.participantCount = 0; }); function renderer(type) { return handlers[type]; } function getLangText(element) { var semantic = getSemantic(element); var lang = injector.get('bpmnjs').getLang(); return semantic.get(`text_${lang}`) } function getSemantic(element) { return element.businessObject; } function renderEmbeddedLabel(parentGfx, element, align) { return renderLabel(parentGfx, getLangText(element), { box: element, align: align, padding: 5, style: { fill: getStrokeColor(element, defaultStrokeColor) } }); } 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 renderNumLabel(parentGfx, text, element) { if (!text) { return; } var textBox = renderLabel(parentGfx, text, { box: { height: 15, width: element.height }, align: 'left-top', padding: 3, style: { fill: 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 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 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 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 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; } this.renderNumLabel = renderNumLabel; this.handlers['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; } this.handlers['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 = getLangText(element); renderLaneLabel(parentGfx, text, element); } else { // Collapsed pool draw text inline var text2 = getLangText(element); 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; } this.handlers['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') { renderLaneLabel(parentGfx, getLangText(element), element); } return rect; } this.handlers['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 = getLangText(element); renderLabel(parentGfx, text, { box: element, align: 'left-top', padding: 5, style: { fill: getStrokeColor(element, defaultStrokeColor) } }); return textElement; } this.handlers['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; } } } MultilangRenderer.$inject = [ 'config.bpmnRenderer', 'eventBus', 'styles', 'pathMap', 'canvas', 'textRenderer', 'injector' ]; MultilangRenderer.prototype.drawShape = function (parentGfx, element) { var type = element.type; var h = this.handlers[type]; const shape = h(parentGfx, element); this.participantCount = this.participantCount || 0; this.elCount = this.elCount || 0; if (element.type != 'label') { svgAttr(shape, { fill: getCustomColor(element) || '#ffffff' }); if (!element.renderNum) { if (element.type == 'bpmn:Participant') { element.renderNum = ++this.participantCount + ''; this.elCount = 0; } else { if (element.type != 'bpmn:TextAnnotation') { element.renderNum = this.participantCount + '.' + (++this.elCount); } } } this.renderNumLabel(parentGfx, element.renderNum, element); } else { svgAttr(shape, { fill: getCustomColor(element) || '#000000' }); } return shape; }; function getCustomColor(element) { var bo = element.businessObject; return bo.di.get('color:background-color'); }