Skip to content

Commit

Permalink
feat: add bpmn:InclusiveGateway support
Browse files Browse the repository at this point in the history
Closes #88
  • Loading branch information
barmac authored and nikku committed Nov 30, 2023
1 parent 14c563f commit 77f7d3a
Show file tree
Hide file tree
Showing 27 changed files with 1,756 additions and 3 deletions.
2 changes: 2 additions & 0 deletions lib/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import SetAnimationSpeedModule from './features/set-animation-speed';

import ExclusiveGatewaySettingsModule from './features/exclusive-gateway-settings';
import NeutralElementColors from './features/neutral-element-colors';
import InclusiveGatewaySettingsModule from './features/inclusive-gateway-settings';
import TokenSimulationPaletteModule from './features/palette';

export default {
Expand All @@ -31,6 +32,7 @@ export default {
SetAnimationSpeedModule,
ExclusiveGatewaySettingsModule,
NeutralElementColors,
InclusiveGatewaySettingsModule,
TokenSimulationPaletteModule
]
};
2 changes: 2 additions & 0 deletions lib/features/context-pads/ContextPads.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from 'min-dom';

import ExclusiveGatewayHandler from './handler/ExclusiveGatewayHandler';
import InclusiveGatewayHandler from './handler/InclusiveGatewayHandler';
import PauseHandler from './handler/PauseHandler';
import TriggerHandler from './handler/TriggerHandler';

Expand Down Expand Up @@ -45,6 +46,7 @@ export default function ContextPads(
this._handlers = [];

this.registerHandler('bpmn:ExclusiveGateway', ExclusiveGatewayHandler);
this.registerHandler('bpmn:InclusiveGateway', InclusiveGatewayHandler);

this.registerHandler('bpmn:Activity', PauseHandler);

Expand Down
47 changes: 47 additions & 0 deletions lib/features/context-pads/handler/InclusiveGatewayHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {
ForkIcon
} from '../../../icons';

import { getBusinessObject } from '../../../util/ElementHelper';
import { isSequenceFlow } from '../../../simulator/util/ModelUtil';

export default function InclusiveGatewayHandler(inclusiveGatewaySettings) {
this._inclusiveGatewaySettings = inclusiveGatewaySettings;
}

InclusiveGatewayHandler.prototype.createContextPads = function(element) {
const outgoingFlows = element.outgoing.filter(isSequenceFlow);

if (outgoingFlows.length < 2) {
return;
}

const nonDefaultFlows = outgoingFlows.filter(outgoing => {
const flowBo = getBusinessObject(outgoing),
gatewayBo = getBusinessObject(element);

return gatewayBo.default !== flowBo;
});

const html = `
<div class="bts-context-pad" title="Set Sequence Flow">
${ForkIcon()}
</div>
`;

return nonDefaultFlows.map(sequenceFlow => {
const action = () => {
this._inclusiveGatewaySettings.toggleSequenceFlow(element, sequenceFlow);
};

return {
action,
element: sequenceFlow,
html
};
});
};

InclusiveGatewayHandler.$inject = [
'inclusiveGatewaySettings'
];
1 change: 0 additions & 1 deletion lib/features/element-support/ElementSupport.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {


const UNSUPPORTED_ELEMENTS = [
'bpmn:InclusiveGateway',
'bpmn:ComplexGateway'
];

Expand Down
161 changes: 161 additions & 0 deletions lib/features/inclusive-gateway-settings/InclusiveGatewaySettings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import {
TOGGLE_MODE_EVENT
} from '../../util/EventHelper';


const SELECTED_COLOR = '--token-simulation-grey-darken-30';
const NOT_SELECTED_COLOR = '--token-simulation-grey-lighten-56';

import {
getBusinessObject,
is,
isSequenceFlow
} from '../../simulator/util/ModelUtil';

const COLOR_ID = 'inclusive-gateway-settings';


export default function InclusiveGatewaySettings(
eventBus, elementRegistry,
elementColors, simulator, simulationStyles) {

this._elementRegistry = elementRegistry;
this._elementColors = elementColors;
this._simulator = simulator;
this._simulationStyles = simulationStyles;

eventBus.on(TOGGLE_MODE_EVENT, event => {
if (event.active) {
this.setDefaults();
} else {
this.reset();
}
});
}

InclusiveGatewaySettings.prototype.setDefaults = function() {
const inclusiveGateways = this._elementRegistry.filter(element => {
return is(element, 'bpmn:InclusiveGateway');
});

inclusiveGateways.forEach(inclusiveGateway => {
if (inclusiveGateway.outgoing.filter(isSequenceFlow).length > 1) {
this._setGatewayDefaults(inclusiveGateway);
}
});
};

InclusiveGatewaySettings.prototype.reset = function() {
const inclusiveGateways = this._elementRegistry.filter(element => {
return is(element, 'bpmn:InclusiveGateway');
});

inclusiveGateways.forEach(inclusiveGateway => {
if (inclusiveGateway.outgoing.filter(isSequenceFlow).length > 1) {
this._resetGateway(inclusiveGateway);
}
});
};

InclusiveGatewaySettings.prototype.toggleSequenceFlow = function(gateway, sequenceFlow) {
const activeOutgoing = this._getActiveOutgoing(gateway),
defaultFlow = getDefaultFlow(gateway),
nonDefaultFlows = getNonDefaultFlows(gateway);

let newActiveOutgoing;
if (activeOutgoing.includes(sequenceFlow)) {
newActiveOutgoing = without(activeOutgoing, sequenceFlow);
} else {
newActiveOutgoing = without(activeOutgoing, defaultFlow).concat(sequenceFlow);
}

// make sure at least one flow is active
if (!newActiveOutgoing.length) {

// default flow if available
if (defaultFlow) {
newActiveOutgoing = [ defaultFlow ];
} else {

// or another flow which is not the one toggled
newActiveOutgoing = [ nonDefaultFlows.find(flow => flow !== sequenceFlow) ];
}
}

this._setActiveOutgoing(gateway, newActiveOutgoing);
};

InclusiveGatewaySettings.prototype._getActiveOutgoing = function(gateway) {
const {
activeOutgoing
} = this._simulator.getConfig(gateway);

return activeOutgoing;
};

InclusiveGatewaySettings.prototype._setActiveOutgoing = function(gateway, activeOutgoing) {
this._simulator.setConfig(gateway, { activeOutgoing });

const sequenceFlows = gateway.outgoing.filter(isSequenceFlow);

// set colors
sequenceFlows.forEach(outgoing => {

const style = (!activeOutgoing || activeOutgoing.includes(outgoing)) ?
SELECTED_COLOR : NOT_SELECTED_COLOR;
const stroke = this._simulationStyles.get(style);

this._elementColors.add(outgoing, COLOR_ID, {
stroke
});
});
};

InclusiveGatewaySettings.prototype._setGatewayDefaults = function(gateway) {
const sequenceFlows = gateway.outgoing.filter(isSequenceFlow);

const defaultFlow = getDefaultFlow(gateway);
const nonDefaultFlows = without(sequenceFlows, defaultFlow);

this._setActiveOutgoing(gateway, nonDefaultFlows);
};

InclusiveGatewaySettings.prototype._resetGateway = function(gateway) {
this._setActiveOutgoing(gateway, undefined);
};

InclusiveGatewaySettings.$inject = [
'eventBus',
'elementRegistry',
'elementColors',
'simulator',
'simulationStyles'
];

function getDefaultFlow(gateway) {
const defaultFlow = getBusinessObject(gateway).default;

if (!defaultFlow) {
return;
}

return gateway.outgoing.find(flow => {
const flowBo = getBusinessObject(flow);

return flowBo === defaultFlow;
});
}

function getNonDefaultFlows(gateway) {
const defaultFlow = getDefaultFlow(gateway);

return gateway.outgoing.filter(flow => {
const flowBo = getBusinessObject(flow);

return flowBo !== defaultFlow;
});
}

function without(array, element) {
return array.filter(arrayElement => arrayElement !== element);
}
11 changes: 11 additions & 0 deletions lib/features/inclusive-gateway-settings/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import InclusiveGatewaySettings from './InclusiveGatewaySettings';
import ElementColorsModule from '../element-colors';
import SimulationStylesModule from '../simulation-styles';

export default {
__depends__: [
ElementColorsModule,
SimulationStylesModule
],
inclusiveGatewaySettings: [ 'type', InclusiveGatewaySettings ]
};

0 comments on commit 77f7d3a

Please sign in to comment.