MoveHelper.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import {
  2. forEach
  3. } from 'min-dash';
  4. import {
  5. getMovedSourceAnchor,
  6. getMovedTargetAnchor
  7. } from './AnchorsHelper';
  8. import MoveClosure from './MoveClosure';
  9. /**
  10. * A helper that is able to carry out serialized move
  11. * operations on multiple elements.
  12. *
  13. * @param {Modeling} modeling
  14. */
  15. export default function MoveHelper(modeling) {
  16. this._modeling = modeling;
  17. }
  18. /**
  19. * Move the specified elements and all children by the given delta.
  20. *
  21. * This moves all enclosed connections, too and layouts all affected
  22. * external connections.
  23. *
  24. * @param {Array<djs.model.Base>} elements
  25. * @param {Point} delta
  26. * @param {djs.model.Base} newParent applied to the first level of shapes
  27. *
  28. * @return {Array<djs.model.Base>} list of touched elements
  29. */
  30. MoveHelper.prototype.moveRecursive = function(elements, delta, newParent) {
  31. if (!elements) {
  32. return [];
  33. } else {
  34. return this.moveClosure(this.getClosure(elements), delta, newParent);
  35. }
  36. };
  37. /**
  38. * Move the given closure of elmements.
  39. *
  40. * @param {Object} closure
  41. * @param {Point} delta
  42. * @param {djs.model.Base} [newParent]
  43. * @param {djs.model.Base} [newHost]
  44. */
  45. MoveHelper.prototype.moveClosure = function(closure, delta, newParent, newHost, primaryShape) {
  46. var modeling = this._modeling;
  47. var allShapes = closure.allShapes,
  48. allConnections = closure.allConnections,
  49. enclosedConnections = closure.enclosedConnections,
  50. topLevel = closure.topLevel,
  51. keepParent = false;
  52. if (primaryShape && primaryShape.parent === newParent) {
  53. keepParent = true;
  54. }
  55. // move all shapes
  56. forEach(allShapes, function(shape) {
  57. // move the element according to the given delta
  58. modeling.moveShape(shape, delta, topLevel[shape.id] && !keepParent && newParent, {
  59. recurse: false,
  60. layout: false
  61. });
  62. });
  63. // move all child connections / layout external connections
  64. forEach(allConnections, function(c) {
  65. var sourceMoved = !!allShapes[c.source.id],
  66. targetMoved = !!allShapes[c.target.id];
  67. if (enclosedConnections[c.id] && sourceMoved && targetMoved) {
  68. modeling.moveConnection(c, delta, topLevel[c.id] && !keepParent && newParent);
  69. } else {
  70. modeling.layoutConnection(c, {
  71. connectionStart: sourceMoved && getMovedSourceAnchor(c, c.source, delta),
  72. connectionEnd: targetMoved && getMovedTargetAnchor(c, c.target, delta)
  73. });
  74. }
  75. });
  76. };
  77. /**
  78. * Returns the closure for the selected elements
  79. *
  80. * @param {Array<djs.model.Base>} elements
  81. * @return {MoveClosure} closure
  82. */
  83. MoveHelper.prototype.getClosure = function(elements) {
  84. return new MoveClosure().addAll(elements, true);
  85. };