123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- import {
- filter,
- forEach,
- sortBy
- } from 'min-dash';
- function last(arr) {
- return arr && arr[arr.length - 1];
- }
- function sortTopOrMiddle(element) {
- return element.y;
- }
- function sortLeftOrCenter(element) {
- return element.x;
- }
- /**
- * Sorting functions for different types of alignment
- *
- * @type {Object}
- *
- * @return {Function}
- */
- var ALIGNMENT_SORTING = {
- left: sortLeftOrCenter,
- center: sortLeftOrCenter,
- right: function(element) {
- return element.x + element.width;
- },
- top: sortTopOrMiddle,
- middle: sortTopOrMiddle,
- bottom: function(element) {
- return element.y + element.height;
- }
- };
- export default function AlignElements(modeling) {
- this._modeling = modeling;
- }
- AlignElements.$inject = [ 'modeling' ];
- /**
- * Get the relevant "axis" and "dimension" related to the current type of alignment
- *
- * @param {String} type left|right|center|top|bottom|middle
- *
- * @return {Object} { axis, dimension }
- */
- AlignElements.prototype._getOrientationDetails = function(type) {
- var vertical = [ 'top', 'bottom', 'middle' ],
- axis = 'x',
- dimension = 'width';
- if (vertical.indexOf(type) !== -1) {
- axis = 'y';
- dimension = 'height';
- }
- return {
- axis: axis,
- dimension: dimension
- };
- };
- AlignElements.prototype._isType = function(type, types) {
- return types.indexOf(type) !== -1;
- };
- /**
- * Get a point on the relevant axis where elements should align to
- *
- * @param {String} type left|right|center|top|bottom|middle
- * @param {Array} sortedElements
- *
- * @return {Object}
- */
- AlignElements.prototype._alignmentPosition = function(type, sortedElements) {
- var orientation = this._getOrientationDetails(type),
- axis = orientation.axis,
- dimension = orientation.dimension,
- alignment = {},
- centers = {},
- hasSharedCenters = false,
- centeredElements,
- firstElement,
- lastElement;
- function getMiddleOrTop(first, last) {
- return Math.round((first[axis] + last[axis] + last[dimension]) / 2);
- }
- if (this._isType(type, [ 'left', 'top' ])) {
- alignment[type] = sortedElements[0][axis];
- } else if (this._isType(type, [ 'right', 'bottom' ])) {
- lastElement = last(sortedElements);
- alignment[type] = lastElement[axis] + lastElement[dimension];
- } else if (this._isType(type, [ 'center', 'middle' ])) {
- // check if there is a center shared by more than one shape
- // if not, just take the middle of the range
- forEach(sortedElements, function(element) {
- var center = element[axis] + Math.round(element[dimension] / 2);
- if (centers[center]) {
- centers[center].elements.push(element);
- } else {
- centers[center] = {
- elements: [ element ],
- center: center
- };
- }
- });
- centeredElements = sortBy(centers, function(center) {
- if (center.elements.length > 1) {
- hasSharedCenters = true;
- }
- return center.elements.length;
- });
- if (hasSharedCenters) {
- alignment[type] = last(centeredElements).center;
- return alignment;
- }
- firstElement = sortedElements[0];
- sortedElements = sortBy(sortedElements, function(element) {
- return element[axis] + element[dimension];
- });
- lastElement = last(sortedElements);
- alignment[type] = getMiddleOrTop(firstElement, lastElement);
- }
- return alignment;
- };
- /**
- * Executes the alignment of a selection of elements
- *
- * @param {Array} elements [description]
- * @param {String} type left|right|center|top|bottom|middle
- */
- AlignElements.prototype.trigger = function(elements, type) {
- var modeling = this._modeling;
- var filteredElements = filter(elements, function(element) {
- return !(element.waypoints || element.host || element.labelTarget);
- });
- var sortFn = ALIGNMENT_SORTING[type];
- var sortedElements = sortBy(filteredElements, sortFn);
- var alignment = this._alignmentPosition(type, sortedElements);
- modeling.alignElements(sortedElements, alignment);
- };
|