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

282 lines
6.1 KiB
JavaScript

import {
assign,
forEach,
isObject
} from 'min-dash';
import inherits from 'inherits';
import {
getBusinessObject,
getDi,
is
} from '../../util/ModelUtil';
import {
isAny
} from '../modeling/util/ModelingUtil';
import {
isExpanded
} from '../../util/DiUtil';
import BaseElementFactory from 'diagram-js/lib/core/ElementFactory';
import {
DEFAULT_LABEL_SIZE
} from '../../util/LabelUtil';
import {
ensureCompatDiRef
} from '../../util/CompatibilityUtil';
/**
* A bpmn-aware factory for diagram-js shapes
*/
export default function ElementFactory(bpmnFactory, moddle, translate) {
BaseElementFactory.call(this);
this._bpmnFactory = bpmnFactory;
this._moddle = moddle;
this._translate = translate;
}
inherits(ElementFactory, BaseElementFactory);
ElementFactory.$inject = [
'bpmnFactory',
'moddle',
'translate'
];
ElementFactory.prototype.baseCreate = BaseElementFactory.prototype.create;
ElementFactory.prototype.create = function(elementType, attrs) {
// no special magic for labels,
// we assume their businessObjects have already been created
// and wired via attrs
if (elementType === 'label') {
var di = attrs.di || this._bpmnFactory.createDiLabel();
return this.baseCreate(elementType, assign({ type: 'label', di: di }, DEFAULT_LABEL_SIZE, attrs));
}
return this.createBpmnElement(elementType, attrs);
};
ElementFactory.prototype.createBpmnElement = function(elementType, attrs) {
var size,
translate = this._translate;
attrs = attrs || {};
var businessObject = attrs.businessObject,
di = attrs.di;
if (!businessObject) {
if (!attrs.type) {
throw new Error(translate('no shape type specified'));
}
businessObject = this._bpmnFactory.create(attrs.type);
ensureCompatDiRef(businessObject);
}
if (!isModdleDi(di)) {
var diAttrs = assign(
di || {},
{ id: businessObject.id + '_di' }
);
if (elementType === 'root') {
di = this._bpmnFactory.createDiPlane(businessObject, diAttrs);
} else
if (elementType === 'connection') {
di = this._bpmnFactory.createDiEdge(businessObject, diAttrs);
} else {
di = this._bpmnFactory.createDiShape(businessObject, diAttrs);
}
}
if (is(businessObject, 'bpmn:Group')) {
attrs = assign({
isFrame: true
}, attrs);
}
applyAttributes(businessObject, attrs, [
'processRef',
'isInterrupting',
'associationDirection',
'isForCompensation'
]);
if (attrs.isExpanded) {
applyAttribute(di, attrs, 'isExpanded');
}
if (is(businessObject, 'bpmn:SubProcess')) {
attrs.collapsed = !isExpanded(businessObject, di);
}
if (is(businessObject, 'bpmn:ExclusiveGateway')) {
di.isMarkerVisible = true;
}
var eventDefinitions,
newEventDefinition;
if (attrs.eventDefinitionType) {
eventDefinitions = businessObject.get('eventDefinitions') || [];
newEventDefinition = this._bpmnFactory.create(attrs.eventDefinitionType, attrs.eventDefinitionAttrs);
if (attrs.eventDefinitionType === 'bpmn:ConditionalEventDefinition') {
newEventDefinition.condition = this._bpmnFactory.create('bpmn:FormalExpression');
}
eventDefinitions.push(newEventDefinition);
newEventDefinition.$parent = businessObject;
businessObject.eventDefinitions = eventDefinitions;
delete attrs.eventDefinitionType;
}
size = this.getDefaultSize(businessObject, di);
attrs = assign({
id: businessObject.id
}, size, attrs, {
businessObject: businessObject,
di: di
});
return this.baseCreate(elementType, attrs);
};
ElementFactory.prototype.getDefaultSize = function(element, di) {
var bo = getBusinessObject(element);
di = di || getDi(element);
if (is(bo, 'bpmn:SubProcess')) {
if (isExpanded(bo, di)) {
return { width: 350, height: 200 };
} else {
return { width: 100, height: 80 };
}
}
if (is(bo, 'bpmn:Task')) {
return { width: 100, height: 80 };
}
if (is(bo, 'bpmn:Gateway')) {
return { width: 50, height: 50 };
}
if (is(bo, 'bpmn:Event')) {
return { width: 36, height: 36 };
}
if (is(bo, 'bpmn:Participant')) {
if (isExpanded(bo, di)) {
return { width: 600, height: 250 };
} else {
return { width: 400, height: 60 };
}
}
if (is(bo, 'bpmn:Lane')) {
return { width: 400, height: 100 };
}
if (is(bo, 'bpmn:DataObjectReference')) {
return { width: 36, height: 50 };
}
if (is(bo, 'bpmn:DataStoreReference')) {
return { width: 50, height: 50 };
}
if (is(bo, 'bpmn:TextAnnotation')) {
return { width: 100, height: 30 };
}
if (is(bo, 'bpmn:Group')) {
return { width: 300, height: 300 };
}
return { width: 100, height: 80 };
};
/**
* Create participant.
*
* @param {boolean|Object} [attrs] attrs
*
* @returns {djs.model.Shape}
*/
ElementFactory.prototype.createParticipantShape = function(attrs) {
if (!isObject(attrs)) {
attrs = { isExpanded: attrs };
}
attrs = assign({ type: 'bpmn:Participant' }, attrs || {});
// participants are expanded by default
if (attrs.isExpanded !== false) {
attrs.processRef = this._bpmnFactory.create('bpmn:Process');
}
return this.createShape(attrs);
};
// helpers //////////////////////
/**
* Apply attributes from a map to the given element,
* remove attribute from the map on application.
*
* @param {Base} element
* @param {Object} attrs (in/out map of attributes)
* @param {Array<string>} attributeNames name of attributes to apply
*/
function applyAttributes(element, attrs, attributeNames) {
forEach(attributeNames, function(property) {
if (attrs[property] !== undefined) {
applyAttribute(element, attrs, property);
}
});
}
/**
* Apply named property to element and drain it from the attrs
* collection.
*
* @param {Base} element
* @param {Object} attrs (in/out map of attributes)
* @param {string} attributeName to apply
*/
function applyAttribute(element, attrs, attributeName) {
element[attributeName] = attrs[attributeName];
delete attrs[attributeName];
}
function isModdleDi(element) {
return isAny(element, [
'bpmndi:BPMNShape',
'bpmndi:BPMNEdge',
'bpmndi:BPMNDiagram',
'bpmndi:BPMNPlane',
]);
}