diagram-js
Version:
A toolbox for displaying and modifying diagrams on the web
110 lines (89 loc) • 2.36 kB
JavaScript
import {
asTRBL,
getMid
} from '../../layout/LayoutUtil';
import { DEFAULT_DISTANCE } from './AutoPlaceUtil';
/**
* @typedef {import('../../core/Types').ShapeLike} Shape
*
* @typedef {import('../../util/Types').Point} Point
*
* @typedef {import('../../core/Canvas').default} Canvas
* @typedef {import('../../core/EventBus').default} EventBus
* @typedef {import('../modeling/Modeling').default} Modeling
*/
var LOW_PRIORITY = 100;
/**
* A service that places elements connected to existing ones
* to an appropriate position in an _automated_ fashion.
*
* @param {EventBus} eventBus
* @param {Modeling} modeling
* @param {Canvas} canvas
*/
export default function AutoPlace(eventBus, modeling, canvas) {
eventBus.on('autoPlace', LOW_PRIORITY, function(context) {
var shape = context.shape,
source = context.source;
return getNewShapePosition(source, shape);
});
eventBus.on('autoPlace.end', function(event) {
canvas.scrollToElement(event.shape);
});
/**
* Append shape to source at appropriate position.
*
* @param {Shape} source
* @param {Shape} shape
* @param {any} [hints={}]
*
* @return {Shape} appended shape
*/
this.append = function(source, shape, hints) {
eventBus.fire('autoPlace.start', {
source: source,
shape: shape
});
// allow others to provide the position
var position = eventBus.fire('autoPlace', {
source: source,
shape: shape
});
var newShape = modeling.appendShape(source, shape, position, source.parent, hints);
eventBus.fire('autoPlace.end', {
source: source,
shape: newShape
});
return newShape;
};
}
AutoPlace.$inject = [
'eventBus',
'modeling',
'canvas'
];
// helpers //////////
/**
* Find the new position for the target element to
* connect to source.
*
* @param {Shape} source
* @param {Shape} element
* @param {Object} [hints]
* @param {Object} [hints.defaultDistance]
*
* @return {Point}
*/
function getNewShapePosition(source, element, hints) {
if (!hints) {
hints = {};
}
var distance = hints.defaultDistance || DEFAULT_DISTANCE;
var sourceMid = getMid(source),
sourceTrbl = asTRBL(source);
// simply put element right next to source
return {
x: sourceTrbl.right + distance + element.width / 2,
y: sourceMid.y
};
}