BpmnAutoPlaceUtil.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. /**
  14. * Find the new position for the target element to
  15. * connect to source.
  16. *
  17. * @param {djs.model.Shape} source
  18. * @param {djs.model.Shape} element
  19. *
  20. * @return {Point}
  21. */
  22. export function getNewShapePosition(source, element) {
  23. if (is(element, 'bpmn:TextAnnotation')) {
  24. return getTextAnnotationPosition(source, element);
  25. }
  26. if (isAny(element, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ])) {
  27. return getDataElementPosition(source, element);
  28. }
  29. if (is(element, 'bpmn:FlowNode')) {
  30. return getFlowNodePosition(source, element);
  31. }
  32. }
  33. /**
  34. * Always try to place element right of source;
  35. * compute actual distance from previous nodes in flow.
  36. */
  37. export function getFlowNodePosition(source, element) {
  38. var sourceTrbl = asTRBL(source);
  39. var sourceMid = getMid(source);
  40. var horizontalDistance = getConnectedDistance(source, {
  41. filter: function(connection) {
  42. return is(connection, 'bpmn:SequenceFlow');
  43. }
  44. });
  45. var margin = 30,
  46. minDistance = 80,
  47. orientation = 'left';
  48. if (is(source, 'bpmn:BoundaryEvent')) {
  49. orientation = getOrientation(source, source.host, -25);
  50. if (orientation.indexOf('top') !== -1) {
  51. margin *= -1;
  52. }
  53. }
  54. var position = {
  55. x: sourceTrbl.right + horizontalDistance + element.width / 2,
  56. y: sourceMid.y + getVerticalDistance(orientation, minDistance)
  57. };
  58. var nextPositionDirection = {
  59. y: {
  60. margin: margin,
  61. minDistance: minDistance
  62. }
  63. };
  64. return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
  65. }
  66. function getVerticalDistance(orientation, minDistance) {
  67. if (orientation.indexOf('top') != -1) {
  68. return -1 * minDistance;
  69. } else if (orientation.indexOf('bottom') != -1) {
  70. return minDistance;
  71. } else {
  72. return 0;
  73. }
  74. }
  75. /**
  76. * Always try to place text annotations top right of source.
  77. */
  78. export function getTextAnnotationPosition(source, element) {
  79. var sourceTrbl = asTRBL(source);
  80. var position = {
  81. x: sourceTrbl.right + element.width / 2,
  82. y: sourceTrbl.top - 50 - element.height / 2
  83. };
  84. var nextPositionDirection = {
  85. y: {
  86. margin: -30,
  87. minDistance: 20
  88. }
  89. };
  90. return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
  91. }
  92. /**
  93. * Always put element bottom right of source.
  94. */
  95. export function getDataElementPosition(source, element) {
  96. var sourceTrbl = asTRBL(source);
  97. var position = {
  98. x: sourceTrbl.right - 10 + element.width / 2,
  99. y: sourceTrbl.bottom + 40 + element.width / 2
  100. };
  101. var nextPositionDirection = {
  102. x: {
  103. margin: 30,
  104. minDistance: 30
  105. }
  106. };
  107. return findFreePosition(source, element, position, generateGetNextPosition(nextPositionDirection));
  108. }