Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/bpmn-support.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ The default rendering uses `white` as fill color and `black` as stroke color.
|Comments

|Exclusive
|
|icon:check-circle-o[]
|

|Parallel
Expand Down
2 changes: 2 additions & 0 deletions src/component/mxgraph/ShapeConfigurator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { MxGraphFactoryService } from '../../service/MxGraphFactoryService';
import { mxgraph } from 'ts-mxgraph';
import { ShapeBpmnElementKind } from '../../model/bpmn/shape/ShapeBpmnElementKind';
import { EndEventShape, StartEventShape } from './shape/event-shapes';
import { ExclusiveGatewayShape } from './shape/gateway-shapes';
import { TaskShape } from './shape/task-shapes';

export default class ShapeConfigurator {
Expand All @@ -32,6 +33,7 @@ export default class ShapeConfigurator {
private registerShapes(): void {
this.mxCellRenderer.registerShape(ShapeBpmnElementKind.EVENT_END, EndEventShape);
this.mxCellRenderer.registerShape(ShapeBpmnElementKind.EVENT_START, StartEventShape);
this.mxCellRenderer.registerShape(ShapeBpmnElementKind.GATEWAY_EXCLUSIVE, ExclusiveGatewayShape);
this.mxCellRenderer.registerShape(ShapeBpmnElementKind.TASK, TaskShape);
}

Expand Down
22 changes: 17 additions & 5 deletions src/component/mxgraph/StyleConfigurator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ export default class StyleConfigurator {
this.configureServiceTaskStyle();
this.configureTaskStyle();
// gateways
this.configureGatewaysStyle();
this.configureParallelGatewayStyle();
this.configureExclusiveGatewayStyle();
}

private getStylesheet(): any {
Expand Down Expand Up @@ -133,6 +133,8 @@ export default class StyleConfigurator {
this.putCellStyle(ShapeBpmnElementKind.TASK, style);
}

// TODO: to be removed as it will be configured in configureGatewaysStyle
// left just to not break current rendering
private configureParallelGatewayStyle(): void {
const style = this.cloneDefaultVertexStyle();
style[this.mxConstants.STYLE_SHAPE] = this.mxConstants.SHAPE_RHOMBUS;
Expand All @@ -147,9 +149,19 @@ export default class StyleConfigurator {
this.putCellStyle(ShapeBpmnElementKind.GATEWAY_PARALLEL, style);
}

private configureExclusiveGatewayStyle(): void {
const style = this.mxUtils.clone(this.getStylesheet().getCellStyle(ShapeBpmnElementKind.GATEWAY_PARALLEL), this.getDefaultVertexStyle());
style[this.mxConstants.STYLE_GRADIENTCOLOR] = '#DDA0DD';
this.putCellStyle(ShapeBpmnElementKind.GATEWAY_EXCLUSIVE, style);
private configureGatewaysStyle(): void {
ShapeUtil.gatewayKinds().forEach(kind => {
const style = this.cloneDefaultVertexStyle();
style[this.mxConstants.STYLE_SHAPE] = kind;
style[this.mxConstants.STYLE_PERIMETER] = this.mxPerimeter.RhombusPerimeter;
style[this.mxConstants.STYLE_VERTICAL_ALIGN] = 'top';

// TODO to be removed when supporting label position
// left just to not break current rendering
style[this.mxConstants.STYLE_SPACING_TOP] = 55;
style[this.mxConstants.STYLE_SPACING_RIGHT] = 110;

this.putCellStyle(kind, style);
});
}
}
80 changes: 80 additions & 0 deletions src/component/mxgraph/shape/gateway-shapes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Copyright 2020 Bonitasoft S.A.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { MxGraphFactoryService } from '../../../service/MxGraphFactoryService';
import { mxgraph } from 'ts-mxgraph';
import { StyleConstant } from '../StyleConfigurator';

const mxRhombus: typeof mxgraph.mxRhombus = MxGraphFactoryService.getMxGraphProperty('mxRhombus');
const mxUtils: typeof mxgraph.mxUtils = MxGraphFactoryService.getMxGraphProperty('mxUtils');
const mxConstants: typeof mxgraph.mxConstants = MxGraphFactoryService.getMxGraphProperty('mxConstants');

abstract class GatewayShape extends mxRhombus {
protected constructor(bounds: mxgraph.mxRectangle, fill: string, stroke: string, strokewidth: number) {
super(bounds, fill, stroke, strokewidth);
}

public paintVertexShape(c: mxgraph.mxXmlCanvas2D, x: number, y: number, w: number, h: number): void {
this.paintOuterShape(c, x, y, w, h);
this.paintInnerShape(c, x, y, w, h);
}

protected paintOuterShape(c: mxgraph.mxXmlCanvas2D, x: number, y: number, w: number, h: number): void {
super.paintVertexShape(c, x, y, w, h);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
protected paintInnerShape(c: mxgraph.mxXmlCanvas2D, x: number, y: number, w: number, h: number): void {
// do nothing by default
}
}

export class ExclusiveGatewayShape extends GatewayShape {
public constructor(bounds: mxgraph.mxRectangle, fill: string, stroke: string, strokewidth: number = StyleConstant.STROKE_WIDTH_THIN) {
super(bounds, fill, stroke, strokewidth);
}

protected paintInnerShape(c: mxgraph.mxXmlCanvas2D, x: number, y: number, w: number, h: number): void {
this.addExclusiveGatewaySymbol(c, x, y, w, h);
}

private addExclusiveGatewaySymbol(c: mxgraph.mxXmlCanvas2D, x: number, y: number, w: number, h: number): void {
const symbolScale = 3 * mxUtils.getValue(this.style, mxConstants.STYLE_MARGIN, Math.min(3 + this.strokewidth, Math.min(w / 5, h / 5)));
x += symbolScale;
y += symbolScale;
w -= 2 * symbolScale;
h -= 2 * symbolScale;
c.setFillColor(this.stroke);
c.setStrokeWidth(0);

c.begin();
c.moveTo(x + w * 0.105, y);
c.lineTo(x + w * 0.5, y + h * 0.38);
c.lineTo(x + w * 0.895, y);
c.lineTo(x + w, y + h * 0.11);
c.lineTo(x + w * 0.6172, y + h * 0.5);
c.lineTo(x + w, y + h * 0.89);
c.lineTo(x + w * 0.895, y + h);
c.lineTo(x + w * 0.5, y + h * 0.62);
c.lineTo(x + w * 0.105, y + h);
c.lineTo(x, y + h * 0.89);
c.lineTo(x + w * 0.3808, y + h * 0.5);
c.lineTo(x, y + h * 0.11);
c.close();

c.fillAndStroke();
}
}
14 changes: 11 additions & 3 deletions src/model/bpmn/shape/ShapeUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ import { ShapeBpmnElementKind } from './ShapeBpmnElementKind';
// TODO move to ShapeBpmnElementKind? and rename into ShapeBpmnElementKindUtil?
// TODO bpmnEventKinds and flowNodeKinds currently hosted in ProcessConverter may be hosted here
export default class ShapeUtil {
private static EVENTS_KIND = Object.values(ShapeBpmnElementKind).filter(kind => {
return kind.endsWith('Event');
});
private static readonly EVENTS_KIND = ShapeUtil.filterKind('Event');
private static readonly GATEWAY_KINDS = ShapeUtil.filterKind('Gateway');

private static filterKind(suffix: string): ShapeBpmnElementKind[] {
return Object.values(ShapeBpmnElementKind).filter(kind => {
return kind.endsWith(suffix);
});
}

public static isEvent(kind: ShapeBpmnElementKind): boolean {
return this.EVENTS_KIND.includes(kind);
Expand All @@ -31,4 +36,7 @@ export default class ShapeUtil {
public static topLevelBpmnEventKinds(): ShapeBpmnElementKind[] {
return this.EVENTS_KIND;
}
public static gatewayKinds(): ShapeBpmnElementKind[] {
return this.GATEWAY_KINDS;
}
}
1 change: 1 addition & 0 deletions src/service/MxGraphFactoryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type MxGraphProperty =
| 'mxClient'
| 'mxConstants'
| 'mxEllipse'
| 'mxRhombus'
| 'mxRectangleShape'
| 'mxGeometry'
| 'mxGraph'
Expand Down