ToggleElementCollapseBehaviour.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import inherits from 'inherits-browser';
  2. import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
  3. import {
  4. getDi,
  5. is
  6. } from '../../../util/ModelUtil';
  7. import {
  8. computeChildrenBBox
  9. } from 'diagram-js/lib/features/resize/ResizeUtil';
  10. /**
  11. * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
  12. * @typedef {import('../ElementFactory').default} ElementFactory
  13. * @typedef {import('../Modeling').default} Modeling
  14. */
  15. var LOW_PRIORITY = 500;
  16. /**
  17. * @param {EventBus} eventBus
  18. * @param {ElementFactory} elementFactory
  19. * @param {Modeling} modeling
  20. */
  21. export default function ToggleElementCollapseBehaviour(
  22. eventBus, elementFactory, modeling) {
  23. CommandInterceptor.call(this, eventBus);
  24. function hideEmptyLabels(children) {
  25. if (children.length) {
  26. children.forEach(function(child) {
  27. if (child.type === 'label' && !child.businessObject.name) {
  28. child.hidden = true;
  29. }
  30. });
  31. }
  32. }
  33. function expandedBounds(shape, defaultSize) {
  34. var children = shape.children,
  35. newBounds = defaultSize,
  36. visibleElements,
  37. visibleBBox;
  38. visibleElements = filterVisible(children).concat([ shape ]);
  39. visibleBBox = computeChildrenBBox(visibleElements);
  40. if (visibleBBox) {
  41. // center to visibleBBox with max(defaultSize, childrenBounds)
  42. newBounds.width = Math.max(visibleBBox.width, newBounds.width);
  43. newBounds.height = Math.max(visibleBBox.height, newBounds.height);
  44. newBounds.x = visibleBBox.x + (visibleBBox.width - newBounds.width) / 2;
  45. newBounds.y = visibleBBox.y + (visibleBBox.height - newBounds.height) / 2;
  46. } else {
  47. // center to collapsed shape with defaultSize
  48. newBounds.x = shape.x + (shape.width - newBounds.width) / 2;
  49. newBounds.y = shape.y + (shape.height - newBounds.height) / 2;
  50. }
  51. return newBounds;
  52. }
  53. function collapsedBounds(shape, defaultSize) {
  54. return {
  55. x: shape.x + (shape.width - defaultSize.width) / 2,
  56. y: shape.y + (shape.height - defaultSize.height) / 2,
  57. width: defaultSize.width,
  58. height: defaultSize.height
  59. };
  60. }
  61. this.executed([ 'shape.toggleCollapse' ], LOW_PRIORITY, function(e) {
  62. var context = e.context,
  63. shape = context.shape;
  64. if (!is(shape, 'bpmn:SubProcess')) {
  65. return;
  66. }
  67. if (!shape.collapsed) {
  68. // all children got made visible through djs, hide empty labels
  69. hideEmptyLabels(shape.children);
  70. // remove collapsed marker
  71. getDi(shape).isExpanded = true;
  72. } else {
  73. // place collapsed marker
  74. getDi(shape).isExpanded = false;
  75. }
  76. });
  77. this.reverted([ 'shape.toggleCollapse' ], LOW_PRIORITY, function(e) {
  78. var context = e.context;
  79. var shape = context.shape;
  80. // revert removing/placing collapsed marker
  81. if (!shape.collapsed) {
  82. getDi(shape).isExpanded = true;
  83. } else {
  84. getDi(shape).isExpanded = false;
  85. }
  86. });
  87. this.postExecuted([ 'shape.toggleCollapse' ], LOW_PRIORITY, function(e) {
  88. var shape = e.context.shape,
  89. defaultSize = elementFactory.getDefaultSize(shape),
  90. newBounds;
  91. if (shape.collapsed) {
  92. // resize to default size of collapsed shapes
  93. newBounds = collapsedBounds(shape, defaultSize);
  94. } else {
  95. // resize to bounds of max(visible children, defaultSize)
  96. newBounds = expandedBounds(shape, defaultSize);
  97. }
  98. modeling.resizeShape(shape, newBounds, null, {
  99. autoResize: shape.collapsed ? false : 'nwse'
  100. });
  101. });
  102. }
  103. inherits(ToggleElementCollapseBehaviour, CommandInterceptor);
  104. ToggleElementCollapseBehaviour.$inject = [
  105. 'eventBus',
  106. 'elementFactory',
  107. 'modeling'
  108. ];
  109. // helpers //////////////////////
  110. function filterVisible(elements) {
  111. return elements.filter(function(e) {
  112. return !e.hidden;
  113. });
  114. }