I’m trying to create a custom bpmn
This component should have the same behavior as the default bpmn
, but it will be thicker and a different color. I followed what I found in the documentation and managed to create this line, but its behavior is not like a bpmn
. Can someone help? Here’s the code I created:
CustomPalette:
'
'create.custom-connection': {
group: 'connect',
className: 'bpmn-icon-connection',
title: translate('Create Custom Connection'),
action: {
dragstart: createCustomConnection,
click: createCustomConnection
}
},
...
function createCustomConnection(event) {
const businessObject = moddle.create('tubo:TuboConnection', {
type: 'tubo:TuboConnection',
diameter: '10mm',
length: '100m'
});
const customConnection = elementFactory.create('connection', {
type: 'tubo:TuboConnection',
businessObject,
source: null,
target: null
});
create.start(event, customConnection);
}
Index.js:
export default {
__init__: ['customContextPad', 'customPalette', 'customRenderer', 'customTuboRenderer', 'customRules', 'customCommandInterceptor'],
customContextPad: ['type', CustomContextPad],
customPalette: ['type', CustomPalette],
customRenderer: ['type', CustomRenderer],
customRules: ['type', CustomRules],
customTuboRenderer: ['type', CustomTuboRenderer],
customCommandInterceptor: ['type', CustomCommandInterceptor],
};
CustomRenderer:
import inherits from 'inherits';
import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
import { is } from 'bpmn-js/lib/util/ModelUtil';
import { append as svgAppend, create as svgCreate } from 'tiny-svg';
const HIGH_PRIORITY = 1500;
export default function CustomTuboRenderer(eventBus, bpmnRenderer) {
BaseRenderer.call(this, eventBus, HIGH_PRIORITY);
this.bpmnRenderer = bpmnRenderer;
this.canRender = function(element) {
const result = is(element, 'tubo:TuboConnection');
console.log('Checking if can render:', element, result);
return result;
};
this.drawCustomConnection = function(visuals, element) {
if (!element.waypoints || element.waypoints.length === 0) {
// Defina waypoints padrão se não estiverem definidos
element.waypoints = [
{ x: element.x, y: element.y },
{ x: element.x + 100, y: element.y + 100 }
];
}
if (!element.waypoints || element.waypoints.length < 2) {
console.error('Waypoints are not defined correctly.');
return;
}
console.log('Drawing custom connection:', element);
const line = svgCreate('line');
svgAppend(visuals, line);
const waypoints = element.waypoints;
line.setAttribute('x1', waypoints[0].x);
line.setAttribute('y1', waypoints[0].y);
line.setAttribute('x2', waypoints[1].x);
line.setAttribute('y2', waypoints[1].y);
line.setAttribute('stroke', '#ff0000'); // Definindo a cor da linha para vermelho
line.setAttribute('stroke-width', 7.5); // Espessura da linha
return line;
};
this.drawShape = function(visuals, element) {
console.log('Drawing shape:', element);
if (this.canRender(element)) {
console.log('Rendering custom connection:', element);
return this.drawCustomConnection(visuals, element);
}
return this.bpmnRenderer.drawShape(visuals, element);
};
}
inherits(CustomTuboRenderer, BaseRenderer);
CustomTuboRenderer.$inject = ['eventBus', 'bpmnRenderer'];
CustomRules.js
export default function CustomRules(eventBus) {
eventBus.on('commandStack.connection.create.canExecute', (context) => {
const { source, target, connection } = context;
if (connection.type === 'tubo:TuboConnection') {
// Permitir conexão entre tarefas e outros elementos BPMN
if (source.type === 'bpmn:Task' && target.type === 'bpmn:Task') {
return true;
}
}
});
}
CustomRules.$inject = ['eventBus'];
CustomCommandInterveptor:
import inherits from 'inherits';
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
import { assign } from 'min-dash';
export default function CustomCommandInterceptor(eventBus) {
CommandInterceptor.call(this, eventBus);
this.preExecute(["connection.create"], function(context) {
var connection = context.connection;
if (connection.type === 'tubo:TuboConnection') {
![imagem-linha|1365x396](upload://gl7kD5IWgP7LZlWuh0ccRNtdHsR.png)
assign(connection, {
businessObject: {
$type: 'tubo:TuboConnection'
}
});
}
}, true);
}
inherits(CustomCommandInterceptor, CommandInterceptor);
CustomCommandInterceptor.$inject = ['eventBus'];
As you can see in the image, when dragging the arrow to the diagram, it does not allow adding and does not allow connecting one component to another like a standard TextAnnotation. Any help is welcome, I have been researching and trying to create this for weeks. Is there any limitation to this behavior? Is it possible, has anyone done something like this and can share or help? Thank you in advance.
The descritor:
{
"name": "Custom BPMN",
"uri": "http://example.com/custom-bpmn",
"prefix": "tubo",
"types": [
{
"name": "TuboConnection",
"superClass": ["bpmn:SequenceFlow"],
"properties": [
{
"name": "diameter",
"isAttr": true,
"type": "String"
},
{
"name": "length",
"isAttr": true,
"type": "String"
}
]
}
]
}