UpdateFlowNodeRefsBehavior.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import inherits from 'inherits-browser';
  2. import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
  3. import {
  4. is
  5. } from '../../../util/ModelUtil';
  6. /**
  7. * @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
  8. * @typedef {import('../Modeling').default} Modeling
  9. * @typedef {import('diagram-js/lib/i18n/translate/translate').default} Translate
  10. */
  11. var LOW_PRIORITY = 500,
  12. HIGH_PRIORITY = 5000;
  13. /**
  14. * BPMN specific delete lane behavior.
  15. *
  16. * @param {EventBus} eventBus
  17. * @param {Modeling} modeling
  18. * @param {Translate} translate
  19. */
  20. export default function UpdateFlowNodeRefsBehavior(eventBus, modeling, translate) {
  21. CommandInterceptor.call(this, eventBus);
  22. /**
  23. * Update Lane#flowNodeRefs and FlowNode#lanes with every flow node
  24. * move/resize and lane move/resize. Groups elements to recompute containments
  25. * as efficient as possible.
  26. */
  27. // the update context
  28. var context;
  29. function initContext() {
  30. context = context || new UpdateContext();
  31. context.enter();
  32. return context;
  33. }
  34. function getContext() {
  35. if (!context) {
  36. throw new Error(translate('out of bounds release'));
  37. }
  38. return context;
  39. }
  40. function releaseContext() {
  41. if (!context) {
  42. throw new Error(translate('out of bounds release'));
  43. }
  44. var triggerUpdate = context.leave();
  45. if (triggerUpdate) {
  46. modeling.updateLaneRefs(context.flowNodes, context.lanes);
  47. context = null;
  48. }
  49. return triggerUpdate;
  50. }
  51. var laneRefUpdateEvents = [
  52. 'spaceTool',
  53. 'lane.add',
  54. 'lane.resize',
  55. 'lane.split',
  56. 'elements.create',
  57. 'elements.delete',
  58. 'elements.move',
  59. 'shape.create',
  60. 'shape.delete',
  61. 'shape.move',
  62. 'shape.resize'
  63. ];
  64. // listen to a lot of stuff to group lane updates
  65. this.preExecute(laneRefUpdateEvents, HIGH_PRIORITY, function(event) {
  66. initContext();
  67. });
  68. this.postExecuted(laneRefUpdateEvents, LOW_PRIORITY, function(event) {
  69. releaseContext();
  70. });
  71. // Mark flow nodes + lanes that need an update
  72. this.preExecute([
  73. 'shape.create',
  74. 'shape.move',
  75. 'shape.delete',
  76. 'shape.resize'
  77. ], function(event) {
  78. var context = event.context,
  79. shape = context.shape;
  80. var updateContext = getContext();
  81. // no need to update labels
  82. if (shape.labelTarget) {
  83. return;
  84. }
  85. if (is(shape, 'bpmn:Lane')) {
  86. updateContext.addLane(shape);
  87. }
  88. if (is(shape, 'bpmn:FlowNode')) {
  89. updateContext.addFlowNode(shape);
  90. }
  91. });
  92. }
  93. UpdateFlowNodeRefsBehavior.$inject = [
  94. 'eventBus',
  95. 'modeling' ,
  96. 'translate'
  97. ];
  98. inherits(UpdateFlowNodeRefsBehavior, CommandInterceptor);
  99. function UpdateContext() {
  100. this.flowNodes = [];
  101. this.lanes = [];
  102. this.counter = 0;
  103. this.addLane = function(lane) {
  104. this.lanes.push(lane);
  105. };
  106. this.addFlowNode = function(flowNode) {
  107. this.flowNodes.push(flowNode);
  108. };
  109. this.enter = function() {
  110. this.counter++;
  111. };
  112. this.leave = function() {
  113. this.counter--;
  114. return !this.counter;
  115. };
  116. }