Skip to content

Commit

Permalink
fix(space-tool): move and resize shapes in correct order
Browse files Browse the repository at this point in the history
  • Loading branch information
philippfromme committed Jun 13, 2019
1 parent 93e7a3e commit 1663305
Show file tree
Hide file tree
Showing 3 changed files with 1,539 additions and 1,283 deletions.
158 changes: 135 additions & 23 deletions lib/features/modeling/cmd/SpaceToolHandler.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,160 @@
import { forEach } from 'min-dash';
import {
forEach,
groupBy,
keys
} from 'min-dash';

import {
resizeBounds
} from '../../space-tool/SpaceUtil';


/**
* A handler that implements reversible creating and removing of space.
*
* It executes in two phases:
*
* (1) resize all affected resizeShapes
* (2) move all affected moveElements
* Add or remove space by moving and resizing shapes.
*/
export default function SpaceToolHandler(modeling) {
this._modeling = modeling;
}

SpaceToolHandler.$inject = [ 'modeling' ];

SpaceToolHandler.$inject = [
'modeling'
];

SpaceToolHandler.prototype.preExecute = function(context) {

// resize
var modeling = this._modeling,
var self = this,
movingShapes = context.movingShapes,
resizingShapes = context.resizingShapes,
delta = context.delta,
direction = context.direction;

forEach(resizingShapes, function(shape) {
var newBounds = resizeBounds(shape, direction, delta);
var addingSpace = isAddingSpace(delta, direction);

modeling.resizeShape(shape, newBounds);
var steps = getSteps(movingShapes, resizingShapes);

if (!addingSpace) {
steps = steps.reverse();
}

steps.forEach(function(step) {
var type = step.type,
shapes = step.shapes;

if (type === 'resize') {
self.resizeShapes(shapes, delta, direction);
} else if (type === 'move') {
self.moveShapes(shapes, delta);
}
});
};

SpaceToolHandler.prototype.postExecute = function(context) {
// move
var modeling = this._modeling,
movingShapes = context.movingShapes,
delta = context.delta;
SpaceToolHandler.prototype.execute = function() {};
SpaceToolHandler.prototype.revert = function() {};

SpaceToolHandler.prototype.moveShapes = function(shapes, delta) {
this._modeling.moveElements(shapes, delta, null, {
autoResize: false,
attach: false
});
};

SpaceToolHandler.prototype.resizeShapes = function(shapes, delta, direction) {
var self = this;

forEach(shapes, function(shape) {
var newBounds = resizeBounds(shape, direction, delta);

modeling.moveElements(movingShapes, delta, undefined, { autoResize: false, attach: false });
self._modeling.resizeShape(shape, newBounds);
});
};

SpaceToolHandler.prototype.execute = function(context) {};
SpaceToolHandler.prototype.revert = function(context) {};


// helpers //////////

function isAddingSpace(delta, direction) {
if (direction === 'n') {
return delta.y < 0;
} else if (direction === 'w') {
return delta.x < 0;
} else if (direction === 's') {
return delta.y >= 0;
} else if (direction === 'e') {
return delta.x >= 0;
}
}

/**
* Get steps for moving and resizing shapes starting with top-level shapes.
*
* @param {Array<djs.model.Shape>} movingShapes
* @param {Array<djs.model.Shape>} resizingShapes
*
* @returns {Array<Object>}
*/
export function getSteps(movingShapes, resizingShapes) {
var steps = [];

var groupedMovingShapes = groupBy(movingShapes, getIndex),
groupedResizingShapes = groupBy(resizingShapes, getIndex);

var maxIndex = max(keys(groupedMovingShapes).concat(keys(groupedResizingShapes)).concat(0));

var index = 1;

var parentIsMoving;

while (index <= maxIndex) {
if (groupedMovingShapes[ index ]) {
parentIsMoving = includes(movingShapes, first(groupedMovingShapes[ index ]).parent);

if (!parentIsMoving) {
steps.push({
type: 'move',
shapes: groupedMovingShapes[ index ]
});
}
}

if (groupedResizingShapes[ index ]) {
steps.push({
type: 'resize',
shapes: groupedResizingShapes[ index ]
});
}

index++;
}

return steps;
}

/**
* Get index of a given shape.
*
* @param {djs.model.Shape} shape
*
* @returns {number}
*/
function getIndex(shape) {
var index = 0;

while (shape.parent) {
index++;

shape = shape.parent;
}

return index;
}

function max(array) {
return Math.max.apply(null, array);
}

function includes(array, value) {
return array.indexOf(value) !== -1;
}

function first(array) {
return array.length && array[0];
}

0 comments on commit 1663305

Please sign in to comment.