ResizeSnapping.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import SnapContext from './SnapContext';
  2. import {
  3. bottomRight,
  4. getChildren,
  5. isSnapped,
  6. setSnapped,
  7. topLeft,
  8. } from './SnapUtil';
  9. import { isCmd } from '../keyboard/KeyboardUtil';
  10. import {
  11. asTRBL,
  12. getMid
  13. } from '../../layout/LayoutUtil';
  14. import { forEach } from 'min-dash';
  15. var HIGHER_PRIORITY = 1250;
  16. /**
  17. * Snap during resize.
  18. *
  19. * @param {EventBus} eventBus
  20. * @param {Snapping} snapping
  21. */
  22. export default function ResizeSnapping(eventBus, snapping) {
  23. var self = this;
  24. eventBus.on([ 'resize.start' ], function(event) {
  25. self.initSnap(event);
  26. });
  27. eventBus.on([
  28. 'resize.move',
  29. 'resize.end',
  30. ], HIGHER_PRIORITY, function(event) {
  31. var context = event.context,
  32. shape = context.shape,
  33. parent = shape.parent,
  34. direction = context.direction,
  35. snapContext = context.snapContext;
  36. if (event.originalEvent && isCmd(event.originalEvent)) {
  37. return;
  38. }
  39. if (isSnapped(event)) {
  40. return;
  41. }
  42. var snapPoints = snapContext.pointsForTarget(parent);
  43. if (!snapPoints.initialized) {
  44. snapPoints = self.addSnapTargetPoints(snapPoints, shape, parent, direction);
  45. snapPoints.initialized = true;
  46. }
  47. if (isHorizontal(direction)) {
  48. setSnapped(event, 'x', event.x);
  49. }
  50. if (isVertical(direction)) {
  51. setSnapped(event, 'y', event.y);
  52. }
  53. snapping.snap(event, snapPoints);
  54. });
  55. eventBus.on([ 'resize.cleanup' ], function() {
  56. snapping.hide();
  57. });
  58. }
  59. ResizeSnapping.prototype.initSnap = function(event) {
  60. var context = event.context,
  61. shape = context.shape,
  62. direction = context.direction,
  63. snapContext = context.snapContext;
  64. if (!snapContext) {
  65. snapContext = context.snapContext = new SnapContext();
  66. }
  67. var snapOrigin = getSnapOrigin(shape, direction);
  68. snapContext.setSnapOrigin('corner', {
  69. x: snapOrigin.x - event.x,
  70. y: snapOrigin.y - event.y
  71. });
  72. return snapContext;
  73. };
  74. ResizeSnapping.prototype.addSnapTargetPoints = function(snapPoints, shape, target, direction) {
  75. var snapTargets = this.getSnapTargets(shape, target);
  76. forEach(snapTargets, function(snapTarget) {
  77. snapPoints.add('corner', bottomRight(snapTarget));
  78. snapPoints.add('corner', topLeft(snapTarget));
  79. });
  80. snapPoints.add('corner', getSnapOrigin(shape, direction));
  81. return snapPoints;
  82. };
  83. ResizeSnapping.$inject = [
  84. 'eventBus',
  85. 'snapping'
  86. ];
  87. ResizeSnapping.prototype.getSnapTargets = function(shape, target) {
  88. return getChildren(target).filter(function(child) {
  89. return !isAttached(child, shape)
  90. && !isConnection(child)
  91. && !isHidden(child)
  92. && !isLabel(child);
  93. });
  94. };
  95. // helpers //////////
  96. function getSnapOrigin(shape, direction) {
  97. var mid = getMid(shape),
  98. trbl = asTRBL(shape);
  99. var snapOrigin = {
  100. x: mid.x,
  101. y: mid.y
  102. };
  103. if (direction.indexOf('n') !== -1) {
  104. snapOrigin.y = trbl.top;
  105. } else if (direction.indexOf('s') !== -1) {
  106. snapOrigin.y = trbl.bottom;
  107. }
  108. if (direction.indexOf('e') !== -1) {
  109. snapOrigin.x = trbl.right;
  110. } else if (direction.indexOf('w') !== -1) {
  111. snapOrigin.x = trbl.left;
  112. }
  113. return snapOrigin;
  114. }
  115. function isAttached(element, host) {
  116. return element.host === host;
  117. }
  118. function isConnection(element) {
  119. return !!element.waypoints;
  120. }
  121. function isHidden(element) {
  122. return !!element.hidden;
  123. }
  124. function isLabel(element) {
  125. return !!element.labelTarget;
  126. }
  127. function isHorizontal(direction) {
  128. return direction === 'n' || direction === 's';
  129. }
  130. function isVertical(direction) {
  131. return direction === 'e' || direction === 'w';
  132. }