UpdateFlowNodeRefsHandler.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import {
  2. collectLanes,
  3. getLanesRoot
  4. } from '../util/LaneUtil';
  5. import {
  6. is
  7. } from '../../../util/ModelUtil';
  8. import {
  9. add as collectionAdd,
  10. remove as collectionRemove
  11. } from 'diagram-js/lib/util/Collections';
  12. import {
  13. asTRBL
  14. } from 'diagram-js/lib/layout/LayoutUtil';
  15. var FLOW_NODE_REFS_ATTR = 'flowNodeRef',
  16. LANES_ATTR = 'lanes';
  17. /**
  18. * A handler that updates lane refs on changed elements
  19. */
  20. export default function UpdateFlowNodeRefsHandler(elementRegistry) {
  21. this._elementRegistry = elementRegistry;
  22. }
  23. UpdateFlowNodeRefsHandler.$inject = [
  24. 'elementRegistry'
  25. ];
  26. UpdateFlowNodeRefsHandler.prototype.computeUpdates = function(flowNodeShapes, laneShapes) {
  27. var handledNodes = [];
  28. var updates = [];
  29. var participantCache = {};
  30. var allFlowNodeShapes = [];
  31. function isInLaneShape(element, laneShape) {
  32. var laneTrbl = asTRBL(laneShape);
  33. var elementMid = {
  34. x: element.x + element.width / 2,
  35. y: element.y + element.height / 2
  36. };
  37. return elementMid.x > laneTrbl.left &&
  38. elementMid.x < laneTrbl.right &&
  39. elementMid.y > laneTrbl.top &&
  40. elementMid.y < laneTrbl.bottom;
  41. }
  42. function addFlowNodeShape(flowNodeShape) {
  43. if (handledNodes.indexOf(flowNodeShape) === -1) {
  44. allFlowNodeShapes.push(flowNodeShape);
  45. handledNodes.push(flowNodeShape);
  46. }
  47. }
  48. function getAllLaneShapes(flowNodeShape) {
  49. var root = getLanesRoot(flowNodeShape);
  50. if (!participantCache[root.id]) {
  51. participantCache[root.id] = collectLanes(root);
  52. }
  53. return participantCache[root.id];
  54. }
  55. function getNewLanes(flowNodeShape) {
  56. if (!flowNodeShape.parent) {
  57. return [];
  58. }
  59. var allLaneShapes = getAllLaneShapes(flowNodeShape);
  60. return allLaneShapes.filter(function(l) {
  61. return isInLaneShape(flowNodeShape, l);
  62. }).map(function(shape) {
  63. return shape.businessObject;
  64. });
  65. }
  66. laneShapes.forEach(function(laneShape) {
  67. var root = getLanesRoot(laneShape);
  68. if (!root || handledNodes.indexOf(root) !== -1) {
  69. return;
  70. }
  71. var children = root.children.filter(function(c) {
  72. return is(c, 'bpmn:FlowNode');
  73. });
  74. children.forEach(addFlowNodeShape);
  75. handledNodes.push(root);
  76. });
  77. flowNodeShapes.forEach(addFlowNodeShape);
  78. allFlowNodeShapes.forEach(function(flowNodeShape) {
  79. var flowNode = flowNodeShape.businessObject;
  80. var lanes = flowNode.get(LANES_ATTR),
  81. remove = lanes.slice(),
  82. add = getNewLanes(flowNodeShape);
  83. updates.push({ flowNode: flowNode, remove: remove, add: add });
  84. });
  85. laneShapes.forEach(function(laneShape) {
  86. var lane = laneShape.businessObject;
  87. // lane got removed XX-)
  88. if (!laneShape.parent) {
  89. lane.get(FLOW_NODE_REFS_ATTR).forEach(function(flowNode) {
  90. updates.push({ flowNode: flowNode, remove: [ lane ], add: [] });
  91. });
  92. }
  93. });
  94. return updates;
  95. };
  96. UpdateFlowNodeRefsHandler.prototype.execute = function(context) {
  97. var updates = context.updates;
  98. if (!updates) {
  99. updates = context.updates = this.computeUpdates(context.flowNodeShapes, context.laneShapes);
  100. }
  101. updates.forEach(function(update) {
  102. var flowNode = update.flowNode,
  103. lanes = flowNode.get(LANES_ATTR);
  104. // unwire old
  105. update.remove.forEach(function(oldLane) {
  106. collectionRemove(lanes, oldLane);
  107. collectionRemove(oldLane.get(FLOW_NODE_REFS_ATTR), flowNode);
  108. });
  109. // wire new
  110. update.add.forEach(function(newLane) {
  111. collectionAdd(lanes, newLane);
  112. collectionAdd(newLane.get(FLOW_NODE_REFS_ATTR), flowNode);
  113. });
  114. });
  115. // TODO(nikku): return changed elements
  116. // return [ ... ];
  117. };
  118. UpdateFlowNodeRefsHandler.prototype.revert = function(context) {
  119. var updates = context.updates;
  120. updates.forEach(function(update) {
  121. var flowNode = update.flowNode,
  122. lanes = flowNode.get(LANES_ATTR);
  123. // unwire new
  124. update.add.forEach(function(newLane) {
  125. collectionRemove(lanes, newLane);
  126. collectionRemove(newLane.get(FLOW_NODE_REFS_ATTR), flowNode);
  127. });
  128. // wire old
  129. update.remove.forEach(function(oldLane) {
  130. collectionAdd(lanes, oldLane);
  131. collectionAdd(oldLane.get(FLOW_NODE_REFS_ATTR), flowNode);
  132. });
  133. });
  134. // TODO(nikku): return changed elements
  135. // return [ ... ];
  136. };