123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- import {
- getBusinessObject,
- is
- } from '../../util/ModelUtil';
- import {
- isEventSubProcess,
- isExpanded
- } from '../../util/DiUtil';
- import {
- isDifferentType
- } from './util/TypeUtil';
- import {
- forEach,
- filter
- } from 'min-dash';
- import * as replaceOptions from '../replace/ReplaceOptions';
- /**
- * This module is an element agnostic replace menu provider for the popup menu.
- */
- export default function ReplaceMenuProvider(
- popupMenu, modeling, moddle,
- bpmnReplace, rules, translate) {
- this._popupMenu = popupMenu;
- this._modeling = modeling;
- this._moddle = moddle;
- this._bpmnReplace = bpmnReplace;
- this._rules = rules;
- this._translate = translate;
- this.register();
- }
- ReplaceMenuProvider.$inject = [
- 'popupMenu',
- 'modeling',
- 'moddle',
- 'bpmnReplace',
- 'rules',
- 'translate'
- ];
- /**
- * Register replace menu provider in the popup menu
- */
- ReplaceMenuProvider.prototype.register = function() {
- this._popupMenu.registerProvider('bpmn-replace', this);
- };
- /**
- * Get all entries from replaceOptions for the given element and apply filters
- * on them. Get for example only elements, which are different from the current one.
- *
- * @param {djs.model.Base} element
- *
- * @return {Array<Object>} a list of menu entry items
- */
- ReplaceMenuProvider.prototype.getEntries = function(element) {
- var businessObject = element.businessObject;
- var rules = this._rules;
- var entries;
- if (!rules.allowed('shape.replace', { element: element })) {
- return [];
- }
- var differentType = isDifferentType(element);
- // start events outside event sub processes
- if (is(businessObject, 'bpmn:StartEvent') && !isEventSubProcess(businessObject.$parent)) {
- entries = filter(replaceOptions.START_EVENT, differentType);
- return this._createEntries(element, entries);
- }
- // expanded/collapsed pools
- if (is(businessObject, 'bpmn:Participant')) {
- entries = filter(replaceOptions.PARTICIPANT, function(entry) {
- return isExpanded(businessObject) !== entry.target.isExpanded;
- });
- return this._createEntries(element, entries);
- }
- // start events inside event sub processes
- if (is(businessObject, 'bpmn:StartEvent') && isEventSubProcess(businessObject.$parent)) {
- entries = filter(replaceOptions.EVENT_SUB_PROCESS_START_EVENT, function(entry) {
- var target = entry.target;
- var isInterrupting = target.isInterrupting !== false;
- var isInterruptingEqual = getBusinessObject(element).isInterrupting === isInterrupting;
- // filters elements which types and event definition are equal but have have different interrupting types
- return differentType(entry) || !differentType(entry) && !isInterruptingEqual;
- });
- return this._createEntries(element, entries);
- }
- // end events
- if (is(businessObject, 'bpmn:EndEvent')) {
- entries = filter(replaceOptions.END_EVENT, function(entry) {
- var target = entry.target;
- // hide cancel end events outside transactions
- if (target.eventDefinitionType == 'bpmn:CancelEventDefinition' && !is(businessObject.$parent, 'bpmn:Transaction')) {
- return false;
- }
- return differentType(entry);
- });
- return this._createEntries(element, entries);
- }
- // boundary events
- if (is(businessObject, 'bpmn:BoundaryEvent')) {
- entries = filter(replaceOptions.BOUNDARY_EVENT, function(entry) {
- var target = entry.target;
- if (target.eventDefinition == 'bpmn:CancelEventDefinition' &&
- !is(businessObject.attachedToRef, 'bpmn:Transaction')) {
- return false;
- }
- var cancelActivity = target.cancelActivity !== false;
- var isCancelActivityEqual = businessObject.cancelActivity == cancelActivity;
- return differentType(entry) || !differentType(entry) && !isCancelActivityEqual;
- });
- return this._createEntries(element, entries);
- }
- // intermediate events
- if (is(businessObject, 'bpmn:IntermediateCatchEvent') ||
- is(businessObject, 'bpmn:IntermediateThrowEvent')) {
- entries = filter(replaceOptions.INTERMEDIATE_EVENT, differentType);
- return this._createEntries(element, entries);
- }
- // gateways
- if (is(businessObject, 'bpmn:Gateway')) {
- entries = filter(replaceOptions.GATEWAY, differentType);
- return this._createEntries(element, entries);
- }
- // transactions
- if (is(businessObject, 'bpmn:Transaction')) {
- entries = filter(replaceOptions.TRANSACTION, differentType);
- return this._createEntries(element, entries);
- }
- // expanded event sub processes
- if (isEventSubProcess(businessObject) && isExpanded(businessObject)) {
- entries = filter(replaceOptions.EVENT_SUB_PROCESS, differentType);
- return this._createEntries(element, entries);
- }
- // expanded sub processes
- if (is(businessObject, 'bpmn:SubProcess') && isExpanded(businessObject)) {
- entries = filter(replaceOptions.SUBPROCESS_EXPANDED, differentType);
- return this._createEntries(element, entries);
- }
- // collapsed ad hoc sub processes
- if (is(businessObject, 'bpmn:AdHocSubProcess') && !isExpanded(businessObject)) {
- entries = filter(replaceOptions.TASK, function(entry) {
- var target = entry.target;
- var isTargetSubProcess = target.type === 'bpmn:SubProcess';
- var isTargetExpanded = target.isExpanded === true;
- return isDifferentType(element, target) && (!isTargetSubProcess || isTargetExpanded);
- });
- return this._createEntries(element, entries);
- }
- // sequence flows
- if (is(businessObject, 'bpmn:SequenceFlow')) {
- return this._createSequenceFlowEntries(element, replaceOptions.SEQUENCE_FLOW);
- }
- // flow nodes
- if (is(businessObject, 'bpmn:FlowNode')) {
- entries = filter(replaceOptions.TASK, differentType);
- // collapsed SubProcess can not be replaced with itself
- if (is(businessObject, 'bpmn:SubProcess') && !isExpanded(businessObject)) {
- entries = filter(entries, function(entry) {
- return entry.label !== 'Sub Process (collapsed)';
- });
- }
- return this._createEntries(element, entries);
- }
- return [];
- };
- /**
- * Get a list of header items for the given element. This includes buttons
- * for multi instance markers and for the ad hoc marker.
- *
- * @param {djs.model.Base} element
- *
- * @return {Array<Object>} a list of menu entry items
- */
- ReplaceMenuProvider.prototype.getHeaderEntries = function(element) {
- var headerEntries = [];
- if (is(element, 'bpmn:Activity') && !isEventSubProcess(element)) {
- headerEntries = headerEntries.concat(this._getLoopEntries(element));
- }
- if (is(element, 'bpmn:SubProcess') &&
- !is(element, 'bpmn:Transaction') &&
- !isEventSubProcess(element)) {
- headerEntries.push(this._getAdHocEntry(element));
- }
- return headerEntries;
- };
- /**
- * Creates an array of menu entry objects for a given element and filters the replaceOptions
- * according to a filter function.
- *
- * @param {djs.model.Base} element
- * @param {Object} replaceOptions
- *
- * @return {Array<Object>} a list of menu items
- */
- ReplaceMenuProvider.prototype._createEntries = function(element, replaceOptions) {
- var menuEntries = [];
- var self = this;
- forEach(replaceOptions, function(definition) {
- var entry = self._createMenuEntry(definition, element);
- menuEntries.push(entry);
- });
- return menuEntries;
- };
- /**
- * Creates an array of menu entry objects for a given sequence flow.
- *
- * @param {djs.model.Base} element
- * @param {Object} replaceOptions
- * @return {Array<Object>} a list of menu items
- */
- ReplaceMenuProvider.prototype._createSequenceFlowEntries = function(element, replaceOptions) {
- var businessObject = getBusinessObject(element);
- var menuEntries = [];
- var modeling = this._modeling,
- moddle = this._moddle;
- var self = this;
- forEach(replaceOptions, function(entry) {
- switch (entry.actionName) {
- case 'replace-with-default-flow':
- if (businessObject.sourceRef.default !== businessObject &&
- (is(businessObject.sourceRef, 'bpmn:ExclusiveGateway') ||
- is(businessObject.sourceRef, 'bpmn:InclusiveGateway') ||
- is(businessObject.sourceRef, 'bpmn:ComplexGateway') ||
- is(businessObject.sourceRef, 'bpmn:Activity'))) {
- menuEntries.push(self._createMenuEntry(entry, element, function() {
- modeling.updateProperties(element.source, { default: businessObject });
- }));
- }
- break;
- case 'replace-with-conditional-flow':
- if (!businessObject.conditionExpression && is(businessObject.sourceRef, 'bpmn:Activity')) {
- menuEntries.push(self._createMenuEntry(entry, element, function() {
- var conditionExpression = moddle.create('bpmn:FormalExpression', { body: '' });
- modeling.updateProperties(element, { conditionExpression: conditionExpression });
- }));
- }
- break;
- default:
- // default flows
- if (is(businessObject.sourceRef, 'bpmn:Activity') && businessObject.conditionExpression) {
- return menuEntries.push(self._createMenuEntry(entry, element, function() {
- modeling.updateProperties(element, { conditionExpression: undefined });
- }));
- }
- // conditional flows
- if ((is(businessObject.sourceRef, 'bpmn:ExclusiveGateway') ||
- is(businessObject.sourceRef, 'bpmn:InclusiveGateway') ||
- is(businessObject.sourceRef, 'bpmn:ComplexGateway') ||
- is(businessObject.sourceRef, 'bpmn:Activity')) &&
- businessObject.sourceRef.default === businessObject) {
- return menuEntries.push(self._createMenuEntry(entry, element, function() {
- modeling.updateProperties(element.source, { default: undefined });
- }));
- }
- }
- });
- return menuEntries;
- };
- /**
- * Creates and returns a single menu entry item.
- *
- * @param {Object} definition a single replace options definition object
- * @param {djs.model.Base} element
- * @param {Function} [action] an action callback function which gets called when
- * the menu entry is being triggered.
- *
- * @return {Object} menu entry item
- */
- ReplaceMenuProvider.prototype._createMenuEntry = function(definition, element, action) {
- var translate = this._translate;
- var replaceElement = this._bpmnReplace.replaceElement;
- var replaceAction = function() {
- return replaceElement(element, definition.target);
- };
- action = action || replaceAction;
- var menuEntry = {
- label: translate(definition.label),
- className: definition.className,
- id: definition.actionName,
- action: action
- };
- return menuEntry;
- };
- /**
- * Get a list of menu items containing buttons for multi instance markers
- *
- * @param {djs.model.Base} element
- *
- * @return {Array<Object>} a list of menu items
- */
- ReplaceMenuProvider.prototype._getLoopEntries = function(element) {
- var self = this;
- var translate = this._translate;
- function toggleLoopEntry(event, entry) {
- var loopCharacteristics;
- if (entry.active) {
- loopCharacteristics = undefined;
- } else {
- loopCharacteristics = self._moddle.create(entry.options.loopCharacteristics);
- if (entry.options.isSequential) {
- loopCharacteristics.isSequential = entry.options.isSequential;
- }
- }
- self._modeling.updateProperties(element, { loopCharacteristics: loopCharacteristics });
- }
- var businessObject = getBusinessObject(element),
- loopCharacteristics = businessObject.loopCharacteristics;
- var isSequential,
- isLoop,
- isParallel;
- if (loopCharacteristics) {
- isSequential = loopCharacteristics.isSequential;
- isLoop = loopCharacteristics.isSequential === undefined;
- isParallel = loopCharacteristics.isSequential !== undefined && !loopCharacteristics.isSequential;
- }
- var loopEntries = [
- {
- id: 'toggle-parallel-mi',
- className: 'bpmn-icon-parallel-mi-marker',
- title: translate('Parallel Multi Instance'),
- active: isParallel,
- action: toggleLoopEntry,
- options: {
- loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
- isSequential: false
- }
- },
- {
- id: 'toggle-sequential-mi',
- className: 'bpmn-icon-sequential-mi-marker',
- title: translate('Sequential Multi Instance'),
- active: isSequential,
- action: toggleLoopEntry,
- options: {
- loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
- isSequential: true
- }
- },
- {
- id: 'toggle-loop',
- className: 'bpmn-icon-loop-marker',
- title: translate('Loop'),
- active: isLoop,
- action: toggleLoopEntry,
- options: {
- loopCharacteristics: 'bpmn:StandardLoopCharacteristics'
- }
- }
- ];
- return loopEntries;
- };
- /**
- * Get the menu items containing a button for the ad hoc marker
- *
- * @param {djs.model.Base} element
- *
- * @return {Object} a menu item
- */
- ReplaceMenuProvider.prototype._getAdHocEntry = function(element) {
- var translate = this._translate;
- var businessObject = getBusinessObject(element);
- var isAdHoc = is(businessObject, 'bpmn:AdHocSubProcess');
- var replaceElement = this._bpmnReplace.replaceElement;
- var adHocEntry = {
- id: 'toggle-adhoc',
- className: 'bpmn-icon-ad-hoc-marker',
- title: translate('Ad-hoc'),
- active: isAdHoc,
- action: function(event, entry) {
- if (isAdHoc) {
- return replaceElement(element, { type: 'bpmn:SubProcess' }, {
- autoResize: false,
- layoutConnection: false
- });
- } else {
- return replaceElement(element, { type: 'bpmn:AdHocSubProcess' }, {
- autoResize: false,
- layoutConnection: false
- });
- }
- }
- };
- return adHocEntry;
- };
|