BpmnOrderingProvider.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import inherits from 'inherits';
  2. import OrderingProvider from 'diagram-js/lib/features/ordering/OrderingProvider';
  3. import {
  4. isAny
  5. } from '../modeling/util/ModelingUtil';
  6. import {
  7. findIndex,
  8. find
  9. } from 'min-dash';
  10. /**
  11. * a simple ordering provider that makes sure:
  12. *
  13. * (0) labels are rendered always on top
  14. * (1) elements are ordered by a {level} property
  15. */
  16. export default function BpmnOrderingProvider(eventBus, canvas, translate) {
  17. OrderingProvider.call(this, eventBus);
  18. var orders = [
  19. { type: 'bpmn:SubProcess', order: { level: 6 } },
  20. {
  21. type: 'bpmn:SequenceFlow',
  22. order: {
  23. level: 3,
  24. containers: [
  25. 'bpmn:Participant',
  26. 'bpmn:FlowElementsContainer'
  27. ]
  28. }
  29. },
  30. // handle DataAssociation(s) like message flows and render them always on top
  31. {
  32. type: 'bpmn:DataAssociation',
  33. order: {
  34. level: 9,
  35. containers: [
  36. 'bpmn:Collaboration',
  37. 'bpmn:Process'
  38. ]
  39. }
  40. },
  41. {
  42. type: 'bpmn:MessageFlow', order: {
  43. level: 9,
  44. containers: [ 'bpmn:Collaboration' ]
  45. }
  46. },
  47. {
  48. type: 'bpmn:Association',
  49. order: {
  50. level: 6,
  51. containers: [
  52. 'bpmn:Participant',
  53. 'bpmn:FlowElementsContainer',
  54. 'bpmn:Collaboration'
  55. ]
  56. }
  57. },
  58. { type: 'bpmn:BoundaryEvent', order: { level: 8 } },
  59. { type: 'bpmn:FlowElement', order: { level: 5 } },
  60. { type: 'bpmn:Participant', order: { level: -2 } },
  61. { type: 'bpmn:Lane', order: { level: -1 } }
  62. ];
  63. function computeOrder(element) {
  64. if (element.labelTarget) {
  65. return { level: 10 };
  66. }
  67. var entry = find(orders, function(o) {
  68. return isAny(element, [ o.type ]);
  69. });
  70. return entry && entry.order || { level: 1 };
  71. }
  72. function getOrder(element) {
  73. var order = element.order;
  74. if (!order) {
  75. element.order = order = computeOrder(element);
  76. }
  77. return order;
  78. }
  79. function findActualParent(element, newParent, containers) {
  80. var actualParent = newParent;
  81. while (actualParent) {
  82. if (isAny(actualParent, containers)) {
  83. break;
  84. }
  85. actualParent = actualParent.parent;
  86. }
  87. if (!actualParent) {
  88. throw new Error(translate('no parent for {element} in {parent}', {
  89. element: element.id,
  90. parent: newParent.id
  91. }));
  92. }
  93. return actualParent;
  94. }
  95. this.getOrdering = function(element, newParent) {
  96. // render labels always on top
  97. if (element.labelTarget) {
  98. return {
  99. parent: canvas.getRootElement(),
  100. index: -1
  101. };
  102. }
  103. var elementOrder = getOrder(element);
  104. if (elementOrder.containers) {
  105. newParent = findActualParent(element, newParent, elementOrder.containers);
  106. }
  107. var currentIndex = newParent.children.indexOf(element);
  108. var insertIndex = findIndex(newParent.children, function(child) {
  109. // do not compare with labels, they are created
  110. // in the wrong order (right after elements) during import and
  111. // mess up the positioning.
  112. if (!element.labelTarget && child.labelTarget) {
  113. return false;
  114. }
  115. return elementOrder.level < getOrder(child).level;
  116. });
  117. // if the element is already in the child list at
  118. // a smaller index, we need to adjust the inser index.
  119. // this takes into account that the element is being removed
  120. // before being re-inserted
  121. if (insertIndex !== -1) {
  122. if (currentIndex !== -1 && currentIndex < insertIndex) {
  123. insertIndex -= 1;
  124. }
  125. }
  126. return {
  127. index: insertIndex,
  128. parent: newParent
  129. };
  130. };
  131. }
  132. BpmnOrderingProvider.$inject = [ 'eventBus', 'canvas', 'translate' ];
  133. inherits(BpmnOrderingProvider, OrderingProvider);