vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
4.5 KiB

  1. /**
  2. * Definitions for param's in jsdoc.
  3. * These are more or less global within Network. Putting them here until I can figure out
  4. * where to really put them
  5. *
  6. * @typedef {string|number} Id
  7. * @typedef {Id} NodeId
  8. * @typedef {Id} EdgeId
  9. * @typedef {Id} LabelId
  10. *
  11. * @typedef {{x: number, y: number}} point
  12. * @typedef {{left: number, top: number, width: number, height: number}} rect
  13. * @typedef {{x: number, y:number, angle: number}} rotationPoint
  14. * - point to rotate around and the angle in radians to rotate. angle == 0 means no rotation
  15. * @typedef {{nodeId:NodeId}} nodeClickItem
  16. * @typedef {{nodeId:NodeId, labelId:LabelId}} nodeLabelClickItem
  17. * @typedef {{edgeId:EdgeId}} edgeClickItem
  18. * @typedef {{edgeId:EdgeId, labelId:LabelId}} edgeLabelClickItem
  19. */
  20. let util = require("../../../../util");
  21. /**
  22. * Helper functions for components
  23. * @class
  24. */
  25. class ComponentUtil {
  26. /**
  27. * Determine values to use for (sub)options of 'chosen'.
  28. *
  29. * This option is either a boolean or an object whose values should be examined further.
  30. * The relevant structures are:
  31. *
  32. * - chosen: <boolean value>
  33. * - chosen: { subOption: <boolean or function> }
  34. *
  35. * Where subOption is 'node', 'edge' or 'label'.
  36. *
  37. * The intention of this method appears to be to set a specific priority to the options;
  38. * Since most properties are either bridged or merged into the local options objects, there
  39. * is not much point in handling them separately.
  40. * TODO: examine if 'most' in previous sentence can be replaced with 'all'. In that case, we
  41. * should be able to get rid of this method.
  42. *
  43. * @param {string} subOption option within object 'chosen' to consider; either 'node', 'edge' or 'label'
  44. * @param {Object} pile array of options objects to consider
  45. *
  46. * @return {boolean|function} value for passed subOption of 'chosen' to use
  47. */
  48. static choosify(subOption, pile) {
  49. // allowed values for subOption
  50. let allowed = [ 'node', 'edge', 'label'];
  51. let value = true;
  52. let chosen = util.topMost(pile, 'chosen');
  53. if (typeof chosen === 'boolean') {
  54. value = chosen;
  55. } else if (typeof chosen === 'object') {
  56. if (allowed.indexOf(subOption) === -1 ) {
  57. throw new Error('choosify: subOption \'' + subOption + '\' should be one of '
  58. + "'" + allowed.join("', '") + "'");
  59. }
  60. let chosenEdge = util.topMost(pile, ['chosen', subOption]);
  61. if ((typeof chosenEdge === 'boolean') || (typeof chosenEdge === 'function')) {
  62. value = chosenEdge;
  63. }
  64. }
  65. return value;
  66. }
  67. /**
  68. * Check if the point falls within the given rectangle.
  69. *
  70. * @param {rect} rect
  71. * @param {point} point
  72. * @param {rotationPoint} [rotationPoint] if specified, the rotation that applies to the rectangle.
  73. * @returns {boolean} true if point within rectangle, false otherwise
  74. * @static
  75. */
  76. static pointInRect(rect, point, rotationPoint) {
  77. if (rect.width <= 0 || rect.height <= 0) {
  78. return false; // early out
  79. }
  80. if (rotationPoint !== undefined) {
  81. // Rotate the point the same amount as the rectangle
  82. var tmp = {
  83. x: point.x - rotationPoint.x,
  84. y: point.y - rotationPoint.y
  85. };
  86. if (rotationPoint.angle !== 0) {
  87. // In order to get the coordinates the same, you need to
  88. // rotate in the reverse direction
  89. var angle = -rotationPoint.angle;
  90. var tmp2 = {
  91. x: Math.cos(angle)*tmp.x - Math.sin(angle)*tmp.y,
  92. y: Math.sin(angle)*tmp.x + Math.cos(angle)*tmp.y
  93. };
  94. point = tmp2;
  95. } else {
  96. point = tmp;
  97. }
  98. // Note that if a rotation is specified, the rectangle coordinates
  99. // are **not* the full canvas coordinates. They are relative to the
  100. // rotationPoint. Hence, the point coordinates need not be translated
  101. // back in this case.
  102. }
  103. var right = rect.x + rect.width;
  104. var bottom = rect.y + rect.width;
  105. return (
  106. rect.left < point.x &&
  107. right > point.x &&
  108. rect.top < point.y &&
  109. bottom > point.y
  110. );
  111. }
  112. /**
  113. * Check if given value is acceptable as a label text.
  114. *
  115. * @param {*} text value to check; can be anything at this point
  116. * @returns {boolean} true if valid label value, false otherwise
  117. */
  118. static isValidLabel(text) {
  119. // Note that this is quite strict: types that *might* be converted to string are disallowed
  120. return (typeof text === 'string' && text !== '');
  121. }
  122. }
  123. export default ComponentUtil;