ResizeHandles.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. import {
  2. bind,
  3. forEach
  4. } from 'min-dash';
  5. var HANDLE_OFFSET = -2,
  6. HANDLE_SIZE = 5,
  7. HANDLE_HIT_SIZE = 20;
  8. var CLS_RESIZER = 'djs-resizer';
  9. import {
  10. append as svgAppend,
  11. attr as svgAttr,
  12. classes as svgClasses,
  13. clear as svgClear,
  14. create as svgCreate
  15. } from 'tiny-svg';
  16. import {
  17. event as domEvent
  18. } from 'min-dom';
  19. import {
  20. isPrimaryButton
  21. } from '../../util/Mouse';
  22. import {
  23. asTRBL
  24. } from '../../layout/LayoutUtil';
  25. import {
  26. transform
  27. } from '../../util/SvgTransformUtil';
  28. /**
  29. * This component is responsible for adding resize handles.
  30. *
  31. * @param {EventBus} eventBus
  32. * @param {Canvas} canvas
  33. * @param {Selection} selection
  34. * @param {Resize} resize
  35. */
  36. export default function ResizeHandles(eventBus, canvas, selection, resize) {
  37. this._resize = resize;
  38. this._canvas = canvas;
  39. var self = this;
  40. eventBus.on('selection.changed', function(e) {
  41. var newSelection = e.newSelection;
  42. // remove old selection markers
  43. self.removeResizers();
  44. // add new selection markers ONLY if single selection
  45. if (newSelection.length === 1) {
  46. forEach(newSelection, bind(self.addResizer, self));
  47. }
  48. });
  49. eventBus.on('shape.changed', function(e) {
  50. var shape = e.element;
  51. if (selection.isSelected(shape)) {
  52. self.removeResizers();
  53. self.addResizer(shape);
  54. }
  55. });
  56. }
  57. ResizeHandles.prototype.makeDraggable = function(element, gfx, direction) {
  58. var resize = this._resize;
  59. function startResize(event) {
  60. // only trigger on left mouse button
  61. if (isPrimaryButton(event)) {
  62. resize.activate(event, element, direction);
  63. }
  64. }
  65. domEvent.bind(gfx, 'mousedown', startResize);
  66. domEvent.bind(gfx, 'touchstart', startResize);
  67. };
  68. ResizeHandles.prototype._createResizer = function(element, x, y, rotation, direction) {
  69. var resizersParent = this._getResizersParent();
  70. var group = svgCreate('g');
  71. svgClasses(group).add(CLS_RESIZER);
  72. svgClasses(group).add(CLS_RESIZER + '-' + element.id);
  73. svgClasses(group).add(CLS_RESIZER + '-' + direction);
  74. svgAppend(resizersParent, group);
  75. var origin = -HANDLE_SIZE + HANDLE_OFFSET;
  76. // Create four drag indicators on the outline
  77. var visual = svgCreate('rect');
  78. svgAttr(visual, {
  79. x: origin,
  80. y: origin,
  81. width: HANDLE_SIZE,
  82. height: HANDLE_SIZE
  83. });
  84. svgClasses(visual).add(CLS_RESIZER + '-visual');
  85. svgAppend(group, visual);
  86. var hit = svgCreate('rect');
  87. svgAttr(hit, {
  88. x: origin,
  89. y: origin,
  90. width: HANDLE_HIT_SIZE,
  91. height: HANDLE_HIT_SIZE
  92. });
  93. svgClasses(hit).add(CLS_RESIZER + '-hit');
  94. svgAppend(group, hit);
  95. transform(group, x, y, rotation);
  96. return group;
  97. };
  98. ResizeHandles.prototype.createResizer = function(element, direction) {
  99. var resizer;
  100. var trbl = asTRBL(element);
  101. if (direction === 'nw') {
  102. resizer = this._createResizer(element, trbl.left, trbl.top, 0, direction);
  103. } else if (direction === 'ne') {
  104. resizer = this._createResizer(element, trbl.right, trbl.top, 90, direction);
  105. } else if (direction === 'se') {
  106. resizer = this._createResizer(element, trbl.right, trbl.bottom, 180, direction);
  107. } else {
  108. resizer = this._createResizer(element, trbl.left, trbl.bottom, 270, direction);
  109. }
  110. this.makeDraggable(element, resizer, direction);
  111. };
  112. // resize handles implementation ///////////////////////////////
  113. /**
  114. * Add resizers for a given element.
  115. *
  116. * @param {djs.model.Shape} shape
  117. */
  118. ResizeHandles.prototype.addResizer = function(shape) {
  119. var resize = this._resize;
  120. if (!resize.canResize({ shape: shape })) {
  121. return;
  122. }
  123. this.createResizer(shape, 'nw');
  124. this.createResizer(shape, 'ne');
  125. this.createResizer(shape, 'se');
  126. this.createResizer(shape, 'sw');
  127. };
  128. /**
  129. * Remove all resizers
  130. */
  131. ResizeHandles.prototype.removeResizers = function() {
  132. var resizersParent = this._getResizersParent();
  133. svgClear(resizersParent);
  134. };
  135. ResizeHandles.prototype._getResizersParent = function() {
  136. return this._canvas.getLayer('resizers');
  137. };
  138. ResizeHandles.$inject = [
  139. 'eventBus',
  140. 'canvas',
  141. 'selection',
  142. 'resize'
  143. ];