BpmnAutoPlaceUtil.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import { is } from '../../util/ModelUtil';
  2. import { isAny } from '../modeling/util/ModelingUtil';
  3. import {
  4. getMid,
  5. asTRBL,
  6. getOrientation
  7. } from 'diagram-js/lib/layout/LayoutUtil';
  8. import {
  9. findFreePosition,
  10. generateGetNextPosition,
  11. getConnectedDistance
  12. } from 'diagram-js/lib/features/auto-place/AutoPlaceUtil';
  13. import { isConnection } from 'diagram-js/lib/util/ModelUtil';
  14. /**
  15. * @typedef {import('../../model/Types').Shape} Shape
  16. *
  17. * @typedef {import('diagram-js/lib/util/Types').Point} Point
  18. * @typedef {import('diagram-js/lib/util/Types').DirectionTRBL} DirectionTRBL
  19. */
  20. /**
  21. * Get the position for given new target relative to the source it will be
  22. * connected to.
  23. *
  24. * @param {Shape} source
  25. * @param {Shape} element
  26. *
  27. * @return {Point}
  28. */
  29. export function getNewShapePosition(source, element) {
  30. if (is(element, 'bpmn:TextAnnotation')) {
  31. return getTextAnnotationPosition(source, element);
  32. }
  33. if (isAny(element, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ])) {
  34. return getDataElementPosition(source, element);
  35. }
  36. if (is(element, 'bpmn:FlowNode')) {
  37. return getFlowNodePosition(source, element);
  38. }
  39. }
  40. /**
  41. * Get the position for given new flow node. Try placing the flow node right of
  42. * the source.
  43. *
  44. * @param {Shape} source
  45. * @param {Shape} element
  46. *
  47. * @return {Point}
  48. */
  49. export function getFlowNodePosition(source, element) {
  50. var sourceTrbl = asTRBL(source);
  51. var sourceMid = getMid(source);
  52. var horizontalDistance = getConnectedDistance(source, {
  53. filter: function(connection) {
  54. return is(connection, 'bpmn:SequenceFlow');
  55. }
  56. });
  57. var margin = 30,
  58. minDistance = 80,
  59. orientation = 'left';
  60. if (is(source, 'bpmn:BoundaryEvent')) {
  61. orientation = getOrientation(source, source.host, -25);
  62. if (orientation.indexOf('top') !== -1) {
  63. margin *= -1;
  64. }
  65. }
  66. var position = {
  67. x: sourceTrbl.right + horizontalDistance + element.width / 2,
  68. y: sourceMid.y + getVerticalDistance(orientation, minDistance)
  69. };
  70. var nextPositionDirection = {
  71. y: {
  72. margin: margin,
  73. minDistance: minDistance
  74. }
  75. };
  76. return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
  77. }
  78. /**
  79. * @param {DirectionTRBL} orientation
  80. * @param {number} minDistance
  81. *
  82. * @return {number}
  83. */
  84. function getVerticalDistance(orientation, minDistance) {
  85. if (orientation.includes('top')) {
  86. return -1 * minDistance;
  87. } else if (orientation.includes('bottom')) {
  88. return minDistance;
  89. } else {
  90. return 0;
  91. }
  92. }
  93. /**
  94. * Get the position for given text annotation. Try placing the text annotation
  95. * top-right of the source.
  96. *
  97. * @param {Shape} source
  98. * @param {Shape} element
  99. *
  100. * @return {Point}
  101. */
  102. export function getTextAnnotationPosition(source, element) {
  103. var sourceTrbl = asTRBL(source);
  104. var position = {
  105. x: sourceTrbl.right + element.width / 2,
  106. y: sourceTrbl.top - 50 - element.height / 2
  107. };
  108. if (isConnection(source)) {
  109. position = getMid(source);
  110. position.x += 100;
  111. position.y -= 50;
  112. }
  113. var nextPositionDirection = {
  114. y: {
  115. margin: -30,
  116. minDistance: 20
  117. }
  118. };
  119. return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
  120. }
  121. /**
  122. * Get the position for given new data element. Try placing the data element
  123. * bottom-right of the source.
  124. *
  125. * @param {Shape} source
  126. * @param {Shape} element
  127. *
  128. * @return {Point}
  129. */
  130. export function getDataElementPosition(source, element) {
  131. var sourceTrbl = asTRBL(source);
  132. var position = {
  133. x: sourceTrbl.right - 10 + element.width / 2,
  134. y: sourceTrbl.bottom + 40 + element.width / 2
  135. };
  136. var nextPositionDirection = {
  137. x: {
  138. margin: 30,
  139. minDistance: 30
  140. }
  141. };
  142. return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
  143. }