Merge branch 'develop'
This commit is contained in:
commit
0a377250bb
|
@ -6,6 +6,13 @@ All notable changes to [bpmn-js](https://github.com/bpmn-io/bpmn-js) are documen
|
||||||
|
|
||||||
___Note:__ Yet to be released changes appear here._
|
___Note:__ Yet to be released changes appear here._
|
||||||
|
|
||||||
|
## 6.5.0
|
||||||
|
|
||||||
|
* `FEAT`: prefer straight layout for sub-process connections ([#1309](https://github.com/bpmn-io/bpmn-js/pull/1309))
|
||||||
|
* `FEAT`: move common auto-place feature to diagram-js, add BPMN-specific auto-place feature ([#1284](https://github.com/bpmn-io/bpmn-js/pull/1284))
|
||||||
|
* `CHORE`: make bpmn-font a development dependency ([`63045bdf`](https://github.com/bpmn-io/bpmn-js/commit/63045bdfa87b9f1989a2a7a509facbeb4616acda))
|
||||||
|
* `CHORE`: bump to `diagram-js@6.6.1`
|
||||||
|
|
||||||
## 6.4.2
|
## 6.4.2
|
||||||
|
|
||||||
* `CHORE`: bump to `bpmn-moddle@6.0.5`
|
* `CHORE`: bump to `bpmn-moddle@6.0.5`
|
||||||
|
|
|
@ -12,8 +12,8 @@ import BaseViewer from './BaseViewer';
|
||||||
*
|
*
|
||||||
* @param {Object} [options] configuration options to pass to the viewer
|
* @param {Object} [options] configuration options to pass to the viewer
|
||||||
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
|
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
|
||||||
* @param {String|Number} [options.width] the width of the viewer
|
* @param {string|number} [options.width] the width of the viewer
|
||||||
* @param {String|Number} [options.height] the height of the viewer
|
* @param {string|number} [options.height] the height of the viewer
|
||||||
* @param {Object} [options.moddleExtensions] extension packages to provide
|
* @param {Object} [options.moddleExtensions] extension packages to provide
|
||||||
* @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
|
* @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
|
||||||
* @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
|
* @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
|
||||||
|
|
|
@ -40,8 +40,8 @@ import {
|
||||||
*
|
*
|
||||||
* @param {Object} [options] configuration options to pass to the viewer
|
* @param {Object} [options] configuration options to pass to the viewer
|
||||||
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
|
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
|
||||||
* @param {String|Number} [options.width] the width of the viewer
|
* @param {string|number} [options.width] the width of the viewer
|
||||||
* @param {String|Number} [options.height] the height of the viewer
|
* @param {string|number} [options.height] the height of the viewer
|
||||||
* @param {Object} [options.moddleExtensions] extension packages to provide
|
* @param {Object} [options.moddleExtensions] extension packages to provide
|
||||||
* @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
|
* @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
|
||||||
* @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
|
* @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
|
||||||
|
@ -84,8 +84,8 @@ inherits(BaseViewer, Diagram);
|
||||||
*
|
*
|
||||||
* You can use these events to hook into the life-cycle.
|
* You can use these events to hook into the life-cycle.
|
||||||
*
|
*
|
||||||
* @param {String} xml the BPMN 2.0 xml
|
* @param {string} xml the BPMN 2.0 xml
|
||||||
* @param {ModdleElement<BPMNDiagram>|String} [bpmnDiagram] BPMN diagram or id of diagram to render (if not provided, the first one will be rendered)
|
* @param {ModdleElement<BPMNDiagram>|string} [bpmnDiagram] BPMN diagram or id of diagram to render (if not provided, the first one will be rendered)
|
||||||
* @param {Function} [done] invoked with (err, warnings=[])
|
* @param {Function} [done] invoked with (err, warnings=[])
|
||||||
*/
|
*/
|
||||||
BaseViewer.prototype.importXML = function(xml, bpmnDiagram, done) {
|
BaseViewer.prototype.importXML = function(xml, bpmnDiagram, done) {
|
||||||
|
@ -150,7 +150,7 @@ BaseViewer.prototype.importXML = function(xml, bpmnDiagram, done) {
|
||||||
* You can use these events to hook into the life-cycle.
|
* You can use these events to hook into the life-cycle.
|
||||||
*
|
*
|
||||||
* @param {ModdleElement<Definitions>} definitions parsed BPMN 2.0 definitions
|
* @param {ModdleElement<Definitions>} definitions parsed BPMN 2.0 definitions
|
||||||
* @param {ModdleElement<BPMNDiagram>|String} [bpmnDiagram] BPMN diagram or id of diagram to render (if not provided, the first one will be rendered)
|
* @param {ModdleElement<BPMNDiagram>|string} [bpmnDiagram] BPMN diagram or id of diagram to render (if not provided, the first one will be rendered)
|
||||||
* @param {Function} [done] invoked with (err, warnings=[])
|
* @param {Function} [done] invoked with (err, warnings=[])
|
||||||
*/
|
*/
|
||||||
BaseViewer.prototype.importDefinitions = function(definitions, bpmnDiagram, done) {
|
BaseViewer.prototype.importDefinitions = function(definitions, bpmnDiagram, done) {
|
||||||
|
@ -183,7 +183,7 @@ BaseViewer.prototype.importDefinitions = function(definitions, bpmnDiagram, done
|
||||||
*
|
*
|
||||||
* You can use these events to hook into the life-cycle.
|
* You can use these events to hook into the life-cycle.
|
||||||
*
|
*
|
||||||
* @param {String|ModdleElement<BPMNDiagram>} [bpmnDiagramOrId] id or the diagram to open
|
* @param {string|ModdleElement<BPMNDiagram>} [bpmnDiagramOrId] id or the diagram to open
|
||||||
* @param {Function} [done] invoked with (err, warnings=[])
|
* @param {Function} [done] invoked with (err, warnings=[])
|
||||||
*/
|
*/
|
||||||
BaseViewer.prototype.open = function(bpmnDiagramOrId, done) {
|
BaseViewer.prototype.open = function(bpmnDiagramOrId, done) {
|
||||||
|
@ -238,8 +238,8 @@ BaseViewer.prototype.open = function(bpmnDiagramOrId, done) {
|
||||||
* You can use these events to hook into the life-cycle.
|
* You can use these events to hook into the life-cycle.
|
||||||
*
|
*
|
||||||
* @param {Object} [options] export options
|
* @param {Object} [options] export options
|
||||||
* @param {Boolean} [options.format=false] output formatted XML
|
* @param {boolean} [options.format=false] output formatted XML
|
||||||
* @param {Boolean} [options.preamble=true] output preamble
|
* @param {boolean} [options.preamble=true] output preamble
|
||||||
*
|
*
|
||||||
* @param {Function} done invoked with (err, xml)
|
* @param {Function} done invoked with (err, xml)
|
||||||
*/
|
*/
|
||||||
|
@ -350,7 +350,7 @@ BaseViewer.prototype.saveSVG = function(options, done) {
|
||||||
* var elementRegistry = viewer.get('elementRegistry');
|
* var elementRegistry = viewer.get('elementRegistry');
|
||||||
* var startEventShape = elementRegistry.get('StartEvent_1');
|
* var startEventShape = elementRegistry.get('StartEvent_1');
|
||||||
*
|
*
|
||||||
* @param {String} name
|
* @param {string} name
|
||||||
*
|
*
|
||||||
* @return {Object} diagram service instance
|
* @return {Object} diagram service instance
|
||||||
*
|
*
|
||||||
|
@ -432,8 +432,8 @@ BaseViewer.prototype.destroy = function() {
|
||||||
*
|
*
|
||||||
* Remove a previously added listener via {@link #off(event, callback)}.
|
* Remove a previously added listener via {@link #off(event, callback)}.
|
||||||
*
|
*
|
||||||
* @param {String} event
|
* @param {string} event
|
||||||
* @param {Number} [priority]
|
* @param {number} [priority]
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
* @param {Object} [that]
|
* @param {Object} [that]
|
||||||
*/
|
*/
|
||||||
|
@ -444,7 +444,7 @@ BaseViewer.prototype.on = function(event, priority, callback, target) {
|
||||||
/**
|
/**
|
||||||
* De-register an event listener
|
* De-register an event listener
|
||||||
*
|
*
|
||||||
* @param {String} event
|
* @param {string} event
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
BaseViewer.prototype.off = function(event, callback) {
|
BaseViewer.prototype.off = function(event, callback) {
|
||||||
|
@ -524,7 +524,7 @@ BaseViewer.prototype._init = function(container, moddle, options) {
|
||||||
/**
|
/**
|
||||||
* Emit an event on the underlying {@link EventBus}
|
* Emit an event on the underlying {@link EventBus}
|
||||||
*
|
*
|
||||||
* @param {String} type
|
* @param {string} type
|
||||||
* @param {Object} event
|
* @param {Object} event
|
||||||
*
|
*
|
||||||
* @return {Object} event processing result (if any)
|
* @return {Object} event processing result (if any)
|
||||||
|
@ -593,7 +593,7 @@ function ensureUnit(val) {
|
||||||
* Find BPMNDiagram in definitions by ID
|
* Find BPMNDiagram in definitions by ID
|
||||||
*
|
*
|
||||||
* @param {ModdleElement<Definitions>} definitions
|
* @param {ModdleElement<Definitions>} definitions
|
||||||
* @param {String} diagramId
|
* @param {string} diagramId
|
||||||
*
|
*
|
||||||
* @return {ModdleElement<BPMNDiagram>|null}
|
* @return {ModdleElement<BPMNDiagram>|null}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -123,8 +123,8 @@ var initialDiagram =
|
||||||
*
|
*
|
||||||
* @param {Object} [options] configuration options to pass to the viewer
|
* @param {Object} [options] configuration options to pass to the viewer
|
||||||
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
|
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
|
||||||
* @param {String|Number} [options.width] the width of the viewer
|
* @param {string|number} [options.width] the width of the viewer
|
||||||
* @param {String|Number} [options.height] the height of the viewer
|
* @param {string|number} [options.height] the height of the viewer
|
||||||
* @param {Object} [options.moddleExtensions] extension packages to provide
|
* @param {Object} [options.moddleExtensions] extension packages to provide
|
||||||
* @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
|
* @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
|
||||||
* @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
|
* @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
|
||||||
|
|
|
@ -49,8 +49,8 @@ import BaseViewer from './BaseViewer';
|
||||||
*
|
*
|
||||||
* @param {Object} [options] configuration options to pass to the viewer
|
* @param {Object} [options] configuration options to pass to the viewer
|
||||||
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
|
* @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
|
||||||
* @param {String|Number} [options.width] the width of the viewer
|
* @param {string|number} [options.width] the width of the viewer
|
||||||
* @param {String|Number} [options.height] the height of the viewer
|
* @param {string|number} [options.height] the height of the viewer
|
||||||
* @param {Object} [options.moddleExtensions] extension packages to provide
|
* @param {Object} [options.moddleExtensions] extension packages to provide
|
||||||
* @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
|
* @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
|
||||||
* @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
|
* @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
|
||||||
|
|
|
@ -362,7 +362,7 @@ export default function PathMap() {
|
||||||
* Also there are use cases where only some parts of a path should be
|
* Also there are use cases where only some parts of a path should be
|
||||||
* scaled.</p>
|
* scaled.</p>
|
||||||
*
|
*
|
||||||
* @param {String} pathId The ID of the path.
|
* @param {string} pathId The ID of the path.
|
||||||
* @param {Object} param <p>
|
* @param {Object} param <p>
|
||||||
* Example param object scales the path to 60% size of the container (data.width, data.height).
|
* Example param object scales the path to 60% size of the container (data.width, data.height).
|
||||||
* <pre>
|
* <pre>
|
||||||
|
|
|
@ -32,7 +32,7 @@ export default function TextRenderer(config) {
|
||||||
* layouted label.
|
* layouted label.
|
||||||
*
|
*
|
||||||
* @param {Bounds} bounds
|
* @param {Bounds} bounds
|
||||||
* @param {String} text
|
* @param {string} text
|
||||||
*
|
*
|
||||||
* @return {Bounds}
|
* @return {Bounds}
|
||||||
*/
|
*/
|
||||||
|
@ -62,7 +62,7 @@ export default function TextRenderer(config) {
|
||||||
* Get the new bounds of text annotation.
|
* Get the new bounds of text annotation.
|
||||||
*
|
*
|
||||||
* @param {Bounds} bounds
|
* @param {Bounds} bounds
|
||||||
* @param {String} text
|
* @param {string} text
|
||||||
*
|
*
|
||||||
* @return {Bounds}
|
* @return {Bounds}
|
||||||
*/
|
*/
|
||||||
|
@ -86,7 +86,7 @@ export default function TextRenderer(config) {
|
||||||
/**
|
/**
|
||||||
* Create a layouted text element.
|
* Create a layouted text element.
|
||||||
*
|
*
|
||||||
* @param {String} text
|
* @param {string} text
|
||||||
* @param {Object} [options]
|
* @param {Object} [options]
|
||||||
*
|
*
|
||||||
* @return {SVGElement} rendered text
|
* @return {SVGElement} rendered text
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
import { getNewShapePosition } from './AutoPlaceUtil';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A service that places elements connected to existing ones
|
|
||||||
* to an appropriate position in an _automated_ fashion.
|
|
||||||
*
|
|
||||||
* @param {EventBus} eventBus
|
|
||||||
* @param {Modeling} modeling
|
|
||||||
*/
|
|
||||||
export default function AutoPlace(eventBus, modeling) {
|
|
||||||
|
|
||||||
function emit(event, payload) {
|
|
||||||
return eventBus.fire(event, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append shape to source at appropriate position.
|
|
||||||
*
|
|
||||||
* @param {djs.model.Shape} source
|
|
||||||
* @param {djs.model.Shape} shape
|
|
||||||
*
|
|
||||||
* @return {djs.model.Shape} appended shape
|
|
||||||
*/
|
|
||||||
this.append = function(source, shape) {
|
|
||||||
|
|
||||||
emit('autoPlace.start', {
|
|
||||||
source: source,
|
|
||||||
shape: shape
|
|
||||||
});
|
|
||||||
|
|
||||||
// allow others to provide the position
|
|
||||||
var position = emit('autoPlace', {
|
|
||||||
source: source,
|
|
||||||
shape: shape
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!position) {
|
|
||||||
position = getNewShapePosition(source, shape);
|
|
||||||
}
|
|
||||||
|
|
||||||
var newShape = modeling.appendShape(source, shape, position, source.parent);
|
|
||||||
|
|
||||||
emit('autoPlace.end', {
|
|
||||||
source: source,
|
|
||||||
shape: newShape
|
|
||||||
});
|
|
||||||
|
|
||||||
return newShape;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoPlace.$inject = [
|
|
||||||
'eventBus',
|
|
||||||
'modeling'
|
|
||||||
];
|
|
|
@ -1,18 +0,0 @@
|
||||||
/**
|
|
||||||
* Select element after auto placement.
|
|
||||||
*
|
|
||||||
* @param {EventBus} eventBus
|
|
||||||
* @param {Selection} selection
|
|
||||||
*/
|
|
||||||
export default function AutoPlaceSelectionBehavior(eventBus, selection) {
|
|
||||||
|
|
||||||
eventBus.on('autoPlace.end', 500, function(e) {
|
|
||||||
selection.select(e.shape);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoPlaceSelectionBehavior.$inject = [
|
|
||||||
'eventBus',
|
|
||||||
'selection'
|
|
||||||
];
|
|
|
@ -1,430 +0,0 @@
|
||||||
import { is } from '../../util/ModelUtil';
|
|
||||||
import { isAny } from '../modeling/util/ModelingUtil';
|
|
||||||
|
|
||||||
import {
|
|
||||||
getMid,
|
|
||||||
asTRBL,
|
|
||||||
getOrientation
|
|
||||||
} from 'diagram-js/lib/layout/LayoutUtil';
|
|
||||||
|
|
||||||
import {
|
|
||||||
find,
|
|
||||||
reduce
|
|
||||||
} from 'min-dash';
|
|
||||||
|
|
||||||
var DEFAULT_HORIZONTAL_DISTANCE = 50;
|
|
||||||
|
|
||||||
var MAX_HORIZONTAL_DISTANCE = 250;
|
|
||||||
|
|
||||||
// padding to detect element placement
|
|
||||||
var PLACEMENT_DETECTION_PAD = 10;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the new position for the target element to
|
|
||||||
* connect to source.
|
|
||||||
*
|
|
||||||
* @param {djs.model.Shape} source
|
|
||||||
* @param {djs.model.Shape} element
|
|
||||||
*
|
|
||||||
* @return {Point}
|
|
||||||
*/
|
|
||||||
export function getNewShapePosition(source, element) {
|
|
||||||
|
|
||||||
if (is(element, 'bpmn:TextAnnotation')) {
|
|
||||||
return getTextAnnotationPosition(source, element);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isAny(element, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ])) {
|
|
||||||
return getDataElementPosition(source, element);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is(element, 'bpmn:FlowNode')) {
|
|
||||||
return getFlowNodePosition(source, element);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getDefaultPosition(source, element);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always try to place element right of source;
|
|
||||||
* compute actual distance from previous nodes in flow.
|
|
||||||
*/
|
|
||||||
export function getFlowNodePosition(source, element) {
|
|
||||||
|
|
||||||
var sourceTrbl = asTRBL(source);
|
|
||||||
var sourceMid = getMid(source);
|
|
||||||
|
|
||||||
var horizontalDistance = getFlowNodeDistance(source, element);
|
|
||||||
|
|
||||||
var orientation = 'left',
|
|
||||||
rowSize = 80,
|
|
||||||
margin = 30;
|
|
||||||
|
|
||||||
if (is(source, 'bpmn:BoundaryEvent')) {
|
|
||||||
orientation = getOrientation(source, source.host, -25);
|
|
||||||
|
|
||||||
if (orientation.indexOf('top') !== -1) {
|
|
||||||
margin *= -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVerticalDistance(orient) {
|
|
||||||
if (orient.indexOf('top') != -1) {
|
|
||||||
return -1 * rowSize;
|
|
||||||
} else if (orient.indexOf('bottom') != -1) {
|
|
||||||
return rowSize;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var position = {
|
|
||||||
x: sourceTrbl.right + horizontalDistance + element.width / 2,
|
|
||||||
y: sourceMid.y + getVerticalDistance(orientation)
|
|
||||||
};
|
|
||||||
|
|
||||||
var escapeDirection = {
|
|
||||||
y: {
|
|
||||||
margin: margin,
|
|
||||||
rowSize: rowSize
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return deconflictPosition(source, element, position, escapeDirection);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute best distance between source and target,
|
|
||||||
* based on existing connections to and from source.
|
|
||||||
*
|
|
||||||
* @param {djs.model.Shape} source
|
|
||||||
* @param {djs.model.Shape} element
|
|
||||||
*
|
|
||||||
* @return {Number} distance
|
|
||||||
*/
|
|
||||||
export function getFlowNodeDistance(source, element) {
|
|
||||||
|
|
||||||
var sourceTrbl = asTRBL(source);
|
|
||||||
|
|
||||||
// is connection a reference to consider?
|
|
||||||
function isReference(c) {
|
|
||||||
return is(c, 'bpmn:SequenceFlow');
|
|
||||||
}
|
|
||||||
|
|
||||||
function toTargetNode(weight) {
|
|
||||||
|
|
||||||
return function(shape) {
|
|
||||||
return {
|
|
||||||
shape: shape,
|
|
||||||
weight: weight,
|
|
||||||
distanceTo: function(shape) {
|
|
||||||
var shapeTrbl = asTRBL(shape);
|
|
||||||
|
|
||||||
return shapeTrbl.left - sourceTrbl.right;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function toSourceNode(weight) {
|
|
||||||
return function(shape) {
|
|
||||||
return {
|
|
||||||
shape: shape,
|
|
||||||
weight: weight,
|
|
||||||
distanceTo: function(shape) {
|
|
||||||
var shapeTrbl = asTRBL(shape);
|
|
||||||
|
|
||||||
return sourceTrbl.left - shapeTrbl.right;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// we create a list of nodes to take into consideration
|
|
||||||
// for calculating the optimal flow node distance
|
|
||||||
//
|
|
||||||
// * weight existing target nodes higher than source nodes
|
|
||||||
// * only take into account individual nodes once
|
|
||||||
//
|
|
||||||
var nodes = reduce([].concat(
|
|
||||||
getTargets(source, isReference).map(toTargetNode(5)),
|
|
||||||
getSources(source, isReference).map(toSourceNode(1))
|
|
||||||
), function(nodes, node) {
|
|
||||||
|
|
||||||
// filter out shapes connected twice via source or target
|
|
||||||
nodes[node.shape.id + '__weight_' + node.weight] = node;
|
|
||||||
|
|
||||||
return nodes;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
// compute distances between source and incoming nodes;
|
|
||||||
// group at the same time by distance and expose the
|
|
||||||
// favourite distance as { fav: { count, value } }.
|
|
||||||
var distancesGrouped = reduce(nodes, function(result, node) {
|
|
||||||
|
|
||||||
var shape = node.shape,
|
|
||||||
weight = node.weight,
|
|
||||||
distanceTo = node.distanceTo;
|
|
||||||
|
|
||||||
var fav = result.fav,
|
|
||||||
currentDistance,
|
|
||||||
currentDistanceCount,
|
|
||||||
currentDistanceEntry;
|
|
||||||
|
|
||||||
currentDistance = distanceTo(shape);
|
|
||||||
|
|
||||||
// ignore too far away peers
|
|
||||||
// or non-left to right modeled nodes
|
|
||||||
if (currentDistance < 0 || currentDistance > MAX_HORIZONTAL_DISTANCE) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDistanceEntry = result[String(currentDistance)] =
|
|
||||||
result[String(currentDistance)] || {
|
|
||||||
value: currentDistance,
|
|
||||||
count: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// inc diff count
|
|
||||||
currentDistanceCount = currentDistanceEntry.count += 1 * weight;
|
|
||||||
|
|
||||||
if (!fav || fav.count < currentDistanceCount) {
|
|
||||||
result.fav = currentDistanceEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}, { });
|
|
||||||
|
|
||||||
|
|
||||||
if (distancesGrouped.fav) {
|
|
||||||
return distancesGrouped.fav.value;
|
|
||||||
} else {
|
|
||||||
return DEFAULT_HORIZONTAL_DISTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always try to place text annotations top right of source.
|
|
||||||
*/
|
|
||||||
export function getTextAnnotationPosition(source, element) {
|
|
||||||
|
|
||||||
var sourceTrbl = asTRBL(source);
|
|
||||||
|
|
||||||
var position = {
|
|
||||||
x: sourceTrbl.right + element.width / 2,
|
|
||||||
y: sourceTrbl.top - 50 - element.height / 2
|
|
||||||
};
|
|
||||||
|
|
||||||
var escapeDirection = {
|
|
||||||
y: {
|
|
||||||
margin: -30,
|
|
||||||
rowSize: 20
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return deconflictPosition(source, element, position, escapeDirection);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always put element bottom right of source.
|
|
||||||
*/
|
|
||||||
export function getDataElementPosition(source, element) {
|
|
||||||
|
|
||||||
var sourceTrbl = asTRBL(source);
|
|
||||||
|
|
||||||
var position = {
|
|
||||||
x: sourceTrbl.right - 10 + element.width / 2,
|
|
||||||
y: sourceTrbl.bottom + 40 + element.width / 2
|
|
||||||
};
|
|
||||||
|
|
||||||
var escapeDirection = {
|
|
||||||
x: {
|
|
||||||
margin: 30,
|
|
||||||
rowSize: 30
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return deconflictPosition(source, element, position, escapeDirection);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always put element right of source per default.
|
|
||||||
*/
|
|
||||||
export function getDefaultPosition(source, element) {
|
|
||||||
|
|
||||||
var sourceTrbl = asTRBL(source);
|
|
||||||
|
|
||||||
var sourceMid = getMid(source);
|
|
||||||
|
|
||||||
// simply put element right next to source
|
|
||||||
return {
|
|
||||||
x: sourceTrbl.right + DEFAULT_HORIZONTAL_DISTANCE + element.width / 2,
|
|
||||||
y: sourceMid.y
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all connected elements around the given source.
|
|
||||||
*
|
|
||||||
* This includes:
|
|
||||||
*
|
|
||||||
* - connected elements
|
|
||||||
* - host connected elements
|
|
||||||
* - attachers connected elements
|
|
||||||
*
|
|
||||||
* @param {djs.model.Shape} source
|
|
||||||
* @param {djs.model.Shape} element
|
|
||||||
*
|
|
||||||
* @return {Array<djs.model.Shape>}
|
|
||||||
*/
|
|
||||||
function getAutoPlaceClosure(source, element) {
|
|
||||||
|
|
||||||
var allConnected = getConnected(source);
|
|
||||||
|
|
||||||
if (source.host) {
|
|
||||||
allConnected = allConnected.concat(getConnected(source.host));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source.attachers) {
|
|
||||||
allConnected = allConnected.concat(source.attachers.reduce(function(shapes, attacher) {
|
|
||||||
return shapes.concat(getConnected(attacher));
|
|
||||||
}, []));
|
|
||||||
}
|
|
||||||
|
|
||||||
return allConnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return target at given position, if defined.
|
|
||||||
*
|
|
||||||
* This takes connected elements from host and attachers
|
|
||||||
* into account, too.
|
|
||||||
*/
|
|
||||||
export function getConnectedAtPosition(source, position, element) {
|
|
||||||
|
|
||||||
var bounds = {
|
|
||||||
x: position.x - (element.width / 2),
|
|
||||||
y: position.y - (element.height / 2),
|
|
||||||
width: element.width,
|
|
||||||
height: element.height
|
|
||||||
};
|
|
||||||
|
|
||||||
var closure = getAutoPlaceClosure(source, element);
|
|
||||||
|
|
||||||
return find(closure, function(target) {
|
|
||||||
|
|
||||||
if (target === element) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var orientation = getOrientation(target, bounds, PLACEMENT_DETECTION_PAD);
|
|
||||||
|
|
||||||
return orientation === 'intersect';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new, position for the given element
|
|
||||||
* based on the given element that is not occupied
|
|
||||||
* by some element connected to source.
|
|
||||||
*
|
|
||||||
* Take into account the escapeDirection (where to move
|
|
||||||
* on positioning clashes) in the computation.
|
|
||||||
*
|
|
||||||
* @param {djs.model.Shape} source
|
|
||||||
* @param {djs.model.Shape} element
|
|
||||||
* @param {Point} position
|
|
||||||
* @param {Object} escapeDelta
|
|
||||||
*
|
|
||||||
* @return {Point}
|
|
||||||
*/
|
|
||||||
export function deconflictPosition(source, element, position, escapeDelta) {
|
|
||||||
|
|
||||||
function nextPosition(existingElement) {
|
|
||||||
|
|
||||||
var newPosition = {
|
|
||||||
x: position.x,
|
|
||||||
y: position.y
|
|
||||||
};
|
|
||||||
|
|
||||||
[ 'x', 'y' ].forEach(function(axis) {
|
|
||||||
|
|
||||||
var axisDelta = escapeDelta[axis];
|
|
||||||
|
|
||||||
if (!axisDelta) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var dimension = axis === 'x' ? 'width' : 'height';
|
|
||||||
|
|
||||||
var margin = axisDelta.margin,
|
|
||||||
rowSize = axisDelta.rowSize;
|
|
||||||
|
|
||||||
if (margin < 0) {
|
|
||||||
newPosition[axis] = Math.min(
|
|
||||||
existingElement[axis] + margin - element[dimension] / 2,
|
|
||||||
position[axis] - rowSize + margin
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
newPosition[axis] = Math.max(
|
|
||||||
existingTarget[axis] + existingTarget[dimension] + margin + element[dimension] / 2,
|
|
||||||
position[axis] + rowSize + margin
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return newPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
var existingTarget;
|
|
||||||
|
|
||||||
// deconflict position until free slot is found
|
|
||||||
while ((existingTarget = getConnectedAtPosition(source, position, element))) {
|
|
||||||
position = nextPosition(existingTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// helpers //////////////////////
|
|
||||||
|
|
||||||
function noneFilter() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getConnected(element, connectionFilter) {
|
|
||||||
return [].concat(
|
|
||||||
getTargets(element, connectionFilter),
|
|
||||||
getSources(element, connectionFilter)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSources(shape, connectionFilter) {
|
|
||||||
|
|
||||||
if (!connectionFilter) {
|
|
||||||
connectionFilter = noneFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shape.incoming.filter(connectionFilter).map(function(c) {
|
|
||||||
return c.source;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTargets(shape, connectionFilter) {
|
|
||||||
|
|
||||||
if (!connectionFilter) {
|
|
||||||
connectionFilter = noneFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shape.outgoing.filter(connectionFilter).map(function(c) {
|
|
||||||
return c.target;
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { getNewShapePosition } from './BpmnAutoPlaceUtil';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BPMN auto-place behavior.
|
||||||
|
*
|
||||||
|
* @param {EventBus} eventBus
|
||||||
|
*/
|
||||||
|
export default function AutoPlace(eventBus) {
|
||||||
|
eventBus.on('autoPlace', function(context) {
|
||||||
|
var shape = context.shape,
|
||||||
|
source = context.source;
|
||||||
|
|
||||||
|
return getNewShapePosition(source, shape);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoPlace.$inject = [ 'eventBus' ];
|
|
@ -0,0 +1,138 @@
|
||||||
|
import { is } from '../../util/ModelUtil';
|
||||||
|
import { isAny } from '../modeling/util/ModelingUtil';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getMid,
|
||||||
|
asTRBL,
|
||||||
|
getOrientation
|
||||||
|
} from 'diagram-js/lib/layout/LayoutUtil';
|
||||||
|
|
||||||
|
import {
|
||||||
|
findFreePosition,
|
||||||
|
generateGetNextPosition,
|
||||||
|
getConnectedDistance
|
||||||
|
} from 'diagram-js/lib/features/auto-place/AutoPlaceUtil';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the new position for the target element to
|
||||||
|
* connect to source.
|
||||||
|
*
|
||||||
|
* @param {djs.model.Shape} source
|
||||||
|
* @param {djs.model.Shape} element
|
||||||
|
*
|
||||||
|
* @return {Point}
|
||||||
|
*/
|
||||||
|
export function getNewShapePosition(source, element) {
|
||||||
|
|
||||||
|
if (is(element, 'bpmn:TextAnnotation')) {
|
||||||
|
return getTextAnnotationPosition(source, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAny(element, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ])) {
|
||||||
|
return getDataElementPosition(source, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is(element, 'bpmn:FlowNode')) {
|
||||||
|
return getFlowNodePosition(source, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always try to place element right of source;
|
||||||
|
* compute actual distance from previous nodes in flow.
|
||||||
|
*/
|
||||||
|
export function getFlowNodePosition(source, element) {
|
||||||
|
|
||||||
|
var sourceTrbl = asTRBL(source);
|
||||||
|
var sourceMid = getMid(source);
|
||||||
|
|
||||||
|
var horizontalDistance = getConnectedDistance(source, {
|
||||||
|
filter: function(connection) {
|
||||||
|
return is(connection, 'bpmn:SequenceFlow');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var margin = 30,
|
||||||
|
minDistance = 80,
|
||||||
|
orientation = 'left';
|
||||||
|
|
||||||
|
if (is(source, 'bpmn:BoundaryEvent')) {
|
||||||
|
orientation = getOrientation(source, source.host, -25);
|
||||||
|
|
||||||
|
if (orientation.indexOf('top') !== -1) {
|
||||||
|
margin *= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var position = {
|
||||||
|
x: sourceTrbl.right + horizontalDistance + element.width / 2,
|
||||||
|
y: sourceMid.y + getVerticalDistance(orientation, minDistance)
|
||||||
|
};
|
||||||
|
|
||||||
|
var nextPositionDirection = {
|
||||||
|
y: {
|
||||||
|
margin: margin,
|
||||||
|
minDistance: minDistance
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getVerticalDistance(orientation, minDistance) {
|
||||||
|
if (orientation.indexOf('top') != -1) {
|
||||||
|
return -1 * minDistance;
|
||||||
|
} else if (orientation.indexOf('bottom') != -1) {
|
||||||
|
return minDistance;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always try to place text annotations top right of source.
|
||||||
|
*/
|
||||||
|
export function getTextAnnotationPosition(source, element) {
|
||||||
|
|
||||||
|
var sourceTrbl = asTRBL(source);
|
||||||
|
|
||||||
|
var position = {
|
||||||
|
x: sourceTrbl.right + element.width / 2,
|
||||||
|
y: sourceTrbl.top - 50 - element.height / 2
|
||||||
|
};
|
||||||
|
|
||||||
|
var nextPositionDirection = {
|
||||||
|
y: {
|
||||||
|
margin: -30,
|
||||||
|
minDistance: 20
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always put element bottom right of source.
|
||||||
|
*/
|
||||||
|
export function getDataElementPosition(source, element) {
|
||||||
|
|
||||||
|
var sourceTrbl = asTRBL(source);
|
||||||
|
|
||||||
|
var position = {
|
||||||
|
x: sourceTrbl.right - 10 + element.width / 2,
|
||||||
|
y: sourceTrbl.bottom + 40 + element.width / 2
|
||||||
|
};
|
||||||
|
|
||||||
|
var nextPositionDirection = {
|
||||||
|
x: {
|
||||||
|
margin: 30,
|
||||||
|
minDistance: 30
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
import AutoPlace from './AutoPlace';
|
import AutoPlaceModule from 'diagram-js/lib/features/auto-place';
|
||||||
import AutoPlaceSelectionBehavior from './AutoPlaceSelectionBehavior';
|
|
||||||
|
import BpmnAutoPlace from './BpmnAutoPlace';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
__init__: [ 'autoPlaceSelectionBehavior' ],
|
__depends__: [ AutoPlaceModule ],
|
||||||
autoPlace: [ 'type', AutoPlace ],
|
__init__: [ 'bpmnAutoPlace' ],
|
||||||
autoPlaceSelectionBehavior: [ 'type', AutoPlaceSelectionBehavior ]
|
bpmnAutoPlace: [ 'type', BpmnAutoPlace ]
|
||||||
};
|
};
|
|
@ -142,9 +142,9 @@ ContextPadProvider.prototype.getContextPadEntries = function(element) {
|
||||||
/**
|
/**
|
||||||
* Create an append action
|
* Create an append action
|
||||||
*
|
*
|
||||||
* @param {String} type
|
* @param {string} type
|
||||||
* @param {String} className
|
* @param {string} className
|
||||||
* @param {String} [title]
|
* @param {string} [title]
|
||||||
* @param {Object} [options]
|
* @param {Object} [options]
|
||||||
*
|
*
|
||||||
* @return {Object} descriptor
|
* @return {Object} descriptor
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { getNewShapePosition } from '../../auto-place/AutoPlaceUtil';
|
import { getNewShapePosition } from '../../auto-place/BpmnAutoPlaceUtil';
|
||||||
|
|
||||||
import { getMid } from 'diagram-js/lib/layout/LayoutUtil';
|
import { getMid } from 'diagram-js/lib/layout/LayoutUtil';
|
||||||
import { is } from '../../../util/ModelUtil';
|
import { is } from '../../../util/ModelUtil';
|
||||||
|
|
||||||
|
var HIGH_PRIORITY = 2000;
|
||||||
|
|
||||||
|
|
||||||
export default function AutoPlaceBehavior(eventBus, gridSnapping) {
|
export default function AutoPlaceBehavior(eventBus, gridSnapping) {
|
||||||
eventBus.on('autoPlace', function(context) {
|
eventBus.on('autoPlace', HIGH_PRIORITY, function(context) {
|
||||||
var source = context.source,
|
var source = context.source,
|
||||||
sourceMid = getMid(source),
|
sourceMid = getMid(source),
|
||||||
shape = context.shape;
|
shape = context.shape;
|
||||||
|
|
|
@ -34,7 +34,7 @@ BpmnKeyboardBindings.prototype.registerBindings = function(keyboard, editorActio
|
||||||
* Add keyboard binding if respective editor action
|
* Add keyboard binding if respective editor action
|
||||||
* is registered.
|
* is registered.
|
||||||
*
|
*
|
||||||
* @param {String} action name
|
* @param {string} action name
|
||||||
* @param {Function} fn that implements the key binding
|
* @param {Function} fn that implements the key binding
|
||||||
*/
|
*/
|
||||||
function addListener(action, fn) {
|
function addListener(action, fn) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ export default function UpdateLabelHandler(modeling, textRenderer) {
|
||||||
* Element parameter can be label itself or connection (i.e. sequence flow).
|
* Element parameter can be label itself or connection (i.e. sequence flow).
|
||||||
*
|
*
|
||||||
* @param {djs.model.Base} element
|
* @param {djs.model.Base} element
|
||||||
* @param {String} text
|
* @param {string} text
|
||||||
*/
|
*/
|
||||||
function setText(element, text) {
|
function setText(element, text) {
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,8 @@ BpmnLayouter.prototype.layoutConnection = function(connection, hints) {
|
||||||
manhattanOptions = {
|
manhattanOptions = {
|
||||||
preferredLayouts: getBoundaryEventPreferredLayouts(source, target, connectionEnd)
|
preferredLayouts: getBoundaryEventPreferredLayouts(source, target, connectionEnd)
|
||||||
};
|
};
|
||||||
|
} else if (isExpandedSubProcess(source) || isExpandedSubProcess(target)) {
|
||||||
|
manhattanOptions = getSubProcessManhattanOptions(source);
|
||||||
} else if (is(source, 'bpmn:Gateway')) {
|
} else if (is(source, 'bpmn:Gateway')) {
|
||||||
manhattanOptions = {
|
manhattanOptions = {
|
||||||
preferredLayouts: [ 'v:h' ]
|
preferredLayouts: [ 'v:h' ]
|
||||||
|
@ -177,6 +179,17 @@ function getMessageFlowPreserveDocking(source, target) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSubProcessManhattanOptions(source) {
|
||||||
|
return {
|
||||||
|
preferredLayouts: [ 'straight', 'h:h' ],
|
||||||
|
preserveDocking: getSubProcessPreserveDocking(source)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSubProcessPreserveDocking(source) {
|
||||||
|
return isExpandedSubProcess(source) ? 'target' : 'source';
|
||||||
|
}
|
||||||
|
|
||||||
function getConnectionDocking(point, shape) {
|
function getConnectionDocking(point, shape) {
|
||||||
return point ? (point.original || point) : getMid(shape);
|
return point ? (point.original || point) : getMid(shape);
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,7 +229,7 @@ ElementFactory.prototype.createParticipantShape = function(attrs) {
|
||||||
*
|
*
|
||||||
* @param {Base} element
|
* @param {Base} element
|
||||||
* @param {Object} attrs (in/out map of attributes)
|
* @param {Object} attrs (in/out map of attributes)
|
||||||
* @param {Array<String>} attributeNames name of attributes to apply
|
* @param {Array<string>} attributeNames name of attributes to apply
|
||||||
*/
|
*/
|
||||||
function applyAttributes(element, attrs, attributeNames) {
|
function applyAttributes(element, attrs, attributeNames) {
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ function applyAttributes(element, attrs, attributeNames) {
|
||||||
*
|
*
|
||||||
* @param {Base} element
|
* @param {Base} element
|
||||||
* @param {Object} attrs (in/out map of attributes)
|
* @param {Object} attrs (in/out map of attributes)
|
||||||
* @param {String} attributeName to apply
|
* @param {string} attributeName to apply
|
||||||
*/
|
*/
|
||||||
function applyAttribute(element, attrs, attributeName) {
|
function applyAttribute(element, attrs, attributeName) {
|
||||||
element[attributeName] = attrs[attributeName];
|
element[attributeName] = attrs[attributeName];
|
||||||
|
|
|
@ -173,7 +173,7 @@ AdaptiveLabelPositioningBehavior.$inject = [
|
||||||
*
|
*
|
||||||
* @param {Shape} element
|
* @param {Shape} element
|
||||||
*
|
*
|
||||||
* @return {Array<String>}
|
* @return {Array<string>}
|
||||||
*/
|
*/
|
||||||
function getTakenHostAlignments(element) {
|
function getTakenHostAlignments(element) {
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ function getTakenHostAlignments(element) {
|
||||||
*
|
*
|
||||||
* @param {Shape} element
|
* @param {Shape} element
|
||||||
*
|
*
|
||||||
* @return {Array<String>}
|
* @return {Array<string>}
|
||||||
*/
|
*/
|
||||||
function getTakenConnectionAlignments(element) {
|
function getTakenConnectionAlignments(element) {
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ function getTakenConnectionAlignments(element) {
|
||||||
*
|
*
|
||||||
* @param {Shape} element
|
* @param {Shape} element
|
||||||
*
|
*
|
||||||
* @return {String} positioning identifier
|
* @return {string} positioning identifier
|
||||||
*/
|
*/
|
||||||
function getOptimalPosition(element) {
|
function getOptimalPosition(element) {
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ export default function GroupBehavior(
|
||||||
*
|
*
|
||||||
* @param {Array<djs.model.shape>} elements
|
* @param {Array<djs.model.shape>} elements
|
||||||
* @param {ModdleElement} categoryValue
|
* @param {ModdleElement} categoryValue
|
||||||
* @return {Boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
function isReferenced(elements, categoryValue) {
|
function isReferenced(elements, categoryValue) {
|
||||||
return elements.some(function(e) {
|
return elements.some(function(e) {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import { getParticipantResizeConstraints } from './util/ResizeUtil';
|
||||||
|
|
||||||
var HIGH_PRIORITY = 1500;
|
var HIGH_PRIORITY = 1500;
|
||||||
|
|
||||||
|
export var LANE_MIN_DIMENSIONS = { width: 300, height: 60 };
|
||||||
|
|
||||||
export var PARTICIPANT_MIN_DIMENSIONS = { width: 300, height: 150 };
|
export var PARTICIPANT_MIN_DIMENSIONS = { width: 300, height: 150 };
|
||||||
|
|
||||||
export var SUB_PROCESS_MIN_DIMENSIONS = { width: 140, height: 120 };
|
export var SUB_PROCESS_MIN_DIMENSIONS = { width: 140, height: 120 };
|
||||||
|
|
|
@ -5,21 +5,38 @@ import { is } from '../../../util/ModelUtil';
|
||||||
import { isExpanded } from '../../../util/DiUtil';
|
import { isExpanded } from '../../../util/DiUtil';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
LANE_MIN_DIMENSIONS,
|
||||||
PARTICIPANT_MIN_DIMENSIONS,
|
PARTICIPANT_MIN_DIMENSIONS,
|
||||||
SUB_PROCESS_MIN_DIMENSIONS,
|
SUB_PROCESS_MIN_DIMENSIONS,
|
||||||
TEXT_ANNOTATION_MIN_DIMENSIONS
|
TEXT_ANNOTATION_MIN_DIMENSIONS
|
||||||
} from './ResizeBehavior';
|
} from './ResizeBehavior';
|
||||||
|
|
||||||
|
import { getChildLanes } from '../util/LaneUtil';
|
||||||
|
|
||||||
|
var max = Math.max;
|
||||||
|
|
||||||
|
|
||||||
export default function SpaceToolBehavior(eventBus) {
|
export default function SpaceToolBehavior(eventBus) {
|
||||||
eventBus.on('spaceTool.getMinDimensions', function(context) {
|
eventBus.on('spaceTool.getMinDimensions', function(context) {
|
||||||
var shapes = context.shapes,
|
var shapes = context.shapes,
|
||||||
|
axis = context.axis,
|
||||||
|
start = context.start,
|
||||||
minDimensions = {};
|
minDimensions = {};
|
||||||
|
|
||||||
forEach(shapes, function(shape) {
|
forEach(shapes, function(shape) {
|
||||||
var id = shape.id;
|
var id = shape.id;
|
||||||
|
|
||||||
if (is(shape, 'bpmn:Participant')) {
|
if (is(shape, 'bpmn:Participant')) {
|
||||||
|
|
||||||
|
if (isHorizontal(axis)) {
|
||||||
minDimensions[ id ] = PARTICIPANT_MIN_DIMENSIONS;
|
minDimensions[ id ] = PARTICIPANT_MIN_DIMENSIONS;
|
||||||
|
} else {
|
||||||
|
minDimensions[ id ] = {
|
||||||
|
width: PARTICIPANT_MIN_DIMENSIONS.width,
|
||||||
|
height: getParticipantMinHeight(shape, start)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is(shape, 'bpmn:SubProcess') && isExpanded(shape)) {
|
if (is(shape, 'bpmn:SubProcess') && isExpanded(shape)) {
|
||||||
|
@ -36,3 +53,72 @@ export default function SpaceToolBehavior(eventBus) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SpaceToolBehavior.$inject = [ 'eventBus' ];
|
SpaceToolBehavior.$inject = [ 'eventBus' ];
|
||||||
|
|
||||||
|
|
||||||
|
// helpers //////////
|
||||||
|
function isHorizontal(axis) {
|
||||||
|
return axis === 'x';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get minimum height for participant taking lanes into account.
|
||||||
|
*
|
||||||
|
* @param {<djs.model.Shape>} participant
|
||||||
|
* @param {number} start
|
||||||
|
*
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
function getParticipantMinHeight(participant, start) {
|
||||||
|
var lanesMinHeight;
|
||||||
|
|
||||||
|
if (!hasChildLanes(participant)) {
|
||||||
|
return PARTICIPANT_MIN_DIMENSIONS.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
lanesMinHeight = getLanesMinHeight(participant, start);
|
||||||
|
|
||||||
|
return max(PARTICIPANT_MIN_DIMENSIONS.height, lanesMinHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasChildLanes(element) {
|
||||||
|
return !!getChildLanes(element).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLanesMinHeight(participant, resizeStart) {
|
||||||
|
var lanes = getChildLanes(participant),
|
||||||
|
resizedLane;
|
||||||
|
|
||||||
|
// find the nested lane which is currently resized
|
||||||
|
resizedLane = findResizedLane(lanes, resizeStart);
|
||||||
|
|
||||||
|
// resized lane cannot shrink below the minimum height
|
||||||
|
// but remaining lanes' dimensions are kept intact
|
||||||
|
return participant.height - resizedLane.height + LANE_MIN_DIMENSIONS.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find nested lane which is currently resized.
|
||||||
|
*
|
||||||
|
* @param {Array<djs.model.Shape>} lanes
|
||||||
|
* @param {number} resizeStart
|
||||||
|
*/
|
||||||
|
function findResizedLane(lanes, resizeStart) {
|
||||||
|
var i, lane, childLanes;
|
||||||
|
|
||||||
|
for (i = 0; i < lanes.length; i++) {
|
||||||
|
lane = lanes[i];
|
||||||
|
|
||||||
|
// resizing current lane or a lane nested
|
||||||
|
if (resizeStart >= lane.y && resizeStart <= lane.y + lane.height) {
|
||||||
|
childLanes = getChildLanes(lane);
|
||||||
|
|
||||||
|
// a nested lane is resized
|
||||||
|
if (childLanes.length) {
|
||||||
|
return findResizedLane(childLanes, resizeStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// current lane is the resized one
|
||||||
|
return lane;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ var sqrt = Math.sqrt,
|
||||||
/**
|
/**
|
||||||
* Calculate the square (power to two) of a number.
|
* Calculate the square (power to two) of a number.
|
||||||
*
|
*
|
||||||
* @param {Number} n
|
* @param {number} n
|
||||||
*
|
*
|
||||||
* @return {Number}
|
* @return {number}
|
||||||
*/
|
*/
|
||||||
function sq(n) {
|
function sq(n) {
|
||||||
return Math.pow(n, 2);
|
return Math.pow(n, 2);
|
||||||
|
@ -20,7 +20,7 @@ function sq(n) {
|
||||||
* @param {Point} p1
|
* @param {Point} p1
|
||||||
* @param {Point} p2
|
* @param {Point} p2
|
||||||
*
|
*
|
||||||
* @return {Number}
|
* @return {number}
|
||||||
*/
|
*/
|
||||||
function getDistance(p1, p2) {
|
function getDistance(p1, p2) {
|
||||||
return sqrt(sq(p1.x - p2.x) + sq(p1.y - p2.y));
|
return sqrt(sq(p1.x - p2.x) + sq(p1.y - p2.y));
|
||||||
|
@ -127,7 +127,7 @@ export function getAttachment(point, line) {
|
||||||
* @param {Point} s1 segment start
|
* @param {Point} s1 segment start
|
||||||
* @param {Point} s2 segment end
|
* @param {Point} s2 segment end
|
||||||
* @param {Point} cc circle center
|
* @param {Point} cc circle center
|
||||||
* @param {Number} cr circle radius
|
* @param {number} cr circle radius
|
||||||
*
|
*
|
||||||
* @return {Array<Point>} intersections
|
* @return {Array<Point>} intersections
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,6 +9,8 @@ import {
|
||||||
getLanesRoot
|
getLanesRoot
|
||||||
} from '../../../modeling/util/LaneUtil';
|
} from '../../../modeling/util/LaneUtil';
|
||||||
|
|
||||||
|
import { LANE_MIN_DIMENSIONS } from '../ResizeBehavior';
|
||||||
|
|
||||||
var abs = Math.abs,
|
var abs = Math.abs,
|
||||||
min = Math.min,
|
min = Math.min,
|
||||||
max = Math.max;
|
max = Math.max;
|
||||||
|
@ -31,9 +33,7 @@ function addMax(trbl, attr, value) {
|
||||||
return addToTrbl(trbl, attr, value, max);
|
return addToTrbl(trbl, attr, value, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
var LANE_MIN_HEIGHT = 60,
|
var LANE_RIGHT_PADDING = 20,
|
||||||
LANE_MIN_WIDTH = 300,
|
|
||||||
LANE_RIGHT_PADDING = 20,
|
|
||||||
LANE_LEFT_PADDING = 50,
|
LANE_LEFT_PADDING = 50,
|
||||||
LANE_TOP_PADDING = 20,
|
LANE_TOP_PADDING = 20,
|
||||||
LANE_BOTTOM_PADDING = 20;
|
LANE_BOTTOM_PADDING = 20;
|
||||||
|
@ -54,10 +54,10 @@ export function getParticipantResizeConstraints(laneShape, resizeDirection, bala
|
||||||
minTrbl = {};
|
minTrbl = {};
|
||||||
|
|
||||||
if (/e/.test(resizeDirection)) {
|
if (/e/.test(resizeDirection)) {
|
||||||
minTrbl.right = laneTrbl.left + LANE_MIN_WIDTH;
|
minTrbl.right = laneTrbl.left + LANE_MIN_DIMENSIONS.width;
|
||||||
} else
|
} else
|
||||||
if (/w/.test(resizeDirection)) {
|
if (/w/.test(resizeDirection)) {
|
||||||
minTrbl.left = laneTrbl.right - LANE_MIN_WIDTH;
|
minTrbl.left = laneTrbl.right - LANE_MIN_DIMENSIONS.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
allLanes.forEach(function(other) {
|
allLanes.forEach(function(other) {
|
||||||
|
@ -72,12 +72,12 @@ export function getParticipantResizeConstraints(laneShape, resizeDirection, bala
|
||||||
|
|
||||||
// max top size (based on next element)
|
// max top size (based on next element)
|
||||||
if (balanced && abs(laneTrbl.top - otherTrbl.bottom) < 10) {
|
if (balanced && abs(laneTrbl.top - otherTrbl.bottom) < 10) {
|
||||||
addMax(maxTrbl, 'top', otherTrbl.top + LANE_MIN_HEIGHT);
|
addMax(maxTrbl, 'top', otherTrbl.top + LANE_MIN_DIMENSIONS.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// min top size (based on self or nested element)
|
// min top size (based on self or nested element)
|
||||||
if (abs(laneTrbl.top - otherTrbl.top) < 5) {
|
if (abs(laneTrbl.top - otherTrbl.top) < 5) {
|
||||||
addMin(minTrbl, 'top', otherTrbl.bottom - LANE_MIN_HEIGHT);
|
addMin(minTrbl, 'top', otherTrbl.bottom - LANE_MIN_DIMENSIONS.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,12 +89,12 @@ export function getParticipantResizeConstraints(laneShape, resizeDirection, bala
|
||||||
|
|
||||||
// max bottom size (based on previous element)
|
// max bottom size (based on previous element)
|
||||||
if (balanced && abs(laneTrbl.bottom - otherTrbl.top) < 10) {
|
if (balanced && abs(laneTrbl.bottom - otherTrbl.top) < 10) {
|
||||||
addMin(maxTrbl, 'bottom', otherTrbl.bottom - LANE_MIN_HEIGHT);
|
addMin(maxTrbl, 'bottom', otherTrbl.bottom - LANE_MIN_DIMENSIONS.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// min bottom size (based on self or nested element)
|
// min bottom size (based on self or nested element)
|
||||||
if (abs(laneTrbl.bottom - otherTrbl.bottom) < 5) {
|
if (abs(laneTrbl.bottom - otherTrbl.bottom) < 5) {
|
||||||
addMax(minTrbl, 'bottom', otherTrbl.top + LANE_MIN_HEIGHT);
|
addMax(minTrbl, 'bottom', otherTrbl.top + LANE_MIN_DIMENSIONS.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,9 +9,9 @@ import { is } from '../../../util/ModelUtil';
|
||||||
* Return true if element has any of the given types.
|
* Return true if element has any of the given types.
|
||||||
*
|
*
|
||||||
* @param {djs.model.Base} element
|
* @param {djs.model.Base} element
|
||||||
* @param {Array<String>} types
|
* @param {Array<string>} types
|
||||||
*
|
*
|
||||||
* @return {Boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
export function isAny(element, types) {
|
export function isAny(element, types) {
|
||||||
return some(types, function(t) {
|
return some(types, function(t) {
|
||||||
|
@ -24,7 +24,7 @@ export function isAny(element, types) {
|
||||||
* Return the parent of the element with any of the given types.
|
* Return the parent of the element with any of the given types.
|
||||||
*
|
*
|
||||||
* @param {djs.model.Base} element
|
* @param {djs.model.Base} element
|
||||||
* @param {String|Array<String>} anyType
|
* @param {string|Array<string>} anyType
|
||||||
*
|
*
|
||||||
* @return {djs.model.Base}
|
* @return {djs.model.Base}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
*
|
*
|
||||||
* @param {djs.model.Base} element
|
* @param {djs.model.Base} element
|
||||||
*
|
*
|
||||||
* @return {Boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
export function isDifferentType(element) {
|
export function isDifferentType(element) {
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,7 @@ BpmnRules.prototype.canCopy = canCopy;
|
||||||
* Checks if given element can be used for starting connection.
|
* Checks if given element can be used for starting connection.
|
||||||
*
|
*
|
||||||
* @param {Element} source
|
* @param {Element} source
|
||||||
* @return {Boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
function canStartConnection(element) {
|
function canStartConnection(element) {
|
||||||
if (nonExistingOrLabel(element)) {
|
if (nonExistingOrLabel(element)) {
|
||||||
|
@ -435,7 +435,7 @@ function canConnect(source, target, connection) {
|
||||||
/**
|
/**
|
||||||
* Can an element be dropped into the target element
|
* Can an element be dropped into the target element
|
||||||
*
|
*
|
||||||
* @return {Boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
function canDrop(element, target, position) {
|
function canDrop(element, target, position) {
|
||||||
|
|
||||||
|
|
|
@ -39,10 +39,10 @@ BpmnSearchProvider.$inject = [
|
||||||
*
|
*
|
||||||
* <Token> :
|
* <Token> :
|
||||||
* {
|
* {
|
||||||
* normal|matched: <String>
|
* normal|matched: <string>
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @param {String} pattern
|
* @param {string} pattern
|
||||||
* @return {Array<Result>}
|
* @return {Array<Result>}
|
||||||
*/
|
*/
|
||||||
BpmnSearchProvider.prototype.find = function(pattern) {
|
BpmnSearchProvider.prototype.find = function(pattern) {
|
||||||
|
|
|
@ -19,9 +19,9 @@ var diRefs = new Refs(
|
||||||
* Returns true if an element has the given meta-model type
|
* Returns true if an element has the given meta-model type
|
||||||
*
|
*
|
||||||
* @param {ModdleElement} element
|
* @param {ModdleElement} element
|
||||||
* @param {String} type
|
* @param {string} type
|
||||||
*
|
*
|
||||||
* @return {Boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
function is(element, type) {
|
function is(element, type) {
|
||||||
return element.$instanceOf(type);
|
return element.$instanceOf(type);
|
||||||
|
|
|
@ -17,7 +17,7 @@ export var FLOW_LABEL_INDENT = 15;
|
||||||
* Returns true if the given semantic has an external label
|
* Returns true if the given semantic has an external label
|
||||||
*
|
*
|
||||||
* @param {BpmnElement} semantic
|
* @param {BpmnElement} semantic
|
||||||
* @return {Boolean} true if has label
|
* @return {boolean} true if has label
|
||||||
*/
|
*/
|
||||||
export function isLabelExternal(semantic) {
|
export function isLabelExternal(semantic) {
|
||||||
return is(semantic, 'bpmn:Event') ||
|
return is(semantic, 'bpmn:Event') ||
|
||||||
|
@ -35,7 +35,7 @@ export function isLabelExternal(semantic) {
|
||||||
* Returns true if the given element has an external label
|
* Returns true if the given element has an external label
|
||||||
*
|
*
|
||||||
* @param {djs.model.shape} element
|
* @param {djs.model.shape} element
|
||||||
* @return {Boolean} true if has label
|
* @return {boolean} true if has label
|
||||||
*/
|
*/
|
||||||
export function hasExternalLabel(element) {
|
export function hasExternalLabel(element) {
|
||||||
return isLabel(element.label);
|
return isLabel(element.label);
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
* Is an element of the given BPMN type?
|
* Is an element of the given BPMN type?
|
||||||
*
|
*
|
||||||
* @param {djs.model.Base|ModdleElement} element
|
* @param {djs.model.Base|ModdleElement} element
|
||||||
* @param {String} type
|
* @param {string} type
|
||||||
*
|
*
|
||||||
* @return {Boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
export function is(element, type) {
|
export function is(element, type) {
|
||||||
var bo = getBusinessObject(element);
|
var bo = getBusinessObject(element);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "bpmn-js",
|
"name": "bpmn-js",
|
||||||
"version": "6.4.2",
|
"version": "6.5.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1103,7 +1103,8 @@
|
||||||
"bpmn-font": {
|
"bpmn-font": {
|
||||||
"version": "0.9.3",
|
"version": "0.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/bpmn-font/-/bpmn-font-0.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/bpmn-font/-/bpmn-font-0.9.3.tgz",
|
||||||
"integrity": "sha512-kzRGXGLzTROLRNCSskkOyj/+SbtTAn2unKfgB9tNt7RWJFybg/Wbe9YjK2ALotI3b64wwlCTkAalXiTiskP6dg=="
|
"integrity": "sha512-kzRGXGLzTROLRNCSskkOyj/+SbtTAn2unKfgB9tNt7RWJFybg/Wbe9YjK2ALotI3b64wwlCTkAalXiTiskP6dg==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"bpmn-moddle": {
|
"bpmn-moddle": {
|
||||||
"version": "6.0.6",
|
"version": "6.0.6",
|
||||||
|
@ -2026,9 +2027,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"diagram-js": {
|
"diagram-js": {
|
||||||
"version": "6.4.1",
|
"version": "6.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/diagram-js/-/diagram-js-6.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/diagram-js/-/diagram-js-6.6.1.tgz",
|
||||||
"integrity": "sha512-VqzydNl6RmnWuHT1B82VId7mH+TG+yZYkgEDp5BizaVDJyhl2F9Z1/q+X9FUQaBq08ZMW1NQP/Bljn56nGHjKw==",
|
"integrity": "sha512-3SlXwT2ieXCZkQn8dVZWfNry9+6d4R+0Q57Oz9t/SfIyNIrRPg0c9IlsaTHpGUhPE3fossXPDjmvqjJD0lmBLw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"css.escape": "^1.5.1",
|
"css.escape": "^1.5.1",
|
||||||
"didi": "^4.0.0",
|
"didi": "^4.0.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "bpmn-js",
|
"name": "bpmn-js",
|
||||||
"version": "6.4.2",
|
"version": "6.5.0",
|
||||||
"description": "A bpmn 2.0 toolkit and web modeler",
|
"description": "A bpmn 2.0 toolkit and web modeler",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"all": "run-s lint test distro test:distro",
|
"all": "run-s lint test distro test:distro",
|
||||||
|
@ -39,6 +39,7 @@
|
||||||
"*.css"
|
"*.css"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"bpmn-font": "^0.9.3",
|
||||||
"camunda-bpmn-moddle": "^4.0.1",
|
"camunda-bpmn-moddle": "^4.0.1",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.1.2",
|
||||||
"chai-match": "^1.1.1",
|
"chai-match": "^1.1.1",
|
||||||
|
@ -79,10 +80,9 @@
|
||||||
"webpack": "^4.35.3"
|
"webpack": "^4.35.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bpmn-font": "^0.9.3",
|
|
||||||
"bpmn-moddle": "^6.0.6",
|
"bpmn-moddle": "^6.0.6",
|
||||||
"css.escape": "^1.5.1",
|
"css.escape": "^1.5.1",
|
||||||
"diagram-js": "^6.4.1",
|
"diagram-js": "^6.6.1",
|
||||||
"diagram-js-direct-editing": "^1.6.1",
|
"diagram-js-direct-editing": "^1.6.1",
|
||||||
"ids": "^1.0.0",
|
"ids": "^1.0.0",
|
||||||
"inherits": "^2.0.1",
|
"inherits": "^2.0.1",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="_tkxkICCPEeWwcL3w8i7dvw" targetNamespace="http://activiti.org/bpmn" exporter="camunda modeler" exporterVersion="2.7.0" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
|
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="_tkxkICCPEeWwcL3w8i7dvw" targetNamespace="http://activiti.org/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.1" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
|
||||||
<bpmn2:process id="Process_1" isExecutable="false">
|
<bpmn2:process id="Process_1" isExecutable="false">
|
||||||
<bpmn2:subProcess id="SubProcess_1">
|
<bpmn2:subProcess id="SubProcess_1">
|
||||||
<bpmn2:startEvent id="StartEvent_1">
|
<bpmn2:startEvent id="StartEvent_1">
|
||||||
|
@ -15,43 +15,32 @@
|
||||||
<bpmn2:boundaryEvent id="BoundaryEvent_2" name="superman" attachedToRef="Task_2" />
|
<bpmn2:boundaryEvent id="BoundaryEvent_2" name="superman" attachedToRef="Task_2" />
|
||||||
<bpmn2:task id="CompensationTask" isForCompensation="true" />
|
<bpmn2:task id="CompensationTask" isForCompensation="true" />
|
||||||
<bpmn2:intermediateThrowEvent id="IntermediateThrowEvent_1" name="joker" />
|
<bpmn2:intermediateThrowEvent id="IntermediateThrowEvent_1" name="joker" />
|
||||||
|
<bpmn2:boundaryEvent id="BoundaryEvent_3" name="wonder woman" attachedToRef="SubProcess_1" />
|
||||||
</bpmn2:process>
|
</bpmn2:process>
|
||||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
|
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
|
||||||
|
<bpmndi:BPMNShape id="_BPMNShape_SubProcess_2" bpmnElement="SubProcess_1" isExpanded="true">
|
||||||
|
<dc:Bounds x="204" y="78" width="457" height="289" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_1" sourceElement="_BPMNShape_StartEvent_2" targetElement="_BPMNShape_Task_2">
|
||||||
|
<di:waypoint x="311" y="232" />
|
||||||
|
<di:waypoint x="431" y="232" />
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<dc:Bounds x="332" y="236" width="6" height="6" />
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||||
<dc:Bounds x="275" y="214" width="36" height="36" />
|
<dc:Bounds x="275" y="214" width="36" height="36" />
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="293" y="255" width="0" height="0" />
|
<dc:Bounds x="293" y="255" width="0" height="0" />
|
||||||
</bpmndi:BPMNLabel>
|
</bpmndi:BPMNLabel>
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_SubProcess_2" bpmnElement="SubProcess_1" isExpanded="true">
|
|
||||||
<dc:Bounds x="204" y="78" width="457" height="289" />
|
|
||||||
</bpmndi:BPMNShape>
|
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_1">
|
<bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_1">
|
||||||
<dc:Bounds x="431" y="192" width="100" height="80" />
|
<dc:Bounds x="431" y="192" width="100" height="80" />
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_1" sourceElement="_BPMNShape_StartEvent_2" targetElement="_BPMNShape_Task_2">
|
|
||||||
<di:waypoint xsi:type="dc:Point" x="311" y="232" />
|
|
||||||
<di:waypoint xsi:type="dc:Point" x="431" y="232" />
|
|
||||||
<bpmndi:BPMNLabel>
|
|
||||||
<dc:Bounds x="332" y="236" width="6" height="6" />
|
|
||||||
</bpmndi:BPMNLabel>
|
|
||||||
</bpmndi:BPMNEdge>
|
|
||||||
<bpmndi:BPMNShape id="BoundaryEvent_1_di" bpmnElement="BoundaryEvent_1">
|
|
||||||
<dc:Bounds x="185" y="349" width="36" height="36" />
|
|
||||||
<bpmndi:BPMNLabel>
|
|
||||||
<dc:Bounds x="155" y="390" width="90" height="20" />
|
|
||||||
</bpmndi:BPMNLabel>
|
|
||||||
</bpmndi:BPMNShape>
|
|
||||||
<bpmndi:BPMNShape id="Task_2_di" bpmnElement="Task_2">
|
<bpmndi:BPMNShape id="Task_2_di" bpmnElement="Task_2">
|
||||||
<dc:Bounds x="795" y="75" width="100" height="80" />
|
<dc:Bounds x="795" y="75" width="100" height="80" />
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNShape id="BoundaryEvent_2_di" bpmnElement="BoundaryEvent_2">
|
|
||||||
<dc:Bounds x="781" y="140" width="36" height="36" />
|
|
||||||
<bpmndi:BPMNLabel>
|
|
||||||
<dc:Bounds x="754" y="176" width="90" height="20" />
|
|
||||||
</bpmndi:BPMNLabel>
|
|
||||||
</bpmndi:BPMNShape>
|
|
||||||
<bpmndi:BPMNShape id="CompensationTask_di" bpmnElement="CompensationTask">
|
<bpmndi:BPMNShape id="CompensationTask_di" bpmnElement="CompensationTask">
|
||||||
<dc:Bounds x="795" y="249" width="100" height="80" />
|
<dc:Bounds x="795" y="249" width="100" height="80" />
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
|
@ -61,6 +50,24 @@
|
||||||
<dc:Bounds x="191" y="525" width="24" height="14" />
|
<dc:Bounds x="191" y="525" width="24" height="14" />
|
||||||
</bpmndi:BPMNLabel>
|
</bpmndi:BPMNLabel>
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="BoundaryEvent_2_di" bpmnElement="BoundaryEvent_2">
|
||||||
|
<dc:Bounds x="781" y="140" width="36" height="36" />
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<dc:Bounds x="754" y="176" width="90" height="20" />
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="BoundaryEvent_1_di" bpmnElement="BoundaryEvent_1">
|
||||||
|
<dc:Bounds x="185" y="349" width="36" height="36" />
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<dc:Bounds x="155" y="390" width="90" height="20" />
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Event_1kn7msk_di" bpmnElement="BoundaryEvent_3">
|
||||||
|
<dc:Bounds x="412" y="349" width="36" height="36" />
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<dc:Bounds x="393" y="392" width="75" height="14" />
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
</bpmndi:BPMNPlane>
|
</bpmndi:BPMNPlane>
|
||||||
</bpmndi:BPMNDiagram>
|
</bpmndi:BPMNDiagram>
|
||||||
</bpmn2:definitions>
|
</bpmn2:definitions>
|
||||||
|
|
|
@ -142,7 +142,7 @@ export function bootstrapBpmnJS(BpmnJS, diagram, options, locals) {
|
||||||
*
|
*
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* @param {String} xml document to display
|
* @param {string} xml document to display
|
||||||
* @param {Object} (options) optional options to be passed to the diagram upon instantiation
|
* @param {Object} (options) optional options to be passed to the diagram upon instantiation
|
||||||
* @param {Object|Function} locals the local overrides to be used by the diagram or a function that produces them
|
* @param {Object|Function} locals the local overrides to be used by the diagram or a function that produces them
|
||||||
* @return {Function} a function to be passed to beforeEach
|
* @return {Function} a function to be passed to beforeEach
|
||||||
|
@ -170,7 +170,7 @@ export function bootstrapModeler(diagram, options, locals) {
|
||||||
*
|
*
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* @param {String} xml document to display
|
* @param {string} xml document to display
|
||||||
* @param {Object} (options) optional options to be passed to the diagram upon instantiation
|
* @param {Object} (options) optional options to be passed to the diagram upon instantiation
|
||||||
* @param {Object|Function} locals the local overrides to be used by the diagram or a function that produces them
|
* @param {Object|Function} locals the local overrides to be used by the diagram or a function that produces them
|
||||||
* @return {Function} a function to be passed to beforeEach
|
* @return {Function} a function to be passed to beforeEach
|
||||||
|
|
|
@ -61,7 +61,7 @@ CustomElementFactory.$inject = [ 'injector' ];
|
||||||
* return shapes[type];
|
* return shapes[type];
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param {String} type
|
* @param {string} type
|
||||||
*
|
*
|
||||||
* @return {Bounds} { width, height}
|
* @return {Bounds} { width, height}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -267,6 +267,21 @@ describe('Viewer', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should throw error due to missing diagram', function(done) {
|
||||||
|
|
||||||
|
var xml = require('../fixtures/bpmn/empty-definitions.bpmn');
|
||||||
|
|
||||||
|
// when
|
||||||
|
createViewer(xml, function(err, warnings) {
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(err.message).to.eql('no diagram to display');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -549,25 +564,6 @@ describe('Viewer', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should throw error due to missing diagram', function(done) {
|
|
||||||
|
|
||||||
var xml = require('../fixtures/bpmn/empty-definitions.bpmn');
|
|
||||||
|
|
||||||
// given
|
|
||||||
viewer = new Viewer({ container: container, additionalModules: testModules });
|
|
||||||
|
|
||||||
// when
|
|
||||||
viewer.importXML(xml, function(err) {
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(err.message).to.eql('no diagram to display');
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -416,8 +416,8 @@ describe('draw - bpmn renderer', function() {
|
||||||
*
|
*
|
||||||
* @param {djs.model.base} element - Element.
|
* @param {djs.model.base} element - Element.
|
||||||
* @param {SVG} gfx - Graphics of element.
|
* @param {SVG} gfx - Graphics of element.
|
||||||
* @param {String} fillColor - Fill color to expect.
|
* @param {string} fillColor - Fill color to expect.
|
||||||
* @param {String} strokeColor - Stroke color to expect.
|
* @param {string} strokeColor - Stroke color to expect.
|
||||||
*/
|
*/
|
||||||
function expectColors(element, gfx, fillColor, strokeColor) {
|
function expectColors(element, gfx, fillColor, strokeColor) {
|
||||||
var djsVisual = domQuery('.djs-visual', gfx);
|
var djsVisual = domQuery('.djs-visual', gfx);
|
||||||
|
|
|
@ -11,14 +11,12 @@ import selectionModule from 'diagram-js/lib/features/selection';
|
||||||
|
|
||||||
import { getBusinessObject } from '../../../../lib/util/ModelUtil';
|
import { getBusinessObject } from '../../../../lib/util/ModelUtil';
|
||||||
|
|
||||||
import { getMid } from 'diagram-js/lib/layout/LayoutUtil';
|
|
||||||
|
|
||||||
|
|
||||||
describe('features/auto-place', function() {
|
describe('features/auto-place', function() {
|
||||||
|
|
||||||
describe('element placement', function() {
|
describe('element placement', function() {
|
||||||
|
|
||||||
var diagramXML = require('./AutoPlace.bpmn');
|
var diagramXML = require('./BpmnAutoPlace.bpmn');
|
||||||
|
|
||||||
before(bootstrapModeler(diagramXML, {
|
before(bootstrapModeler(diagramXML, {
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -116,7 +114,7 @@ describe('features/auto-place', function() {
|
||||||
|
|
||||||
describe('integration', function() {
|
describe('integration', function() {
|
||||||
|
|
||||||
var diagramXML = require('./AutoPlace.bpmn');
|
var diagramXML = require('./BpmnAutoPlace.bpmn');
|
||||||
|
|
||||||
before(bootstrapModeler(diagramXML, {
|
before(bootstrapModeler(diagramXML, {
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -174,7 +172,7 @@ describe('features/auto-place', function() {
|
||||||
|
|
||||||
describe('multi connection handling', function() {
|
describe('multi connection handling', function() {
|
||||||
|
|
||||||
var diagramXML = require('./AutoPlace.multi-connection.bpmn');
|
var diagramXML = require('./BpmnAutoPlace.multi-connection.bpmn');
|
||||||
|
|
||||||
before(bootstrapModeler(diagramXML, {
|
before(bootstrapModeler(diagramXML, {
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -209,7 +207,7 @@ describe('features/auto-place', function() {
|
||||||
|
|
||||||
describe('boundary event connection handling', function() {
|
describe('boundary event connection handling', function() {
|
||||||
|
|
||||||
var diagramXML = require('./AutoPlace.boundary-events.bpmn');
|
var diagramXML = require('./BpmnAutoPlace.boundary-events.bpmn');
|
||||||
|
|
||||||
before(bootstrapModeler(diagramXML, {
|
before(bootstrapModeler(diagramXML, {
|
||||||
modules: [
|
modules: [
|
||||||
|
@ -241,12 +239,14 @@ describe('features/auto-place', function() {
|
||||||
expectedBounds: { x: 242, y: -27, width: 100, height: 80 }
|
expectedBounds: { x: 242, y: -27, width: 100, height: 80 }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should place top right of BOUNDARY_TOP_RIGHT without infinite loop', autoPlace({
|
it('should place top right of BOUNDARY_TOP_RIGHT without infinite loop', autoPlace({
|
||||||
element: 'bpmn:Task',
|
element: 'bpmn:Task',
|
||||||
behind: 'BOUNDARY_TOP_RIGHT',
|
behind: 'BOUNDARY_TOP_RIGHT',
|
||||||
expectedBounds: { x: 473, y: -27, width: 100, height: 80 }
|
expectedBounds: { x: 473, y: -27, width: 100, height: 80 }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should place top right of BOUNDARY_SUBPROCESS_TOP', autoPlace({
|
it('should place top right of BOUNDARY_SUBPROCESS_TOP', autoPlace({
|
||||||
element: 'bpmn:Task',
|
element: 'bpmn:Task',
|
||||||
behind: 'BOUNDARY_SUBPROCESS_TOP',
|
behind: 'BOUNDARY_SUBPROCESS_TOP',
|
||||||
|
@ -255,114 +255,10 @@ describe('features/auto-place', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('eventbus integration', function() {
|
|
||||||
|
|
||||||
var diagramXML = require('./AutoPlace.bpmn');
|
|
||||||
|
|
||||||
beforeEach(bootstrapModeler(diagramXML, {
|
|
||||||
modules: [
|
|
||||||
autoPlaceModule,
|
|
||||||
coreModule,
|
|
||||||
labelEditingModule,
|
|
||||||
modelingModule,
|
|
||||||
selectionModule
|
|
||||||
]
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
it('<autoPlace.start>', inject(
|
|
||||||
function(autoPlace, elementFactory, elementRegistry, eventBus) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var element = elementFactory.createShape({ type: 'bpmn:Task' });
|
|
||||||
|
|
||||||
var source = elementRegistry.get('TASK_2');
|
|
||||||
|
|
||||||
var listener = sinon.spy(function(event) {
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(event.shape).to.equal(element);
|
|
||||||
expect(event.source).to.equal(source);
|
|
||||||
});
|
|
||||||
|
|
||||||
eventBus.on('autoPlace.start', listener);
|
|
||||||
|
|
||||||
// when
|
|
||||||
autoPlace.append(source, element);
|
|
||||||
|
|
||||||
expect(listener).to.have.been.called;
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
it('<autoPlace>', inject(
|
|
||||||
function(autoPlace, elementFactory, elementRegistry, eventBus) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var element = elementFactory.createShape({ type: 'bpmn:Task' });
|
|
||||||
|
|
||||||
var source = elementRegistry.get('TASK_2');
|
|
||||||
|
|
||||||
var listener = sinon.spy(function(event) {
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(event.shape).to.equal(element);
|
|
||||||
expect(event.source).to.equal(source);
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: 0,
|
|
||||||
y: 0
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
eventBus.on('autoPlace', listener);
|
|
||||||
|
|
||||||
// when
|
|
||||||
autoPlace.append(source, element);
|
|
||||||
|
|
||||||
expect(listener).to.have.been.called;
|
|
||||||
|
|
||||||
expect(getMid(element)).to.eql({
|
|
||||||
x: 0,
|
|
||||||
y: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
it('<autoPlace.end>', inject(
|
|
||||||
function(autoPlace, elementFactory, elementRegistry, eventBus) {
|
|
||||||
|
|
||||||
// given
|
|
||||||
var element = elementFactory.createShape({ type: 'bpmn:Task' });
|
|
||||||
|
|
||||||
var source = elementRegistry.get('TASK_2');
|
|
||||||
|
|
||||||
var listener = sinon.spy(function(event) {
|
|
||||||
|
|
||||||
// then
|
|
||||||
expect(event.shape).to.equal(element);
|
|
||||||
expect(event.source).to.equal(source);
|
|
||||||
});
|
|
||||||
|
|
||||||
eventBus.on('autoPlace.end', listener);
|
|
||||||
|
|
||||||
// when
|
|
||||||
autoPlace.append(source, element);
|
|
||||||
|
|
||||||
expect(listener).to.have.been.called;
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// helpers //////////
|
||||||
|
|
||||||
// helpers //////////////////////
|
|
||||||
|
|
||||||
function autoPlace(cfg) {
|
function autoPlace(cfg) {
|
||||||
|
|
|
@ -834,7 +834,7 @@ describe('features/copy-paste', function() {
|
||||||
/**
|
/**
|
||||||
* Integration test involving copying, pasting, moving, undoing and redoing.
|
* Integration test involving copying, pasting, moving, undoing and redoing.
|
||||||
*
|
*
|
||||||
* @param {String|Array<String>} elementIds
|
* @param {string|Array<string>} elementIds
|
||||||
*/
|
*/
|
||||||
function integrationTest(elementIds) {
|
function integrationTest(elementIds) {
|
||||||
if (!isArray(elementIds)) {
|
if (!isArray(elementIds)) {
|
||||||
|
@ -1000,7 +1000,7 @@ function _findDescriptorsInTree(elements, tree, depth) {
|
||||||
/**
|
/**
|
||||||
* Copy elements.
|
* Copy elements.
|
||||||
*
|
*
|
||||||
* @param {Array<String|djs.model.Base} elements
|
* @param {Array<string|djs.model.Base} elements
|
||||||
*
|
*
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,6 +3,8 @@ import {
|
||||||
inject
|
inject
|
||||||
} from 'test/TestHelper';
|
} from 'test/TestHelper';
|
||||||
|
|
||||||
|
import { pick } from 'min-dash';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getBusinessObject
|
getBusinessObject
|
||||||
} from 'lib/util/ModelUtil';
|
} from 'lib/util/ModelUtil';
|
||||||
|
@ -123,4 +125,35 @@ describe('features/modeling - resize shape', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('integration', function() {
|
||||||
|
|
||||||
|
var diagramXML = require('../../../fixtures/bpmn/boundary-events.bpmn');
|
||||||
|
|
||||||
|
var testModules = [ coreModule, modelingModule ];
|
||||||
|
|
||||||
|
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
||||||
|
|
||||||
|
|
||||||
|
it('should not move Boundary Event if unnecessary', inject(function(elementRegistry, modeling) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var boundaryEvent = elementRegistry.get('BoundaryEvent_3'),
|
||||||
|
originalPosition = getPosition(boundaryEvent),
|
||||||
|
subProcessElement = elementRegistry.get('SubProcess_1');
|
||||||
|
|
||||||
|
// when
|
||||||
|
modeling.resizeShape(subProcessElement, { x: 204, y: 28, width: 400, height: 339 });
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(getPosition(boundaryEvent)).to.jsonEqual(originalPosition);
|
||||||
|
}));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// helper /////
|
||||||
|
function getPosition(shape) {
|
||||||
|
return pick(shape, [ 'x', 'y' ]);
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,11 @@ import {
|
||||||
createCanvasEvent as canvasEvent
|
createCanvasEvent as canvasEvent
|
||||||
} from '../../../../util/MockEvents';
|
} from '../../../../util/MockEvents';
|
||||||
|
|
||||||
import { SUB_PROCESS_MIN_DIMENSIONS } from 'lib/features/modeling/behavior/ResizeBehavior';
|
import {
|
||||||
|
LANE_MIN_DIMENSIONS,
|
||||||
|
PARTICIPANT_MIN_DIMENSIONS,
|
||||||
|
SUB_PROCESS_MIN_DIMENSIONS
|
||||||
|
} from 'lib/features/modeling/behavior/ResizeBehavior';
|
||||||
|
|
||||||
var testModules = [
|
var testModules = [
|
||||||
coreModule,
|
coreModule,
|
||||||
|
@ -26,16 +30,16 @@ var testModules = [
|
||||||
|
|
||||||
describe('features/modeling - space tool behavior', function() {
|
describe('features/modeling - space tool behavior', function() {
|
||||||
|
|
||||||
describe('participant', function() {
|
describe('subprocess', function() {
|
||||||
|
|
||||||
describe('minimum dimensions', function() {
|
describe('minimum dimensions', function() {
|
||||||
|
|
||||||
var diagramXML = require('./SpaceToolBehaviorSpec.bpmn');
|
var diagramXML = require('./SpaceToolBehaviorSpec.subprocess.bpmn');
|
||||||
|
|
||||||
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
||||||
|
|
||||||
|
|
||||||
it('should ensure minimum dimensions', inject(
|
it('should ensure subprocess minimum dimensions', inject(
|
||||||
function(dragging, elementRegistry, spaceTool) {
|
function(dragging, elementRegistry, spaceTool) {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
|
@ -57,4 +61,92 @@ describe('features/modeling - space tool behavior', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('participant', function() {
|
||||||
|
|
||||||
|
describe('minimum dimensions', function() {
|
||||||
|
|
||||||
|
var diagramXML = require('./SpaceToolBehaviorSpec.participant.bpmn');
|
||||||
|
|
||||||
|
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
||||||
|
|
||||||
|
|
||||||
|
it('should ensure participant minimum width', inject(
|
||||||
|
function(dragging, elementRegistry, spaceTool) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var participant = elementRegistry.get('Participant_1');
|
||||||
|
|
||||||
|
// when
|
||||||
|
spaceTool.activateMakeSpace(canvasEvent({ x: 300, y: 0 }));
|
||||||
|
|
||||||
|
dragging.move(canvasEvent({ x: -200, y: 0 }));
|
||||||
|
|
||||||
|
dragging.end();
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(participant.width).to.equal(PARTICIPANT_MIN_DIMENSIONS.width);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
it('should ensure participant minimum height', inject(
|
||||||
|
function(dragging, elementRegistry, spaceTool) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var participant = elementRegistry.get('Participant_1');
|
||||||
|
|
||||||
|
// when
|
||||||
|
spaceTool.activateMakeSpace(canvasEvent({ x: 0, y: 100 }));
|
||||||
|
|
||||||
|
dragging.move(canvasEvent({ x: 0, y: -400 }));
|
||||||
|
|
||||||
|
dragging.end();
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(participant.height).to.equal(PARTICIPANT_MIN_DIMENSIONS.height);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
it('should ensure lane minimum height', inject(
|
||||||
|
function(dragging, elementRegistry, spaceTool) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var lane = elementRegistry.get('Lane_1');
|
||||||
|
|
||||||
|
// when
|
||||||
|
spaceTool.activateMakeSpace(canvasEvent({ x: 0, y: 400 }));
|
||||||
|
|
||||||
|
dragging.move(canvasEvent({ x: 0, y: 0 }));
|
||||||
|
|
||||||
|
dragging.end();
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(lane.height).to.equal(LANE_MIN_DIMENSIONS.height);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
it('should ensure nested lane minimum height', inject(
|
||||||
|
function(dragging, elementRegistry, spaceTool) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var lane = elementRegistry.get('Lane_6');
|
||||||
|
|
||||||
|
// when
|
||||||
|
spaceTool.activateMakeSpace(canvasEvent({ x: 0, y: 925 }));
|
||||||
|
|
||||||
|
dragging.move(canvasEvent({ x: 0, y: 0 }));
|
||||||
|
|
||||||
|
dragging.end();
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(lane.height).to.equal(LANE_MIN_DIMENSIONS.height);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" id="Definitions_0mdr1un" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.0">
|
||||||
|
<bpmn:collaboration id="Collaboration_1">
|
||||||
|
<bpmn:participant id="Participant_1" name="Participant_1" processRef="Process_1" />
|
||||||
|
<bpmn:participant id="Participant_2" name="Participant_2" processRef="Process_2" />
|
||||||
|
<bpmn:participant id="Participant_3" name="Participant_3" processRef="Process_3" />
|
||||||
|
</bpmn:collaboration>
|
||||||
|
<bpmn:process id="Process_1" isExecutable="true" />
|
||||||
|
<bpmn:process id="Process_2" isExecutable="false">
|
||||||
|
<bpmn:laneSet id="LaneSet_16fkurg">
|
||||||
|
<bpmn:lane id="Lane_1" name="Lane_1" />
|
||||||
|
<bpmn:lane id="Lane_2" name="Lane_2" />
|
||||||
|
</bpmn:laneSet>
|
||||||
|
</bpmn:process>
|
||||||
|
<bpmn:process id="Process_3" isExecutable="false">
|
||||||
|
<bpmn:laneSet id="LaneSet_04c016w">
|
||||||
|
<bpmn:lane id="Lane_3" name="Lane_3" />
|
||||||
|
<bpmn:lane id="Lane_4" name="Lane_4">
|
||||||
|
<bpmn:childLaneSet id="LaneSet_1eow6b9">
|
||||||
|
<bpmn:lane id="Lane_5" name="Lane_5" />
|
||||||
|
<bpmn:lane id="Lane_6" name="Lane_6" />
|
||||||
|
</bpmn:childLaneSet>
|
||||||
|
</bpmn:lane>
|
||||||
|
</bpmn:laneSet>
|
||||||
|
</bpmn:process>
|
||||||
|
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||||
|
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
|
||||||
|
<bpmndi:BPMNShape id="Participant_06757og_di" bpmnElement="Participant_1" isHorizontal="true">
|
||||||
|
<dc:Bounds x="0" y="0" width="600" height="250" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Participant_0ae1cne_di" bpmnElement="Participant_2" isHorizontal="true">
|
||||||
|
<dc:Bounds x="700" y="350" width="600" height="250" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Lane_030yoo3_di" bpmnElement="Lane_1" isHorizontal="true">
|
||||||
|
<dc:Bounds x="730" y="350" width="570" height="130" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Lane_1bwlv2s_di" bpmnElement="Lane_2" isHorizontal="true">
|
||||||
|
<dc:Bounds x="730" y="480" width="570" height="120" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Participant_01wmlzw_di" bpmnElement="Participant_3" isHorizontal="true">
|
||||||
|
<dc:Bounds x="1400" y="700" width="600" height="250" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Lane_0jco8kr_di" bpmnElement="Lane_3" isHorizontal="true">
|
||||||
|
<dc:Bounds x="1430" y="700" width="570" height="125" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Lane_0zojmuw_di" bpmnElement="Lane_4" isHorizontal="true">
|
||||||
|
<dc:Bounds x="1430" y="825" width="570" height="125" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Lane_1xlpjnj_di" bpmnElement="Lane_5" isHorizontal="true">
|
||||||
|
<dc:Bounds x="1460" y="825" width="540" height="63" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Lane_0k03ea4_di" bpmnElement="Lane_6" isHorizontal="true">
|
||||||
|
<dc:Bounds x="1460" y="888" width="540" height="62" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
</bpmndi:BPMNPlane>
|
||||||
|
</bpmndi:BPMNDiagram>
|
||||||
|
</bpmn:definitions>
|
|
@ -5,6 +5,7 @@ import {
|
||||||
} from 'test/TestHelper';
|
} from 'test/TestHelper';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
map,
|
||||||
pick
|
pick
|
||||||
} from 'min-dash';
|
} from 'min-dash';
|
||||||
|
|
||||||
|
@ -270,6 +271,45 @@ describe('features/modeling - add Lane', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('flow node handling', function() {
|
||||||
|
|
||||||
|
var diagramXML = require('./lanes.bpmn');
|
||||||
|
|
||||||
|
beforeEach(bootstrapModeler(diagramXML, {
|
||||||
|
modules: testModules
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should move flow nodes and sequence flows', inject(function(elementRegistry, modeling) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var laneShape = elementRegistry.get('Nested_Lane_B'),
|
||||||
|
task_Boundary = elementRegistry.get('Task_Boundary'),
|
||||||
|
boundary = elementRegistry.get('Boundary'),
|
||||||
|
sequenceFlow = elementRegistry.get('SequenceFlow'),
|
||||||
|
sequenceFlow_From_Boundary = elementRegistry.get('SequenceFlow_From_Boundary');
|
||||||
|
|
||||||
|
// when
|
||||||
|
var newLane = modeling.addLane(laneShape, 'top');
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(task_Boundary).to.have.position({ x: 264, y: -57 });
|
||||||
|
expect(boundary).to.have.position({ x: 311, y: 5 });
|
||||||
|
|
||||||
|
expect(sequenceFlow_From_Boundary).to.have.waypoints([
|
||||||
|
{ x: 329, y: 161 - newLane.height },
|
||||||
|
{ x: 329, y: 188 - newLane.height },
|
||||||
|
{ x: 482, y: 188 - newLane.height },
|
||||||
|
{ x: 482, y: 143 - newLane.height }
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(sequenceFlow).to.have.waypoints([
|
||||||
|
{ x: 364, y: 103 - newLane.height },
|
||||||
|
{ x: 432, y: 103 - newLane.height }
|
||||||
|
]);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
describe('flow node handling', function() {
|
describe('flow node handling', function() {
|
||||||
|
|
||||||
var diagramXML = require('./lanes-flow-nodes.bpmn');
|
var diagramXML = require('./lanes-flow-nodes.bpmn');
|
||||||
|
@ -278,6 +318,7 @@ describe('features/modeling - add Lane', function() {
|
||||||
modules: testModules
|
modules: testModules
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
function addLaneAbove(laneId) {
|
function addLaneAbove(laneId) {
|
||||||
|
|
||||||
return getBpmnJS().invoke(function(elementRegistry, modeling) {
|
return getBpmnJS().invoke(function(elementRegistry, modeling) {
|
||||||
|
@ -289,19 +330,32 @@ describe('features/modeling - add Lane', function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addLaneBelow(laneId) {
|
||||||
|
|
||||||
|
return getBpmnJS().invoke(function(elementRegistry, modeling) {
|
||||||
|
var existingLane = elementRegistry.get(laneId);
|
||||||
|
|
||||||
|
expect(existingLane).to.exist;
|
||||||
|
|
||||||
|
return modeling.addLane(existingLane, 'bottom');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
it('should move flow nodes', inject(function(elementRegistry, modeling) {
|
it('should move flow nodes', inject(function(elementRegistry, modeling) {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
var task_Boundary = elementRegistry.get('Task_Boundary'),
|
var task_Boundary = elementRegistry.get('Task_Boundary'),
|
||||||
boundary = elementRegistry.get('Boundary');
|
taskPosition = getPosition(task_Boundary),
|
||||||
|
boundary = elementRegistry.get('Boundary'),
|
||||||
|
boundaryPosition = getPosition(boundary);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
addLaneAbove('Nested_Lane_B');
|
addLaneAbove('Nested_Lane_B');
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(task_Boundary).to.have.position({ x: 344, y: -7 });
|
expect(task_Boundary).to.have.position({ x: taskPosition.x, y: taskPosition.y - 120 });
|
||||||
expect(boundary).to.have.position({ x: 391, y: 55 });
|
expect(boundary).to.have.position({ x: boundaryPosition.x, y: boundaryPosition.y - 120 });
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
@ -309,22 +363,54 @@ describe('features/modeling - add Lane', function() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
var sequenceFlow = elementRegistry.get('SequenceFlow'),
|
var sequenceFlow = elementRegistry.get('SequenceFlow'),
|
||||||
sequenceFlow_From_Boundary = elementRegistry.get('SequenceFlow_From_Boundary');
|
sequenceFlowWaypoints = sequenceFlow.waypoints,
|
||||||
|
sequenceFlow_From_Boundary = elementRegistry.get('SequenceFlow_From_Boundary'),
|
||||||
|
sequenceFlow_From_BoundaryWaypoints = sequenceFlow_From_Boundary.waypoints;
|
||||||
|
|
||||||
// when
|
// when
|
||||||
addLaneAbove('Nested_Lane_B');
|
addLaneAbove('Nested_Lane_B');
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(sequenceFlow_From_Boundary).to.have.waypoints([
|
expect(sequenceFlow_From_Boundary).to.have.waypoints(
|
||||||
{ x: 409, y: 91 },
|
moveWaypoints(sequenceFlow_From_BoundaryWaypoints, 0, -120)
|
||||||
{ x: 409, y: 118 },
|
);
|
||||||
{ x: 562, y: 118 },
|
|
||||||
{ x: 562, y: 73 }
|
|
||||||
]);
|
|
||||||
|
|
||||||
expect(sequenceFlow).to.have.waypoints([
|
expect(sequenceFlow).to.have.waypoints(
|
||||||
{ x: 444, y: 33 },
|
moveWaypoints(sequenceFlowWaypoints, 0, -120)
|
||||||
{ x: 512, y: 33 }
|
);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should move message flows when lane added above', inject(function(elementRegistry) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var messageFlow = elementRegistry.get('MessageFlowAbove'),
|
||||||
|
messageFlowWaypoints = messageFlow.waypoints;
|
||||||
|
|
||||||
|
// when
|
||||||
|
addLaneAbove('Nested_Lane_B');
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(messageFlow).to.have.waypoints([
|
||||||
|
movePosition(messageFlowWaypoints[0], 0, -120),
|
||||||
|
messageFlowWaypoints[1]
|
||||||
|
]);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should move message flows when lane added below', inject(function(elementRegistry) {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var messageFlow = elementRegistry.get('MessageFlowBelow'),
|
||||||
|
messageFlowWaypoints = messageFlow.waypoints;
|
||||||
|
|
||||||
|
// when
|
||||||
|
addLaneBelow('Nested_Lane_B');
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(messageFlow).to.have.waypoints([
|
||||||
|
messageFlowWaypoints[0],
|
||||||
|
movePosition(messageFlowWaypoints[1], 0, 120)
|
||||||
]);
|
]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -333,7 +419,8 @@ describe('features/modeling - add Lane', function() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
var event = elementRegistry.get('Event'),
|
var event = elementRegistry.get('Event'),
|
||||||
label = event.label;
|
label = event.label,
|
||||||
|
labelPosition = getPosition(label);
|
||||||
|
|
||||||
// TODO(nikku): consolidate import + editing behavior => not consistent right now
|
// TODO(nikku): consolidate import + editing behavior => not consistent right now
|
||||||
|
|
||||||
|
@ -344,7 +431,10 @@ describe('features/modeling - add Lane', function() {
|
||||||
addLaneAbove('Nested_Lane_B');
|
addLaneAbove('Nested_Lane_B');
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(label.y).to.eql(58);
|
expect(label).to.have.position({
|
||||||
|
x: labelPosition.x,
|
||||||
|
y: labelPosition.y - 120
|
||||||
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -408,3 +498,23 @@ function padEvent(entry) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPosition(element) {
|
||||||
|
return {
|
||||||
|
x: element.x,
|
||||||
|
y: element.y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveWaypoints(waypoints, deltaX, deltaY) {
|
||||||
|
return map(waypoints, function(waypoint) {
|
||||||
|
return movePosition(waypoint, deltaX, deltaY);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function movePosition(point, deltaX, deltaY) {
|
||||||
|
return {
|
||||||
|
x: point.x + deltaX,
|
||||||
|
y: point.y + deltaY
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="_4bAZoD9WEeWLcNBL4nCk1A" targetNamespace="http://camunda.org/schema/1.0/bpmn" exporter="bpmn-js (https://demo.bpmn.io)" exporterVersion="6.3.1" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
|
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="_4bAZoD9WEeWLcNBL4nCk1A" targetNamespace="http://camunda.org/schema/1.0/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.1" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
|
||||||
<bpmn2:collaboration id="_Collaboration_2">
|
<bpmn2:collaboration id="_Collaboration_2">
|
||||||
<bpmn2:participant id="Participant_Lane" name="Participant_Lane" processRef="Process_Lane" />
|
<bpmn2:participant id="Participant_Lane" name="Participant_Lane" processRef="Process_Lane" />
|
||||||
|
<bpmn2:participant id="ParticipantBelow" name="ParticipantBelow" processRef="Process_0kzdcfx" />
|
||||||
|
<bpmn2:participant id="ParticipantAbove" name="ParticipantAbove" processRef="Process_1nej7ck" />
|
||||||
|
<bpmn2:messageFlow id="MessageFlowBelow" sourceRef="ParticipantBelow" targetRef="Participant_Lane" />
|
||||||
|
<bpmn2:messageFlow id="MessageFlowAbove" name="MessageFlowAbove" sourceRef="Participant_Lane" targetRef="ParticipantAbove" />
|
||||||
</bpmn2:collaboration>
|
</bpmn2:collaboration>
|
||||||
<bpmn2:process id="Process_Lane" isExecutable="false">
|
<bpmn2:process id="Process_Lane" isExecutable="false">
|
||||||
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
|
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
|
||||||
|
@ -11,13 +15,13 @@
|
||||||
<bpmn2:flowNodeRef>Event</bpmn2:flowNodeRef>
|
<bpmn2:flowNodeRef>Event</bpmn2:flowNodeRef>
|
||||||
<bpmn2:flowNodeRef>Boundary</bpmn2:flowNodeRef>
|
<bpmn2:flowNodeRef>Boundary</bpmn2:flowNodeRef>
|
||||||
<bpmn2:childLaneSet id="LaneSet_2">
|
<bpmn2:childLaneSet id="LaneSet_2">
|
||||||
<bpmn2:lane id="Nested_Lane_B" name="Nested_Lane_B" />
|
|
||||||
<bpmn2:lane id="Nested_Lane_A" name="Nested_Lane_A">
|
<bpmn2:lane id="Nested_Lane_A" name="Nested_Lane_A">
|
||||||
<bpmn2:flowNodeRef>Task_Boundary</bpmn2:flowNodeRef>
|
<bpmn2:flowNodeRef>Task_Boundary</bpmn2:flowNodeRef>
|
||||||
<bpmn2:flowNodeRef>Task</bpmn2:flowNodeRef>
|
<bpmn2:flowNodeRef>Task</bpmn2:flowNodeRef>
|
||||||
<bpmn2:flowNodeRef>Event</bpmn2:flowNodeRef>
|
<bpmn2:flowNodeRef>Event</bpmn2:flowNodeRef>
|
||||||
<bpmn2:flowNodeRef>Boundary</bpmn2:flowNodeRef>
|
<bpmn2:flowNodeRef>Boundary</bpmn2:flowNodeRef>
|
||||||
</bpmn2:lane>
|
</bpmn2:lane>
|
||||||
|
<bpmn2:lane id="Nested_Lane_B" name="Nested_Lane_B" />
|
||||||
</bpmn2:childLaneSet>
|
</bpmn2:childLaneSet>
|
||||||
</bpmn2:lane>
|
</bpmn2:lane>
|
||||||
</bpmn2:laneSet>
|
</bpmn2:laneSet>
|
||||||
|
@ -32,57 +36,76 @@
|
||||||
<bpmn2:boundaryEvent id="Boundary" name="Boundary" attachedToRef="Task_Boundary">
|
<bpmn2:boundaryEvent id="Boundary" name="Boundary" attachedToRef="Task_Boundary">
|
||||||
<bpmn2:outgoing>SequenceFlow_From_Boundary</bpmn2:outgoing>
|
<bpmn2:outgoing>SequenceFlow_From_Boundary</bpmn2:outgoing>
|
||||||
</bpmn2:boundaryEvent>
|
</bpmn2:boundaryEvent>
|
||||||
<bpmn2:sequenceFlow id="SequenceFlow" name="Flow" sourceRef="Task_Boundary" targetRef="Task" />
|
|
||||||
<bpmn2:sequenceFlow id="SequenceFlow_From_Boundary" name="" sourceRef="Boundary" targetRef="Task" />
|
<bpmn2:sequenceFlow id="SequenceFlow_From_Boundary" name="" sourceRef="Boundary" targetRef="Task" />
|
||||||
|
<bpmn2:sequenceFlow id="SequenceFlow" name="Flow" sourceRef="Task_Boundary" targetRef="Task" />
|
||||||
</bpmn2:process>
|
</bpmn2:process>
|
||||||
|
<bpmn2:process id="Process_0kzdcfx" isExecutable="false" />
|
||||||
|
<bpmn2:process id="Process_1nej7ck" isExecutable="false" />
|
||||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="_Collaboration_2">
|
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="_Collaboration_2">
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_Participant_2" bpmnElement="Participant_Lane" isHorizontal="true">
|
<bpmndi:BPMNShape id="_BPMNShape_Participant_2" bpmnElement="Participant_Lane" isHorizontal="true">
|
||||||
<dc:Bounds x="152" y="83" width="540" height="537" />
|
<dc:Bounds x="152" y="633" width="540" height="537" />
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_Boundary">
|
<bpmndi:BPMNShape id="_BPMNShape_Lane_3" bpmnElement="Lane_A" isHorizontal="true">
|
||||||
<dc:Bounds x="344" y="113" width="100" height="80" />
|
<dc:Bounds x="182" y="633" width="510" height="537" />
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_BoundaryEvent_2" bpmnElement="Boundary">
|
<bpmndi:BPMNShape id="_BPMNShape_Lane_4" bpmnElement="Nested_Lane_A" isHorizontal="true">
|
||||||
<dc:Bounds x="391" y="175" width="36" height="36" />
|
<dc:Bounds x="212" y="633" width="480" height="180" />
|
||||||
<bpmndi:BPMNLabel>
|
|
||||||
<dc:Bounds x="339" y="210" width="48" height="14" />
|
|
||||||
</bpmndi:BPMNLabel>
|
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_Task_3" bpmnElement="Task">
|
<bpmndi:BPMNShape id="_BPMNShape_Lane_5" bpmnElement="Nested_Lane_B" isHorizontal="true">
|
||||||
<dc:Bounds x="512" y="113" width="100" height="80" />
|
<dc:Bounds x="212" y="813" width="480" height="357" />
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_From_Boundary" sourceElement="_BPMNShape_BoundaryEvent_2" targetElement="_BPMNShape_Task_3">
|
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_From_Boundary" sourceElement="_BPMNShape_BoundaryEvent_2" targetElement="_BPMNShape_Task_3">
|
||||||
<di:waypoint x="409" y="211" />
|
<di:waypoint x="409" y="761" />
|
||||||
<di:waypoint x="409" y="238" />
|
<di:waypoint x="409" y="788" />
|
||||||
<di:waypoint x="562" y="238" />
|
<di:waypoint x="562" y="788" />
|
||||||
<di:waypoint x="562" y="193" />
|
<di:waypoint x="562" y="743" />
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="377" y="188" width="6" height="6" />
|
<dc:Bounds x="377" y="188" width="6" height="6" />
|
||||||
</bpmndi:BPMNLabel>
|
</bpmndi:BPMNLabel>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_2" bpmnElement="SequenceFlow" sourceElement="_BPMNShape_Task_2" targetElement="_BPMNShape_Task_3">
|
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_2" bpmnElement="SequenceFlow" sourceElement="_BPMNShape_Task_2" targetElement="_BPMNShape_Task_3">
|
||||||
<di:waypoint x="444" y="153" />
|
<di:waypoint x="444" y="703" />
|
||||||
<di:waypoint x="512" y="153" />
|
<di:waypoint x="512" y="703" />
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="466" y="135" width="25" height="14" />
|
<dc:Bounds x="467" y="685" width="24" height="14" />
|
||||||
</bpmndi:BPMNLabel>
|
</bpmndi:BPMNLabel>
|
||||||
</bpmndi:BPMNEdge>
|
</bpmndi:BPMNEdge>
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_3" bpmnElement="Lane_A" isHorizontal="true">
|
<bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_Boundary">
|
||||||
<dc:Bounds x="182" y="83" width="510" height="537" />
|
<dc:Bounds x="344" y="663" width="100" height="80" />
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_4" bpmnElement="Nested_Lane_A" isHorizontal="true">
|
<bpmndi:BPMNShape id="_BPMNShape_Task_3" bpmnElement="Task">
|
||||||
<dc:Bounds x="212" y="83" width="480" height="180" />
|
<dc:Bounds x="512" y="663" width="100" height="80" />
|
||||||
</bpmndi:BPMNShape>
|
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_Lane_5" bpmnElement="Nested_Lane_B" isHorizontal="true">
|
|
||||||
<dc:Bounds x="212" y="263" width="480" height="357" />
|
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
<bpmndi:BPMNShape id="Event_di" bpmnElement="Event">
|
<bpmndi:BPMNShape id="Event_di" bpmnElement="Event">
|
||||||
<dc:Bounds x="262" y="135" width="36" height="36" />
|
<dc:Bounds x="262" y="685" width="36" height="36" />
|
||||||
<bpmndi:BPMNLabel>
|
<bpmndi:BPMNLabel>
|
||||||
<dc:Bounds x="268" y="178" width="24" height="14" />
|
<dc:Bounds x="268" y="728" width="24" height="14" />
|
||||||
</bpmndi:BPMNLabel>
|
</bpmndi:BPMNLabel>
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="_BPMNShape_BoundaryEvent_2" bpmnElement="Boundary">
|
||||||
|
<dc:Bounds x="391" y="725" width="36" height="36" />
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<dc:Bounds x="339" y="760" width="48" height="14" />
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Participant_1nh1wgv_di" bpmnElement="ParticipantBelow" isHorizontal="true">
|
||||||
|
<dc:Bounds x="152" y="1500" width="600" height="250" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Participant_05yp9aj_di" bpmnElement="ParticipantAbove" isHorizontal="true">
|
||||||
|
<dc:Bounds x="152" y="80" width="600" height="250" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_1g3bwbi_di" bpmnElement="MessageFlowBelow">
|
||||||
|
<di:waypoint x="452" y="1500" />
|
||||||
|
<di:waypoint x="452" y="1170" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge id="Flow_0n2j5uv_di" bpmnElement="MessageFlowAbove">
|
||||||
|
<di:waypoint x="422" y="633" />
|
||||||
|
<di:waypoint x="422" y="330" />
|
||||||
|
<bpmndi:BPMNLabel>
|
||||||
|
<dc:Bounds x="393" y="479" width="88" height="27" />
|
||||||
|
</bpmndi:BPMNLabel>
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
</bpmndi:BPMNPlane>
|
</bpmndi:BPMNPlane>
|
||||||
</bpmndi:BPMNDiagram>
|
</bpmndi:BPMNDiagram>
|
||||||
</bpmn2:definitions>
|
</bpmn2:definitions>
|
||||||
|
|
|
@ -552,4 +552,119 @@ describe('features/modeling - layout', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('subProcess', function() {
|
||||||
|
|
||||||
|
var diagramXML = require('./LayoutSequenceFlowSpec.subProcess.bpmn');
|
||||||
|
|
||||||
|
var testModules = [ coreModule, modelingModule ];
|
||||||
|
|
||||||
|
beforeEach(bootstrapModeler(diagramXML, { modules: testModules }));
|
||||||
|
|
||||||
|
|
||||||
|
it('should layout straight between subProcesses (top -> bottom)', function() {
|
||||||
|
|
||||||
|
// when
|
||||||
|
var connection = connect('SubProcess_Center', 'SubProcess_Bottom'),
|
||||||
|
source = connection.source,
|
||||||
|
target = connection.target;
|
||||||
|
|
||||||
|
var expectedX = getMid(target).x;
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(connection).to.have.waypoints([
|
||||||
|
{ x: expectedX, y: source.y + source.height },
|
||||||
|
{ x: expectedX, y: target.y }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should layout straight between subProcesses (bottom -> top)', function() {
|
||||||
|
|
||||||
|
// when
|
||||||
|
var connection = connect('SubProcess_Bottom', 'SubProcess_Center'),
|
||||||
|
source = connection.source,
|
||||||
|
target = connection.target;
|
||||||
|
|
||||||
|
var expectedX = getMid(target).x;
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(connection).to.have.waypoints([
|
||||||
|
{ x: expectedX, y: source.y },
|
||||||
|
{ x: expectedX, y: target.y + target.height }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should layout straight between subProcess and task next to it (subProcess -> task)',
|
||||||
|
function() {
|
||||||
|
|
||||||
|
// when
|
||||||
|
var connection = connect('SubProcess_Center', 'Task_Right'),
|
||||||
|
source = connection.source,
|
||||||
|
target = connection.target;
|
||||||
|
|
||||||
|
var expectedY = getMid(target).y;
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(connection).to.have.waypoints([
|
||||||
|
{ x: source.x + source.width, y: expectedY },
|
||||||
|
{ x: target.x, y: expectedY }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
it('should layout straight between subProcess and task next to it (task -> subProcess)',
|
||||||
|
function() {
|
||||||
|
|
||||||
|
// when
|
||||||
|
var connection = connect('Task_Right', 'SubProcess_Center'),
|
||||||
|
source = connection.source,
|
||||||
|
target = connection.target;
|
||||||
|
|
||||||
|
var expectedY = getMid(source).y;
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(connection).to.have.waypoints([
|
||||||
|
{ x: source.x, y: expectedY },
|
||||||
|
{ x: target.x + target.width, y: expectedY }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
it('should layout straight between subProcess and task above (subProcess -> task)', function() {
|
||||||
|
|
||||||
|
// when
|
||||||
|
var connection = connect('SubProcess_Center', 'Task_Top'),
|
||||||
|
source = connection.source,
|
||||||
|
target = connection.target;
|
||||||
|
|
||||||
|
var expectedX = getMid(target).x;
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(connection).to.have.waypoints([
|
||||||
|
{ x: expectedX, y: source.y },
|
||||||
|
{ x: expectedX, y: target.y + target.height }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should layout straight between subProcess and task above (task -> subProcess)', function() {
|
||||||
|
|
||||||
|
// when
|
||||||
|
var connection = connect('Task_Top', 'SubProcess_Center'),
|
||||||
|
source = connection.source,
|
||||||
|
target = connection.target;
|
||||||
|
|
||||||
|
var expectedX = getMid(source).x;
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(connection).to.have.waypoints([
|
||||||
|
{ x: expectedX, y: source.y + source.height },
|
||||||
|
{ x: expectedX, y: target.y }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" id="Definitions_00dfyhw" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.1">
|
||||||
|
<bpmn:process id="Process_00i7uqd" isExecutable="true">
|
||||||
|
<bpmn:subProcess id="SubProcess_Center" />
|
||||||
|
<bpmn:subProcess id="SubProcess_Bottom" />
|
||||||
|
<bpmn:task id="Task_Right" />
|
||||||
|
<bpmn:task id="Task_Top" />
|
||||||
|
</bpmn:process>
|
||||||
|
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||||
|
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_00i7uqd">
|
||||||
|
<bpmndi:BPMNShape id="Activity_0r2w32m_di" bpmnElement="SubProcess_Center" isExpanded="true">
|
||||||
|
<dc:Bounds x="270" y="270" width="350" height="200" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_0tbriov_di" bpmnElement="SubProcess_Bottom" isExpanded="true">
|
||||||
|
<dc:Bounds x="160" y="600" width="350" height="200" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_0fm36cc_di" bpmnElement="Task_Right">
|
||||||
|
<dc:Bounds x="780" y="270" width="100" height="80" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape id="Activity_16fbgsj_di" bpmnElement="Task_Top">
|
||||||
|
<dc:Bounds x="520" y="110" width="100" height="80" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
</bpmndi:BPMNPlane>
|
||||||
|
</bpmndi:BPMNDiagram>
|
||||||
|
</bpmn:definitions>
|
|
@ -6,7 +6,7 @@ import {
|
||||||
/**
|
/**
|
||||||
* Create a fake key event for testing purposes.
|
* Create a fake key event for testing purposes.
|
||||||
*
|
*
|
||||||
* @param {String|Number} key the key or keyCode/charCode
|
* @param {string|number} key the key or keyCode/charCode
|
||||||
* @param {Object} [attrs]
|
* @param {Object} [attrs]
|
||||||
*
|
*
|
||||||
* @return {Event}
|
* @return {Event}
|
||||||
|
|
Loading…
Reference in New Issue