chore(import): factor out import logic to own component

This commit extracts the main import logic found in import/Importer into
the core/BpmnImporter module. By doing so we we are able to reuse it
during modeling.

Related to #6
This commit is contained in:
Nico Rehwaldt 2014-06-30 17:01:00 +02:00
parent 90e3e86237
commit 921de712d2
2 changed files with 189 additions and 147 deletions

179
lib/core/BpmnImporter.js Normal file
View File

@ -0,0 +1,179 @@
'use strict';
var _ = require('lodash');
function hasLabel(semantic) {
return semantic.$instanceOf('bpmn:Event') ||
semantic.$instanceOf('bpmn:Gateway') ||
semantic.$instanceOf('bpmn:DataStoreReference') ||
semantic.$instanceOf('bpmn:DataObjectReference') ||
semantic.$instanceOf('bpmn:SequenceFlow') ||
semantic.$instanceOf('bpmn:MessageFlow');
}
function isCollapsed(semantic, di) {
return semantic.$instanceOf('bpmn:SubProcess') && di && !di.isExpanded;
}
function getWaypointsMid(waypoints) {
var mid = waypoints.length / 2 - 1;
var first = waypoints[Math.floor(mid)];
var second = waypoints[Math.ceil(mid + 0.01)];
return {
x: first.x + (second.x - first.x) / 2,
y: first.y + (second.y - first.y) / 2
};
}
/**
* Returns the bounds of an elements label, parsed from the elements DI or
* generated from its bounds.
*/
function getLabelBounds(di, data) {
var mid,
size;
var label = di.label;
if (label && label.bounds) {
var bounds = label.bounds;
size = {
width: Math.max(150, bounds.width),
height: bounds.height
};
mid = {
x: bounds.x + bounds.width / 2,
y: bounds.y
};
} else {
if (data.waypoints) {
mid = getWaypointsMid(data.waypoints);
} else {
mid = {
x: data.x + data.width / 2,
y: data.y + data.height - 5
};
}
size = {
width: 90,
height: 50
};
}
return _.extend({
x: mid.x - size.width / 2,
y: mid.y
}, size);
}
/**
* An importer that adds bpmn elements to the canvas
*
* @param {EventBus} eventBus
* @param {Canvas} canvas
*/
function BpmnImporter(eventBus, canvas) {
this._eventBus = eventBus;
this._canvas = canvas;
}
BpmnImporter.$inject = [ 'eventBus', 'canvas' ];
/**
* Add bpmn element (semantic, di) to the canvas onto the
* specified parent element.
*/
BpmnImporter.prototype.add = function(semantic, di, parent) {
var events = this._eventBus,
canvas = this._canvas;
var shape;
/**
* fire element specific event
*/
function fire(type, shape) {
events.fire('bpmn.element.' + type, {
semantic: semantic, di: di, diagramElement: shape
});
}
/**
* add label for the element
*/
function addLabel(semantic, di, data) {
if (!hasLabel(semantic)) {
return;
}
var labelBounds = getLabelBounds(di, data);
var label = _.extend({
id: semantic.id + '_label',
attachedId: semantic.id,
type: 'label',
hidden: data.hidden
}, labelBounds);
canvas.addShape(label);
// we wire data and label so that
// the label of a BPMN element can be quickly accessed via
// element.label in various components
data.label = label;
}
if (di.$type === 'bpmndi:BPMNShape') {
var bounds = di.bounds;
var collapsed = isCollapsed(semantic, di);
var hidden = parent && (parent.hidden || parent.collapsed);
shape = {
id: semantic.id, type: semantic.$type,
x: bounds.x, y: bounds.y,
width: bounds.width, height: bounds.height,
collapsed: collapsed,
hidden: hidden,
parent: parent
};
fire('add', shape);
canvas.addShape(shape);
} else {
var waypoints = _.collect(di.waypoint, function(p) {
return { x: p.x, y: p.y };
});
shape = { id: semantic.id, type: semantic.$type, waypoints: waypoints };
fire('add', shape);
canvas.addConnection(shape);
}
fire('added', shape);
// add label if needed
addLabel(semantic, di, shape);
return shape;
};
module.exports = BpmnImporter;

View File

@ -1,164 +1,27 @@
'use strict';
var _ = require('lodash');
var BpmnTreeWalker = require('./BpmnTreeWalker'),
Util = require('../Util');
function hasLabel(element) {
return element.$instanceOf('bpmn:Event') ||
element.$instanceOf('bpmn:Gateway') ||
element.$instanceOf('bpmn:DataStoreReference') ||
element.$instanceOf('bpmn:DataObjectReference') ||
element.$instanceOf('bpmn:SequenceFlow') ||
element.$instanceOf('bpmn:MessageFlow');
}
function isCollapsed(element, di) {
return element.$instanceOf('bpmn:SubProcess') && di && !di.isExpanded;
}
function getWaypointsMid(waypoints) {
var mid = waypoints.length / 2 - 1;
var first = waypoints[Math.floor(mid)];
var second = waypoints[Math.ceil(mid + 0.01)];
return {
x: first.x + (second.x - first.x) / 2,
y: first.y + (second.y - first.y) / 2
};
}
var BpmnTreeWalker = require('./BpmnTreeWalker');
/**
* Returns the bounds of an elements label, parsed from the elements DI or
* generated from its bounds.
* Import the definitions into the given diagram, reporting errors and warnings
* via the specified callback.
*
* @param {Diagram} diagram
* @param {ModdleElement} definitions
* @param {Function} done the callback, invoked with (err, [ warning ]) once the import is done
*/
function getLabelBounds(di, data) {
var mid,
size;
var label = di.label;
if (label && label.bounds) {
var bounds = label.bounds;
size = {
width: Math.max(150, bounds.width),
height: bounds.height
};
mid = {
x: bounds.x + bounds.width / 2,
y: bounds.y
};
} else {
if (data.waypoints) {
mid = getWaypointsMid(data.waypoints);
} else {
mid = {
x: data.x + data.width / 2,
y: data.y + data.height - 5
};
}
size = {
width: 90,
height: 50
};
}
return _.extend({
x: mid.x - size.width / 2,
y: mid.y
}, size);
}
function importBpmnDiagram(diagram, definitions, done) {
var canvas = diagram.get('canvas');
var events = diagram.get('eventBus');
var commandStack = diagram.get('commandStack');
function addLabel(element, di, data) {
if (!hasLabel(element)) {
return;
}
var labelBounds = getLabelBounds(di, data);
var label = _.extend({
id: element.id + '_label',
attachedId: element.id,
type: 'label',
hidden: data.hidden
}, labelBounds);
canvas.addShape(label);
// we wire data and label so that
// the label of a BPMN element can be quickly accessed via
// element.label in various components
data.label = label;
}
var importer = diagram.get('bpmnImporter'),
commandStack = diagram.get('commandStack');
var warnings = [];
var visitor = {
element: function(element, di, parent) {
var shape;
function fire(type, shape) {
events.fire('bpmn.element.' + type, {
semantic: element, di: di, diagramElement: shape
});
}
if (di.$type === 'bpmndi:BPMNShape') {
var bounds = di.bounds;
var collapsed = isCollapsed(element, di);
var hidden = parent && (parent.hidden || parent.collapsed);
shape = {
id: element.id, type: element.$type,
x: bounds.x, y: bounds.y,
width: bounds.width, height: bounds.height,
collapsed: collapsed,
hidden: hidden,
parent: parent
};
fire('add', shape);
canvas.addShape(shape);
} else {
var waypoints = _.collect(di.waypoint, function(p) {
return { x: p.x, y: p.y };
});
shape = { id: element.id, type: element.$type, waypoints: waypoints };
fire('add', shape);
canvas.addConnection(shape);
}
fire('added', shape);
// add label if needed
addLabel(element, di, shape);
return shape;
return importer.add(element, di, parent);
},
error: function(message, context) {