mxCellOverlay.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /**
  2. * Copyright (c) 2006-2015, JGraph Ltd
  3. * Copyright (c) 2006-2015, Gaudenz Alder
  4. */
  5. /**
  6. * Class: mxCellOverlay
  7. *
  8. * Extends <mxEventSource> to implement a graph overlay, represented by an icon
  9. * and a tooltip. Overlays can handle and fire <click> events and are added to
  10. * the graph using <mxGraph.addCellOverlay>, and removed using
  11. * <mxGraph.removeCellOverlay>, or <mxGraph.removeCellOverlays> to remove all overlays.
  12. * The <mxGraph.getCellOverlays> function returns the array of overlays for a given
  13. * cell in a graph. If multiple overlays exist for the same cell, then
  14. * <getBounds> should be overridden in at least one of the overlays.
  15. *
  16. * Overlays appear on top of all cells in a special layer. If this is not
  17. * desirable, then the image must be rendered as part of the shape or label of
  18. * the cell instead.
  19. *
  20. * Example:
  21. *
  22. * The following adds a new overlays for a given vertex and selects the cell
  23. * if the overlay is clicked.
  24. *
  25. * (code)
  26. * var overlay = new mxCellOverlay(img, html);
  27. * graph.addCellOverlay(vertex, overlay);
  28. * overlay.addListener(mxEvent.CLICK, function(sender, evt)
  29. * {
  30. * var cell = evt.getProperty('cell');
  31. * graph.setSelectionCell(cell);
  32. * });
  33. * (end)
  34. *
  35. * For cell overlays to be printed use <mxPrintPreview.printOverlays>.
  36. *
  37. * Event: mxEvent.CLICK
  38. *
  39. * Fires when the user clicks on the overlay. The <code>event</code> property
  40. * contains the corresponding mouse event and the <code>cell</code> property
  41. * contains the cell. For touch devices this is fired if the element receives
  42. * a touchend event.
  43. *
  44. * Constructor: mxCellOverlay
  45. *
  46. * Constructs a new overlay using the given image and tooltip.
  47. *
  48. * Parameters:
  49. *
  50. * image - <mxImage> that represents the icon to be displayed.
  51. * tooltip - Optional string that specifies the tooltip.
  52. * align - Optional horizontal alignment for the overlay. Possible
  53. * values are <ALIGN_LEFT>, <ALIGN_CENTER> and <ALIGN_RIGHT>
  54. * (default).
  55. * verticalAlign - Vertical alignment for the overlay. Possible
  56. * values are <ALIGN_TOP>, <ALIGN_MIDDLE> and <ALIGN_BOTTOM>
  57. * (default).
  58. */
  59. function mxCellOverlay(image, tooltip, align, verticalAlign, offset, cursor)
  60. {
  61. this.image = image;
  62. this.tooltip = tooltip;
  63. this.align = (align != null) ? align : this.align;
  64. this.verticalAlign = (verticalAlign != null) ? verticalAlign : this.verticalAlign;
  65. this.offset = (offset != null) ? offset : new mxPoint();
  66. this.cursor = (cursor != null) ? cursor : 'help';
  67. };
  68. /**
  69. * Extends mxEventSource.
  70. */
  71. mxCellOverlay.prototype = new mxEventSource();
  72. mxCellOverlay.prototype.constructor = mxCellOverlay;
  73. /**
  74. * Variable: image
  75. *
  76. * Holds the <mxImage> to be used as the icon.
  77. */
  78. mxCellOverlay.prototype.image = null;
  79. /**
  80. * Variable: tooltip
  81. *
  82. * Holds the optional string to be used as the tooltip.
  83. */
  84. mxCellOverlay.prototype.tooltip = null;
  85. /**
  86. * Variable: align
  87. *
  88. * Holds the horizontal alignment for the overlay. Default is
  89. * <mxConstants.ALIGN_RIGHT>. For edges, the overlay always appears in the
  90. * center of the edge.
  91. */
  92. mxCellOverlay.prototype.align = mxConstants.ALIGN_RIGHT;
  93. /**
  94. * Variable: verticalAlign
  95. *
  96. * Holds the vertical alignment for the overlay. Default is
  97. * <mxConstants.ALIGN_BOTTOM>. For edges, the overlay always appears in the
  98. * center of the edge.
  99. */
  100. mxCellOverlay.prototype.verticalAlign = mxConstants.ALIGN_BOTTOM;
  101. /**
  102. * Variable: offset
  103. *
  104. * Holds the offset as an <mxPoint>. The offset will be scaled according to the
  105. * current scale.
  106. */
  107. mxCellOverlay.prototype.offset = null;
  108. /**
  109. * Variable: cursor
  110. *
  111. * Holds the cursor for the overlay. Default is 'help'.
  112. */
  113. mxCellOverlay.prototype.cursor = null;
  114. /**
  115. * Variable: defaultOverlap
  116. *
  117. * Defines the overlapping for the overlay, that is, the proportional distance
  118. * from the origin to the point defined by the alignment. Default is 0.5.
  119. */
  120. mxCellOverlay.prototype.defaultOverlap = 0.5;
  121. /**
  122. * Function: getBounds
  123. *
  124. * Returns the bounds of the overlay for the given <mxCellState> as an
  125. * <mxRectangle>. This should be overridden when using multiple overlays
  126. * per cell so that the overlays do not overlap.
  127. *
  128. * The following example will place the overlay along an edge (where
  129. * x=[-1..1] from the start to the end of the edge and y is the
  130. * orthogonal offset in px).
  131. *
  132. * (code)
  133. * overlay.getBounds = function(state)
  134. * {
  135. * var bounds = mxCellOverlay.prototype.getBounds.apply(this, arguments);
  136. *
  137. * if (state.view.graph.getModel().isEdge(state.cell))
  138. * {
  139. * var pt = state.view.getPoint(state, {x: 0, y: 0, relative: true});
  140. *
  141. * bounds.x = pt.x - bounds.width / 2;
  142. * bounds.y = pt.y - bounds.height / 2;
  143. * }
  144. *
  145. * return bounds;
  146. * };
  147. * (end)
  148. *
  149. * Parameters:
  150. *
  151. * state - <mxCellState> that represents the current state of the
  152. * associated cell.
  153. */
  154. mxCellOverlay.prototype.getBounds = function(state)
  155. {
  156. var isEdge = state.view.graph.getModel().isEdge(state.cell);
  157. var s = state.view.scale;
  158. var pt = null;
  159. var w = this.image.width;
  160. var h = this.image.height;
  161. if (isEdge)
  162. {
  163. var pts = state.absolutePoints;
  164. if (pts.length % 2 == 1)
  165. {
  166. pt = pts[Math.floor(pts.length / 2)];
  167. }
  168. else
  169. {
  170. var idx = pts.length / 2;
  171. var p0 = pts[idx-1];
  172. var p1 = pts[idx];
  173. pt = new mxPoint(p0.x + (p1.x - p0.x) / 2,
  174. p0.y + (p1.y - p0.y) / 2);
  175. }
  176. }
  177. else
  178. {
  179. pt = new mxPoint();
  180. if (this.align == mxConstants.ALIGN_LEFT)
  181. {
  182. pt.x = state.x;
  183. }
  184. else if (this.align == mxConstants.ALIGN_CENTER)
  185. {
  186. pt.x = state.x + state.width / 2;
  187. }
  188. else
  189. {
  190. pt.x = state.x + state.width;
  191. }
  192. if (this.verticalAlign == mxConstants.ALIGN_TOP)
  193. {
  194. pt.y = state.y;
  195. }
  196. else if (this.verticalAlign == mxConstants.ALIGN_MIDDLE)
  197. {
  198. pt.y = state.y + state.height / 2;
  199. }
  200. else
  201. {
  202. pt.y = state.y + state.height;
  203. }
  204. }
  205. return new mxRectangle(Math.round(pt.x - (w * this.defaultOverlap - this.offset.x) * s),
  206. Math.round(pt.y - (h * this.defaultOverlap - this.offset.y) * s), w * s, h * s);
  207. };
  208. /**
  209. * Function: toString
  210. *
  211. * Returns the textual representation of the overlay to be used as the
  212. * tooltip. This implementation returns <tooltip>.
  213. */
  214. mxCellOverlay.prototype.toString = function()
  215. {
  216. return this.tooltip;
  217. };
  218. __mxOutput.mxCellOverlay = typeof mxCellOverlay !== 'undefined' ? mxCellOverlay : undefined;