test(custom-elements): add integration tests for custom elements
Closes #352
This commit is contained in:
parent
857454bbc1
commit
1295400fe0
|
@ -1,15 +1,18 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var is = require('../../util/ModelUtil').is;
|
||||||
|
|
||||||
function getLabelAttr(semantic) {
|
function getLabelAttr(semantic) {
|
||||||
if (semantic.$instanceOf('bpmn:FlowElement') ||
|
if (is(semantic, 'bpmn:FlowElement') ||
|
||||||
semantic.$instanceOf('bpmn:Participant') ||
|
is(semantic, 'bpmn:Participant') ||
|
||||||
semantic.$instanceOf('bpmn:Lane') ||
|
is(semantic, 'bpmn:Lane') ||
|
||||||
semantic.$instanceOf('bpmn:SequenceFlow') ||
|
is(semantic, 'bpmn:SequenceFlow') ||
|
||||||
semantic.$instanceOf('bpmn:MessageFlow')) {
|
is(semantic, 'bpmn:MessageFlow')) {
|
||||||
|
|
||||||
return 'name';
|
return 'name';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (semantic.$instanceOf('bpmn:TextAnnotation')) {
|
if (is(semantic, 'bpmn:TextAnnotation')) {
|
||||||
return 'text';
|
return 'text';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
var assign = require('lodash/object/assign');
|
var assign = require('lodash/object/assign');
|
||||||
|
|
||||||
|
var is = require('./ModelUtil').is;
|
||||||
|
|
||||||
var DEFAULT_LABEL_SIZE = module.exports.DEFAULT_LABEL_SIZE = {
|
var DEFAULT_LABEL_SIZE = module.exports.DEFAULT_LABEL_SIZE = {
|
||||||
width: 90,
|
width: 90,
|
||||||
|
@ -16,17 +17,12 @@ var DEFAULT_LABEL_SIZE = module.exports.DEFAULT_LABEL_SIZE = {
|
||||||
* @return {Boolean} true if has label
|
* @return {Boolean} true if has label
|
||||||
*/
|
*/
|
||||||
module.exports.hasExternalLabel = function(semantic) {
|
module.exports.hasExternalLabel = function(semantic) {
|
||||||
// custom elements
|
return is(semantic, 'bpmn:Event') ||
|
||||||
if (typeof semantic.$instanceOf !== 'function') {
|
is(semantic, 'bpmn:Gateway') ||
|
||||||
return false;
|
is(semantic, 'bpmn:DataStoreReference') ||
|
||||||
}
|
is(semantic, 'bpmn:DataObjectReference') ||
|
||||||
|
is(semantic, 'bpmn:SequenceFlow') ||
|
||||||
return semantic.$instanceOf('bpmn:Event') ||
|
is(semantic, 'bpmn:MessageFlow');
|
||||||
semantic.$instanceOf('bpmn:Gateway') ||
|
|
||||||
semantic.$instanceOf('bpmn:DataStoreReference') ||
|
|
||||||
semantic.$instanceOf('bpmn:DataObjectReference') ||
|
|
||||||
semantic.$instanceOf('bpmn:SequenceFlow') ||
|
|
||||||
semantic.$instanceOf('bpmn:MessageFlow');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +32,7 @@ module.exports.hasExternalLabel = function(semantic) {
|
||||||
* @param {Array<Point>} waypoints
|
* @param {Array<Point>} waypoints
|
||||||
* @return {Point} the mid point
|
* @return {Point} the mid point
|
||||||
*/
|
*/
|
||||||
var getWaypointsMid = module.exports.getWaypointsMid = function(waypoints) {
|
function getWaypointsMid(waypoints) {
|
||||||
|
|
||||||
var mid = waypoints.length / 2 - 1;
|
var mid = waypoints.length / 2 - 1;
|
||||||
|
|
||||||
|
@ -47,10 +43,12 @@ var getWaypointsMid = module.exports.getWaypointsMid = function(waypoints) {
|
||||||
x: first.x + (second.x - first.x) / 2,
|
x: first.x + (second.x - first.x) / 2,
|
||||||
y: first.y + (second.y - first.y) / 2
|
y: first.y + (second.y - first.y) / 2
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
|
module.exports.getWaypointsMid = getWaypointsMid;
|
||||||
|
|
||||||
|
|
||||||
var getExternalLabelMid = module.exports.getExternalLabelMid = function(element) {
|
function getExternalLabelMid(element) {
|
||||||
|
|
||||||
if (element.waypoints) {
|
if (element.waypoints) {
|
||||||
return getWaypointsMid(element.waypoints);
|
return getWaypointsMid(element.waypoints);
|
||||||
|
@ -60,7 +58,10 @@ var getExternalLabelMid = module.exports.getExternalLabelMid = function(element)
|
||||||
y: element.y + element.height + DEFAULT_LABEL_SIZE.height / 2
|
y: element.y + element.height + DEFAULT_LABEL_SIZE.height / 2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
module.exports.getExternalLabelMid = getExternalLabelMid;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bounds of an elements label, parsed from the elements DI or
|
* Returns the bounds of an elements label, parsed from the elements DI or
|
||||||
|
|
|
@ -192,6 +192,7 @@ function inject(fn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports.bootstrapBpmnJS = (window || global).bootstrapBpmnJS = bootstrapBpmnJS;
|
||||||
module.exports.bootstrapModeler = (window || global).bootstrapModeler = bootstrapModeler;
|
module.exports.bootstrapModeler = (window || global).bootstrapModeler = bootstrapModeler;
|
||||||
module.exports.bootstrapViewer = (window || global).bootstrapViewer = bootstrapViewer;
|
module.exports.bootstrapViewer = (window || global).bootstrapViewer = bootstrapViewer;
|
||||||
module.exports.inject = (window || global).inject = inject;
|
module.exports.inject = (window || global).inject = inject;
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* global bootstrapModeler, inject */
|
||||||
|
|
||||||
|
var Modeler = require('../../lib/Modeler');
|
||||||
|
|
||||||
|
var canvasEvent = require('../util/MockEvents').createCanvasEvent;
|
||||||
|
|
||||||
|
|
||||||
|
var customElementsModules = require('./custom-elements'),
|
||||||
|
noTouchInteractionModule = { touchInteractionEvents: ['value', null ]},
|
||||||
|
modelerModules = Modeler.prototype._modules,
|
||||||
|
customModules = [ customElementsModules, noTouchInteractionModule ];
|
||||||
|
|
||||||
|
var testModules = [].concat(modelerModules, customModules);
|
||||||
|
|
||||||
|
|
||||||
|
describe('custom elements', function() {
|
||||||
|
|
||||||
|
var diagramXML = require('../fixtures/bpmn/simple.bpmn');
|
||||||
|
|
||||||
|
beforeEach(bootstrapModeler(diagramXML, {
|
||||||
|
modules: testModules
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('renderer', function () {
|
||||||
|
|
||||||
|
var triangle, circle;
|
||||||
|
|
||||||
|
beforeEach(inject(function(elementFactory, canvas) {
|
||||||
|
triangle = elementFactory.createShape({
|
||||||
|
id: 'triangle',
|
||||||
|
type: 'custom:triangle',
|
||||||
|
x: 700, y: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.addShape(triangle);
|
||||||
|
|
||||||
|
circle = elementFactory.createShape({
|
||||||
|
id: 'circle',
|
||||||
|
type: 'custom:circle',
|
||||||
|
x: 800, y: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.addShape(circle);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should render custom elements', inject(function(elementRegistry) {
|
||||||
|
// when
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(elementRegistry.get('triangle')).to.eql(triangle);
|
||||||
|
expect(elementRegistry.get('circle')).to.eql(circle);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should get the correct custom elements path', inject(function(graphicsFactory) {
|
||||||
|
// when
|
||||||
|
var trianglePath = graphicsFactory.getShapePath(triangle),
|
||||||
|
circlePath = graphicsFactory.getShapePath(circle);
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(trianglePath).to.equal('M720,100l20,40l-40,0z');
|
||||||
|
expect(circlePath).to.equal('M870,170m0,-70a70,70,0,1,1,0,140a70,70,0,1,1,0,-140z');
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should still render bpmn elements', inject(function(elementFactory) {
|
||||||
|
// when
|
||||||
|
var startEvent = elementFactory.createShape({ type: 'bpmn:StartEvent' });
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(startEvent.businessObject.$type).to.equal('bpmn:StartEvent');
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('integration', function () {
|
||||||
|
|
||||||
|
var triangle, circle;
|
||||||
|
|
||||||
|
beforeEach(inject(function(elementFactory, canvas) {
|
||||||
|
|
||||||
|
circle = elementFactory.createShape({
|
||||||
|
id: 'circle',
|
||||||
|
type: 'custom:circle',
|
||||||
|
x: 800, y: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.addShape(circle);
|
||||||
|
|
||||||
|
triangle = elementFactory.createShape({
|
||||||
|
id: 'triangle',
|
||||||
|
type: 'custom:triangle',
|
||||||
|
x: 700, y: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.addShape(triangle);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should allow moving a custom shape inside another one',
|
||||||
|
inject(function(elementFactory, elementRegistry, dragging, move) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var circleGfx = elementRegistry.getGraphics(circle);
|
||||||
|
|
||||||
|
// when
|
||||||
|
move.start(canvasEvent({ x: 0, y: 0 }), triangle);
|
||||||
|
|
||||||
|
dragging.move(canvasEvent({ x: 100, y: 0 }));
|
||||||
|
dragging.hover({ element: circle, gfx: circleGfx });
|
||||||
|
dragging.move(canvasEvent({ x: 150, y: 50 }));
|
||||||
|
|
||||||
|
dragging.end();
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(triangle.parent).to.equal(circle);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should update the custom shape properties',
|
||||||
|
inject(function(elementFactory, elementRegistry, dragging, move) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var circleGfx = elementRegistry.getGraphics(circle);
|
||||||
|
|
||||||
|
// when
|
||||||
|
move.start(canvasEvent({ x: 0, y: 0 }), triangle);
|
||||||
|
|
||||||
|
dragging.move(canvasEvent({ x: 100, y: 0 }));
|
||||||
|
dragging.hover({ element: circle, gfx: circleGfx });
|
||||||
|
dragging.move(canvasEvent({ x: 150, y: 50 }));
|
||||||
|
|
||||||
|
dragging.end();
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(triangle.businessObject.leader).to.equal(circle);
|
||||||
|
expect(circle.businessObject.companions).to.include(triangle);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should connect a bpmn element to a custom one',
|
||||||
|
inject(function(elementFactory, dragging, elementRegistry, connect) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var subProcess = elementRegistry.get('SubProcess_1'),
|
||||||
|
triangleGfx = elementRegistry.getGraphics(triangle);
|
||||||
|
|
||||||
|
// when
|
||||||
|
connect.start(canvasEvent({ x: 590, y: 90 }), subProcess);
|
||||||
|
|
||||||
|
dragging.move(canvasEvent({ x: 700, y: 100 }));
|
||||||
|
dragging.hover({ element: triangle, gfx: triangleGfx });
|
||||||
|
dragging.move(canvasEvent({ x: 715, y: 115 }));
|
||||||
|
|
||||||
|
dragging.end();
|
||||||
|
|
||||||
|
var connection = triangle.incoming[0];
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(connection.type).to.equal('bpmn:Association');
|
||||||
|
expect(connection.source).to.equal(subProcess);
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,77 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var assign = require('lodash/object/assign'),
|
||||||
|
inherits = require('inherits');
|
||||||
|
|
||||||
|
var BpmnElementFactory = require('../../../lib/features/modeling/ElementFactory'),
|
||||||
|
LabelUtil = require('../../../lib/util/LabelUtil');
|
||||||
|
|
||||||
|
|
||||||
|
function CustomElementFactory(bpmnFactory, moddle) {
|
||||||
|
BpmnElementFactory.call(this, bpmnFactory, moddle);
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.create = function(elementType, attrs) {
|
||||||
|
var type = attrs.type,
|
||||||
|
businessObject,
|
||||||
|
size;
|
||||||
|
|
||||||
|
if (elementType === 'label') {
|
||||||
|
return self.baseCreate(elementType, assign({ type: 'label' }, LabelUtil.DEFAULT_LABEL_SIZE, attrs));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^custom\:/.test(type)) {
|
||||||
|
type = attrs.type.replace(/^custom\:/, '');
|
||||||
|
|
||||||
|
businessObject = {};
|
||||||
|
|
||||||
|
size = self._getCustomElementSize(type);
|
||||||
|
|
||||||
|
return self.baseCreate(elementType,
|
||||||
|
assign({ type: elementType, businessObject: businessObject }, attrs, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.createBpmnElement(elementType, attrs);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(CustomElementFactory, BpmnElementFactory);
|
||||||
|
|
||||||
|
module.exports = CustomElementFactory;
|
||||||
|
|
||||||
|
CustomElementFactory.$inject = [ 'bpmnFactory', 'moddle' ];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the *width* and *height* for custom shapes.
|
||||||
|
*
|
||||||
|
* The following example shows an interface on how
|
||||||
|
* to setup the custom element's dimensions.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* var shapes = {
|
||||||
|
* triangle: { width: 40, height: 40 },
|
||||||
|
* rectangle: { width: 100, height: 20 }
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* return shapes[type];
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param {String} type
|
||||||
|
*
|
||||||
|
* @return {Bounds} { width, height}
|
||||||
|
*/
|
||||||
|
CustomElementFactory.prototype._getCustomElementSize = function (type) {
|
||||||
|
if (!type) {
|
||||||
|
return { width: 100, height: 80 };
|
||||||
|
}
|
||||||
|
|
||||||
|
var shapes = {
|
||||||
|
triangle: { width: 40, height: 40 },
|
||||||
|
circle: { width: 140, height: 140 }
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapes[type];
|
||||||
|
};
|
|
@ -0,0 +1,127 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var inherits = require('inherits');
|
||||||
|
|
||||||
|
var BaseRenderer = require('diagram-js/lib/draw/BaseRenderer');
|
||||||
|
|
||||||
|
var componentsToPath = require('diagram-js/lib/util/RenderUtil').componentsToPath;
|
||||||
|
|
||||||
|
|
||||||
|
function CustomRenderer(eventBus, styles) {
|
||||||
|
|
||||||
|
BaseRenderer.call(this, eventBus, 2000);
|
||||||
|
|
||||||
|
this._styles = styles;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var computeStyle = styles.computeStyle;
|
||||||
|
|
||||||
|
this.handlers = {
|
||||||
|
'custom:triangle': function(p, element) {
|
||||||
|
return self.drawTriangle(p, element.width);
|
||||||
|
},
|
||||||
|
'custom:circle': function(p, element, attrs) {
|
||||||
|
return self.drawCircle(p, element.width, element.height, attrs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.drawTriangle = function(p, side, attrs) {
|
||||||
|
var halfSide = side / 2,
|
||||||
|
points;
|
||||||
|
|
||||||
|
points = [ halfSide, 0, side, side, 0, side ];
|
||||||
|
|
||||||
|
attrs = computeStyle(attrs, {
|
||||||
|
stroke: '#3CAA82',
|
||||||
|
strokeWidth: 2,
|
||||||
|
fill: '#3CAA82'
|
||||||
|
});
|
||||||
|
|
||||||
|
return p.polygon(points).attr(attrs);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getTrianglePath = function(element) {
|
||||||
|
var x = element.x,
|
||||||
|
y = element.y,
|
||||||
|
width = element.width,
|
||||||
|
height = element.height;
|
||||||
|
|
||||||
|
var trianglePath = [
|
||||||
|
['M', x + width / 2, y],
|
||||||
|
['l', width / 2, height],
|
||||||
|
['l', -width, 0 ],
|
||||||
|
['z']
|
||||||
|
];
|
||||||
|
|
||||||
|
return componentsToPath(trianglePath);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.drawCircle = function(p, width, height, attrs) {
|
||||||
|
var cx = width / 2,
|
||||||
|
cy = height / 2;
|
||||||
|
|
||||||
|
attrs = computeStyle(attrs, {
|
||||||
|
stroke: '#4488aa',
|
||||||
|
strokeWidth: 4,
|
||||||
|
fill: 'white'
|
||||||
|
});
|
||||||
|
|
||||||
|
return p.circle(cx, cy, Math.round((width + height) / 4)).attr(attrs);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getCirclePath = function(shape) {
|
||||||
|
var cx = shape.x + shape.width / 2,
|
||||||
|
cy = shape.y + shape.height / 2,
|
||||||
|
radius = shape.width / 2;
|
||||||
|
|
||||||
|
var circlePath = [
|
||||||
|
['M', cx, cy],
|
||||||
|
['m', 0, -radius],
|
||||||
|
['a', radius, radius, 0, 1, 1, 0, 2 * radius],
|
||||||
|
['a', radius, radius, 0, 1, 1, 0, -2 * radius],
|
||||||
|
['z']
|
||||||
|
];
|
||||||
|
|
||||||
|
return componentsToPath(circlePath);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(CustomRenderer, BaseRenderer);
|
||||||
|
|
||||||
|
module.exports = CustomRenderer;
|
||||||
|
|
||||||
|
CustomRenderer.$inject = [ 'eventBus', 'styles' ];
|
||||||
|
|
||||||
|
|
||||||
|
CustomRenderer.prototype.canRender = function(element) {
|
||||||
|
return /^custom\:/.test(element.type);
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomRenderer.prototype.drawShape = function(visuals, element) {
|
||||||
|
var type = element.type;
|
||||||
|
var h = this.handlers[type];
|
||||||
|
|
||||||
|
/* jshint -W040 */
|
||||||
|
return h(visuals, element);
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomRenderer.prototype.drawConnection = function(visuals, element) {
|
||||||
|
var type = element.type;
|
||||||
|
var h = this.handlers[type];
|
||||||
|
|
||||||
|
/* jshint -W040 */
|
||||||
|
return h(visuals, element);
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomRenderer.prototype.getShapePath = function(element) {
|
||||||
|
var type = element.type.replace(/^custom\:/, '');
|
||||||
|
|
||||||
|
var shapes = {
|
||||||
|
triangle: this.getTrianglePath,
|
||||||
|
circle: this.getCirclePath
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapes[type](element);
|
||||||
|
};
|
|
@ -0,0 +1,148 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var forEach = require('lodash/collection/forEach'),
|
||||||
|
inherits = require('inherits');
|
||||||
|
|
||||||
|
var RuleProvider = require('diagram-js/lib/features/rules/RuleProvider');
|
||||||
|
|
||||||
|
var HIGH_PRIORITY = 1500;
|
||||||
|
|
||||||
|
|
||||||
|
function isType(element, type) {
|
||||||
|
var patt = new RegExp(type, 'i');
|
||||||
|
|
||||||
|
return element && patt.test(element.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCustom(element) {
|
||||||
|
return element && /^custom\:/.test(element.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific rules for custom elements
|
||||||
|
*/
|
||||||
|
function CustomRules(eventBus) {
|
||||||
|
RuleProvider.call(this, eventBus);
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(CustomRules, RuleProvider);
|
||||||
|
|
||||||
|
CustomRules.$inject = [ 'eventBus' ];
|
||||||
|
|
||||||
|
module.exports = CustomRules;
|
||||||
|
|
||||||
|
|
||||||
|
CustomRules.prototype.init = function() {
|
||||||
|
|
||||||
|
this.addRule('connection.create', HIGH_PRIORITY, function(context) {
|
||||||
|
var source = context.source,
|
||||||
|
target = context.target;
|
||||||
|
|
||||||
|
return canConnect(source, target);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addRule('connection.reconnectStart', HIGH_PRIORITY, function(context) {
|
||||||
|
|
||||||
|
var connection = context.connection,
|
||||||
|
source = context.hover || context.source,
|
||||||
|
target = connection.target;
|
||||||
|
|
||||||
|
return canConnect(source, target, connection);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addRule('connection.reconnectEnd', HIGH_PRIORITY, function(context) {
|
||||||
|
|
||||||
|
var connection = context.connection,
|
||||||
|
source = connection.source,
|
||||||
|
target = context.hover || context.target;
|
||||||
|
|
||||||
|
return canConnect(source, target, connection);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addRule('connection.updateWaypoints', HIGH_PRIORITY, function(context) {
|
||||||
|
// OK! but visually ignore
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addRule('elements.move', HIGH_PRIORITY, function(context) {
|
||||||
|
|
||||||
|
var target = context.target,
|
||||||
|
shapes = context.shapes,
|
||||||
|
position = context.position;
|
||||||
|
|
||||||
|
return canMove(shapes, target, position);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addRule('shape.create', HIGH_PRIORITY, function(context) {
|
||||||
|
var target = context.target,
|
||||||
|
shape = context.shape,
|
||||||
|
position = context.position;
|
||||||
|
|
||||||
|
return canCreate(shape, target, position);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addRule('shape.resize', HIGH_PRIORITY, function(context) {
|
||||||
|
var shape = context.shape;
|
||||||
|
|
||||||
|
if (isCustom(shape)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function canConnect(source, target) {
|
||||||
|
if (isType(target, 'custom:triangle')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isType(target, 'custom:circle')) {
|
||||||
|
if (isType(source, 'custom:triangle')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCustom(source)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function canCreate(shape, target) {
|
||||||
|
if (isType(target, 'custom:triangle')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isType(target, 'custom:circle')) {
|
||||||
|
if (isType(shape, 'custom:triangle')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCustom(shape)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function canMove(shapes, target, position) {
|
||||||
|
var result;
|
||||||
|
|
||||||
|
forEach(shapes, function(shape) {
|
||||||
|
if (isType(shape, 'custom:triangle') && isType(target, 'custom:circle')) {
|
||||||
|
result = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCustom(target)) {
|
||||||
|
result = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCustom(shape)) {
|
||||||
|
result = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var inherits = require('inherits');
|
||||||
|
|
||||||
|
var isBpmn = require('../../../lib/util/ModelUtil').is;
|
||||||
|
|
||||||
|
var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor');
|
||||||
|
|
||||||
|
|
||||||
|
function isCustom(element, type) {
|
||||||
|
return element && element.type === type;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ifCustomElement(fn) {
|
||||||
|
return function(event) {
|
||||||
|
var context = event.context,
|
||||||
|
element = context.shape || context.connection;
|
||||||
|
|
||||||
|
if (!isBpmn(element, 'bpmn:BaseElement')) {
|
||||||
|
fn(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A handler responsible for updating the custom element's businessObject
|
||||||
|
* once changes on the diagram happen
|
||||||
|
*/
|
||||||
|
function CustomUpdater(eventBus, bpmnFactory, connectionDocking) {
|
||||||
|
|
||||||
|
CommandInterceptor.call(this, eventBus);
|
||||||
|
|
||||||
|
function updateTriangle(evt) {
|
||||||
|
var context = evt.context,
|
||||||
|
shape = context.shape,
|
||||||
|
businessObject = shape.businessObject,
|
||||||
|
leader = businessObject.leader,
|
||||||
|
companions,
|
||||||
|
parent,
|
||||||
|
idx;
|
||||||
|
|
||||||
|
if (!isCustom(shape, 'custom:triangle')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = shape.parent;
|
||||||
|
|
||||||
|
if (!parent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBpmn(parent, 'bpmn:SubProcess')) {
|
||||||
|
shape.businessObject.foo = 'geil';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isBpmn(parent, 'bpmn:SubProcess')) {
|
||||||
|
shape.businessObject.foo = 'bar';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCustom(parent, 'custom:circle')) {
|
||||||
|
shape.businessObject.leader = parent;
|
||||||
|
|
||||||
|
if (!parent.businessObject.companions) {
|
||||||
|
parent.businessObject.companions = [];
|
||||||
|
}
|
||||||
|
parent.businessObject.companions.push(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCustom(parent, 'custom:circle') && leader) {
|
||||||
|
companions = leader.businessObject.companions;
|
||||||
|
|
||||||
|
idx = companions.indexOf(shape);
|
||||||
|
|
||||||
|
companions.splice(idx, 1);
|
||||||
|
|
||||||
|
businessObject.leader = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.executed([
|
||||||
|
'shape.move',
|
||||||
|
'shape.create'
|
||||||
|
], ifCustomElement(updateTriangle));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(CustomUpdater, CommandInterceptor);
|
||||||
|
|
||||||
|
module.exports = CustomUpdater;
|
||||||
|
|
||||||
|
CustomUpdater.$inject = [ 'eventBus' ];
|
|
@ -0,0 +1,7 @@
|
||||||
|
module.exports = {
|
||||||
|
__init__: [ 'customRenderer', 'customRules', 'customUpdater' ],
|
||||||
|
elementFactory: [ 'type', require('./CustomElementFactory') ],
|
||||||
|
customRenderer: [ 'type', require('./CustomRenderer') ],
|
||||||
|
customRules: [ 'type', require('./CustomRules') ],
|
||||||
|
customUpdater: [ 'type', require('./CustomUpdater') ]
|
||||||
|
};
|
Loading…
Reference in New Issue