UpdateFlowNodeRefsBehavior.js 2.8 KB

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