123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- import {
- filter,
- isNumber
- } from 'min-dash';
- var max = Math.max,
- min = Math.min;
- var DEFAULT_CHILD_BOX_PADDING = 20;
- import {
- getBBox
- } from '../../util/Elements';
- import {
- asTRBL,
- asBounds
- } from '../../layout/LayoutUtil';
- /**
- * Substract a TRBL from another
- *
- * @param {TRBL} trblA
- * @param {TRBL} trblB
- *
- * @return {TRBL}
- */
- export function substractTRBL(trblA, trblB) {
- return {
- top: trblA.top - trblB.top,
- right: trblA.right - trblB.right,
- bottom: trblA.bottom - trblB.bottom,
- left: trblA.left - trblB.left
- };
- }
- /**
- * Resize the given bounds by the specified delta from a given anchor point.
- *
- * @param {Bounds} bounds the bounding box that should be resized
- * @param {String} direction in which the element is resized (nw, ne, se, sw)
- * @param {Point} delta of the resize operation
- *
- * @return {Bounds} resized bounding box
- */
- export function resizeBounds(bounds, direction, delta) {
- var dx = delta.x,
- dy = delta.y;
- switch (direction) {
- case 'nw':
- return {
- x: bounds.x + dx,
- y: bounds.y + dy,
- width: bounds.width - dx,
- height: bounds.height - dy
- };
- case 'sw':
- return {
- x: bounds.x + dx,
- y: bounds.y,
- width: bounds.width - dx,
- height: bounds.height + dy
- };
- case 'ne':
- return {
- x: bounds.x,
- y: bounds.y + dy,
- width: bounds.width + dx,
- height: bounds.height - dy
- };
- case 'se':
- return {
- x: bounds.x,
- y: bounds.y,
- width: bounds.width + dx,
- height: bounds.height + dy
- };
- default:
- throw new Error('unrecognized direction: ' + direction);
- }
- }
- /**
- * Resize the given bounds by applying the passed
- * { top, right, bottom, left } delta.
- *
- * @param {Bounds} bounds
- * @param {TRBL} trblResize
- *
- * @return {Bounds}
- */
- export function resizeTRBL(bounds, resize) {
- return {
- x: bounds.x + (resize.left || 0),
- y: bounds.y + (resize.top || 0),
- width: bounds.width - (resize.left || 0) + (resize.right || 0),
- height: bounds.height - (resize.top || 0) + (resize.bottom || 0)
- };
- }
- export function reattachPoint(bounds, newBounds, point) {
- var sx = bounds.width / newBounds.width,
- sy = bounds.height / newBounds.height;
- return {
- x: Math.round((newBounds.x + newBounds.width / 2)) - Math.floor(((bounds.x + bounds.width / 2) - point.x) / sx),
- y: Math.round((newBounds.y + newBounds.height / 2)) - Math.floor(((bounds.y + bounds.height / 2) - point.y) / sy)
- };
- }
- function applyConstraints(attr, trbl, resizeConstraints) {
- var value = trbl[attr],
- minValue = resizeConstraints.min && resizeConstraints.min[attr],
- maxValue = resizeConstraints.max && resizeConstraints.max[attr];
- if (isNumber(minValue)) {
- value = (/top|left/.test(attr) ? min : max)(value, minValue);
- }
- if (isNumber(maxValue)) {
- value = (/top|left/.test(attr) ? max : min)(value, maxValue);
- }
- return value;
- }
- export function ensureConstraints(currentBounds, resizeConstraints) {
- if (!resizeConstraints) {
- return currentBounds;
- }
- var currentTrbl = asTRBL(currentBounds);
- return asBounds({
- top: applyConstraints('top', currentTrbl, resizeConstraints),
- right: applyConstraints('right', currentTrbl, resizeConstraints),
- bottom: applyConstraints('bottom', currentTrbl, resizeConstraints),
- left: applyConstraints('left', currentTrbl, resizeConstraints)
- });
- }
- export function getMinResizeBounds(direction, currentBounds, minDimensions, childrenBounds) {
- var currentBox = asTRBL(currentBounds);
- var minBox = {
- top: /n/.test(direction) ? currentBox.bottom - minDimensions.height : currentBox.top,
- left: /w/.test(direction) ? currentBox.right - minDimensions.width : currentBox.left,
- bottom: /s/.test(direction) ? currentBox.top + minDimensions.height : currentBox.bottom,
- right: /e/.test(direction) ? currentBox.left + minDimensions.width : currentBox.right
- };
- var childrenBox = childrenBounds ? asTRBL(childrenBounds) : minBox;
- var combinedBox = {
- top: min(minBox.top, childrenBox.top),
- left: min(minBox.left, childrenBox.left),
- bottom: max(minBox.bottom, childrenBox.bottom),
- right: max(minBox.right, childrenBox.right)
- };
- return asBounds(combinedBox);
- }
- function asPadding(mayBePadding, defaultValue) {
- if (typeof mayBePadding !== 'undefined') {
- return mayBePadding;
- } else {
- return DEFAULT_CHILD_BOX_PADDING;
- }
- }
- export function addPadding(bbox, padding) {
- var left, right, top, bottom;
- if (typeof padding === 'object') {
- left = asPadding(padding.left);
- right = asPadding(padding.right);
- top = asPadding(padding.top);
- bottom = asPadding(padding.bottom);
- } else {
- left = right = top = bottom = asPadding(padding);
- }
- return {
- x: bbox.x - left,
- y: bbox.y - top,
- width: bbox.width + left + right,
- height: bbox.height + top + bottom
- };
- }
- /**
- * Is the given element part of the resize
- * targets min boundary box?
- *
- * This is the default implementation which excludes
- * connections and labels.
- *
- * @param {djs.model.Base} element
- */
- function isBBoxChild(element) {
- // exclude connections
- if (element.waypoints) {
- return false;
- }
- // exclude labels
- if (element.type === 'label') {
- return false;
- }
- return true;
- }
- /**
- * Return children bounding computed from a shapes children
- * or a list of prefiltered children.
- *
- * @param {djs.model.Shape|Array<djs.model.Shape>} shapeOrChildren
- * @param {Number|Object} padding
- *
- * @return {Bounds}
- */
- export function computeChildrenBBox(shapeOrChildren, padding) {
- var elements;
- // compute based on shape
- if (shapeOrChildren.length === undefined) {
- // grab all the children that are part of the
- // parents children box
- elements = filter(shapeOrChildren.children, isBBoxChild);
- } else {
- elements = shapeOrChildren;
- }
- if (elements.length) {
- return addPadding(getBBox(elements), padding);
- }
- }
|