115 lines
3.3 KiB
JavaScript
115 lines
3.3 KiB
JavaScript
'use strict';
|
|
|
|
var inherits = require('inherits');
|
|
|
|
var is = require('../../util/ModelUtil').is;
|
|
|
|
var pick = require('lodash/object/pick'),
|
|
assign = require('lodash/object/assign');
|
|
|
|
var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor');
|
|
|
|
var OFFSET = { top: 60, bottom: 60, left: 100, right: 100 };
|
|
var PADDING = { top: 2, bottom: 2, left: 15, right: 15 };
|
|
|
|
/**
|
|
* An auto resize component that takes care of expanding parent participants
|
|
* and lanes if an element is modeled close to an edge of the parent element.
|
|
*/
|
|
function AutoResize(eventBus, canvas, modeling){
|
|
|
|
CommandInterceptor.call(this, eventBus);
|
|
|
|
this.postExecuted([ 'shape.create', 'shape.move' ], function(event) {
|
|
var context = event.context,
|
|
shape = context.shape,
|
|
parent = context.parent || context.newParent;
|
|
|
|
expand(shape, parent);
|
|
});
|
|
|
|
/**
|
|
* Returns an object which indicates near which bounding edge(s)
|
|
* of a target an element is located.
|
|
*
|
|
* @param {Shape} element
|
|
* @param {Shape} target
|
|
* @param {Number} padding
|
|
*
|
|
* @return {Object} {top, bottom, left, right}
|
|
*
|
|
* @example
|
|
*
|
|
* // If an element is near the bottom left corner of a target the return object is:
|
|
* { top: false, bottom: true, left: true, right: false }
|
|
*
|
|
*/
|
|
function isInbounds(element, target, padding) {
|
|
return {
|
|
top: element.y < target.y + padding.top && element.y + element.height > target.y,
|
|
bottom: element.y < target.y + target.height &&
|
|
element.y + element.height > target.y + target.height - padding.bottom,
|
|
left: element.x < target.x + padding.left && element.x + element.width > target.x,
|
|
right: element.x < target.x + target.width &&
|
|
element.x + element.width > target.x + target.width - padding.right,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Expand target elements if the moved element is near or on an edge, considering the position
|
|
* of the element edge in relation to the parent's edge plus padding. The amount to expand
|
|
* can be defined for each edge in the OFFSET variables.
|
|
*
|
|
* @param {Shape} shape
|
|
* @param {Shape} target
|
|
*/
|
|
function expand(shape, target) {
|
|
|
|
if (is(shape, 'bpmn:Lane')) {
|
|
return;
|
|
}
|
|
|
|
if (shape.labelTarget) {
|
|
return;
|
|
}
|
|
|
|
if (!is(target, 'bpmn:Participant') && !is(target, 'bpmn:Lane')) {
|
|
return;
|
|
}
|
|
|
|
if (target !== shape.parent) {
|
|
return;
|
|
}
|
|
|
|
var inbounds = isInbounds(shape, target, PADDING);
|
|
|
|
var newBounds = pick(target, [ 'x', 'y', 'width', 'height' ]);
|
|
|
|
if (inbounds.top) {
|
|
var topPosition = shape.y - OFFSET.top;
|
|
assign(newBounds, { y: topPosition, height: target.height + target.y - topPosition });
|
|
}
|
|
|
|
if (inbounds.bottom) {
|
|
assign(newBounds, { height: shape.y + shape.height + OFFSET.bottom - target.y });
|
|
}
|
|
|
|
if (inbounds.left) {
|
|
var leftPosition = shape.x - OFFSET.left;
|
|
assign(newBounds, { x: leftPosition, width: target.width + target.x - leftPosition });
|
|
}
|
|
|
|
if (inbounds.right) {
|
|
assign(newBounds, { width: shape.x + shape.width + OFFSET.right - target.x });
|
|
}
|
|
|
|
modeling.resizeShape(target, newBounds);
|
|
}
|
|
}
|
|
|
|
AutoResize.$inject = [ 'eventBus', 'canvas', 'modeling' ];
|
|
|
|
inherits(AutoResize, CommandInterceptor);
|
|
|
|
module.exports = AutoResize;
|