LabelUtil.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. import {
  2. assign
  3. } from 'min-dash';
  4. import { is } from './ModelUtil';
  5. import { isLabel } from 'diagram-js/lib/util/ModelUtil';
  6. export { isLabel } from 'diagram-js/lib/util/ModelUtil';
  7. /**
  8. * @typedef {import('diagram-js/lib/util/Types').Point} Point
  9. * @typedef {import('diagram-js/lib/util/Types').Rect} Rect
  10. *
  11. * @typedef {import('../model/Types').Element} Element
  12. * @typedef {import('../model/Types').ModdleElement} ModdleElement
  13. */
  14. export var DEFAULT_LABEL_SIZE = {
  15. width: 90,
  16. height: 20
  17. };
  18. export var FLOW_LABEL_INDENT = 15;
  19. /**
  20. * Return true if the given semantic has an external label.
  21. *
  22. * @param {Element} semantic
  23. *
  24. * @return {boolean}
  25. */
  26. export function isLabelExternal(semantic) {
  27. return is(semantic, 'bpmn:Event') ||
  28. is(semantic, 'bpmn:Gateway') ||
  29. is(semantic, 'bpmn:DataStoreReference') ||
  30. is(semantic, 'bpmn:DataObjectReference') ||
  31. is(semantic, 'bpmn:DataInput') ||
  32. is(semantic, 'bpmn:DataOutput') ||
  33. is(semantic, 'bpmn:SequenceFlow') ||
  34. is(semantic, 'bpmn:MessageFlow') ||
  35. is(semantic, 'bpmn:Group');
  36. }
  37. /**
  38. * Return true if the given element has an external label.
  39. *
  40. * @param {Element} element
  41. *
  42. * @return {boolean}
  43. */
  44. export function hasExternalLabel(element) {
  45. return isLabel(element.label);
  46. }
  47. /**
  48. * Get the position of a sequence flow label.
  49. *
  50. * @param {Point[]} waypoints
  51. *
  52. * @return {Point}
  53. */
  54. export function getFlowLabelPosition(waypoints) {
  55. // get the waypoints mid
  56. var mid = waypoints.length / 2 - 1;
  57. var first = waypoints[Math.floor(mid)];
  58. var second = waypoints[Math.ceil(mid + 0.01)];
  59. // get position
  60. var position = getWaypointsMid(waypoints);
  61. // calculate angle
  62. var angle = Math.atan((second.y - first.y) / (second.x - first.x));
  63. var x = position.x,
  64. y = position.y;
  65. if (Math.abs(angle) < Math.PI / 2) {
  66. y -= FLOW_LABEL_INDENT;
  67. } else {
  68. x += FLOW_LABEL_INDENT;
  69. }
  70. return { x: x, y: y };
  71. }
  72. /**
  73. * Get the middle of a number of waypoints.
  74. *
  75. * @param {Point[]} waypoints
  76. *
  77. * @return {Point}
  78. */
  79. export function getWaypointsMid(waypoints) {
  80. var mid = waypoints.length / 2 - 1;
  81. var first = waypoints[Math.floor(mid)];
  82. var second = waypoints[Math.ceil(mid + 0.01)];
  83. return {
  84. x: first.x + (second.x - first.x) / 2,
  85. y: first.y + (second.y - first.y) / 2
  86. };
  87. }
  88. /**
  89. * Get the middle of the external label of an element.
  90. *
  91. * @param {Element} element
  92. *
  93. * @return {Point}
  94. */
  95. export function getExternalLabelMid(element) {
  96. if (element.waypoints) {
  97. return getFlowLabelPosition(element.waypoints);
  98. } else if (is(element, 'bpmn:Group')) {
  99. return {
  100. x: element.x + element.width / 2,
  101. y: element.y + DEFAULT_LABEL_SIZE.height / 2
  102. };
  103. } else {
  104. return {
  105. x: element.x + element.width / 2,
  106. y: element.y + element.height + DEFAULT_LABEL_SIZE.height / 2
  107. };
  108. }
  109. }
  110. /**
  111. * Return the bounds of an elements label, parsed from the elements DI or
  112. * generated from its bounds.
  113. *
  114. * @param {ModdleElement} di
  115. * @param {Element} element
  116. *
  117. * @return {Rect}
  118. */
  119. export function getExternalLabelBounds(di, element) {
  120. var mid,
  121. size,
  122. bounds,
  123. label = di.label;
  124. if (label && label.bounds) {
  125. bounds = label.bounds;
  126. size = {
  127. width: Math.max(DEFAULT_LABEL_SIZE.width, bounds.width),
  128. height: bounds.height
  129. };
  130. mid = {
  131. x: bounds.x + bounds.width / 2,
  132. y: bounds.y + bounds.height / 2
  133. };
  134. } else {
  135. mid = getExternalLabelMid(element);
  136. size = DEFAULT_LABEL_SIZE;
  137. }
  138. return assign({
  139. x: mid.x - size.width / 2,
  140. y: mid.y - size.height / 2
  141. }, size);
  142. }
  143. /**
  144. * @param {ModdleElement} semantic
  145. *
  146. * @returns {string}
  147. */
  148. function getLabelAttr(semantic) {
  149. if (
  150. is(semantic, 'bpmn:FlowElement') ||
  151. is(semantic, 'bpmn:Participant') ||
  152. is(semantic, 'bpmn:Lane') ||
  153. is(semantic, 'bpmn:SequenceFlow') ||
  154. is(semantic, 'bpmn:MessageFlow') ||
  155. is(semantic, 'bpmn:DataInput') ||
  156. is(semantic, 'bpmn:DataOutput')
  157. ) {
  158. return 'name';
  159. }
  160. if (is(semantic, 'bpmn:TextAnnotation')) {
  161. return 'text';
  162. }
  163. if (is(semantic, 'bpmn:Group')) {
  164. return 'categoryValueRef';
  165. }
  166. }
  167. /**
  168. * @param {ModdleElement} semantic
  169. *
  170. * @returns {string}
  171. */
  172. function getCategoryValue(semantic) {
  173. var categoryValueRef = semantic['categoryValueRef'];
  174. if (!categoryValueRef) {
  175. return '';
  176. }
  177. return categoryValueRef.value || '';
  178. }
  179. /**
  180. * @param {Element} element
  181. *
  182. * @return {string}
  183. */
  184. export function getLabel(element) {
  185. var semantic = element.businessObject,
  186. attr = getLabelAttr(semantic);
  187. if (attr) {
  188. if (attr === 'categoryValueRef') {
  189. return getCategoryValue(semantic);
  190. }
  191. return semantic[attr] || '';
  192. }
  193. }
  194. /**
  195. * @param {Element} element
  196. * @param {string} text
  197. *
  198. * @return {Element}
  199. */
  200. export function setLabel(element, text) {
  201. var semantic = element.businessObject,
  202. attr = getLabelAttr(semantic);
  203. if (attr) {
  204. if (attr === 'categoryValueRef') {
  205. semantic['categoryValueRef'].value = text;
  206. } else {
  207. semantic[attr] = text;
  208. }
  209. }
  210. return element;
  211. }