mxConnector.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /**
  2. * Copyright (c) 2006-2015, JGraph Ltd
  3. * Copyright (c) 2006-2015, Gaudenz Alder
  4. */
  5. /**
  6. * Class: mxConnector
  7. *
  8. * Extends <mxShape> to implement a connector shape. The connector
  9. * shape allows for arrow heads on either side.
  10. *
  11. * This shape is registered under <mxConstants.SHAPE_CONNECTOR> in
  12. * <mxCellRenderer>.
  13. *
  14. * Constructor: mxConnector
  15. *
  16. * Constructs a new connector shape.
  17. *
  18. * Parameters:
  19. *
  20. * points - Array of <mxPoints> that define the points. This is stored in
  21. * <mxShape.points>.
  22. * stroke - String that defines the stroke color. This is stored in <stroke>.
  23. * Default is 'black'.
  24. * strokewidth - Optional integer that defines the stroke width. Default is
  25. * 1. This is stored in <strokewidth>.
  26. */
  27. function mxConnector(points, stroke, strokewidth)
  28. {
  29. mxPolyline.call(this, points, stroke, strokewidth);
  30. };
  31. /**
  32. * Extends mxPolyline.
  33. */
  34. mxUtils.extend(mxConnector, mxPolyline);
  35. /**
  36. * Function: updateBoundingBox
  37. *
  38. * Updates the <boundingBox> for this shape using <createBoundingBox> and
  39. * <augmentBoundingBox> and stores the result in <boundingBox>.
  40. */
  41. mxConnector.prototype.updateBoundingBox = function()
  42. {
  43. this.useSvgBoundingBox = this.style != null && this.style[mxConstants.STYLE_CURVED] == 1;
  44. mxShape.prototype.updateBoundingBox.apply(this, arguments);
  45. };
  46. /**
  47. * Function: paintEdgeShape
  48. *
  49. * Paints the line shape.
  50. */
  51. mxConnector.prototype.paintEdgeShape = function(c, pts)
  52. {
  53. // The indirection via functions for markers is needed in
  54. // order to apply the offsets before painting the line and
  55. // paint the markers after painting the line.
  56. var sourceMarker = this.createMarker(c, pts, true);
  57. var targetMarker = this.createMarker(c, pts, false);
  58. mxPolyline.prototype.paintEdgeShape.apply(this, arguments);
  59. // Disables shadows, dashed styles and fixes fill color for markers
  60. c.setFillColor(this.stroke);
  61. c.setShadow(false);
  62. c.setDashed(false);
  63. if (sourceMarker != null)
  64. {
  65. sourceMarker();
  66. }
  67. if (targetMarker != null)
  68. {
  69. targetMarker();
  70. }
  71. };
  72. /**
  73. * Function: createMarker
  74. *
  75. * Prepares the marker by adding offsets in pts and returning a function to
  76. * paint the marker.
  77. */
  78. mxConnector.prototype.createMarker = function(c, pts, source)
  79. {
  80. var result = null;
  81. var n = pts.length;
  82. var type = mxUtils.getValue(this.style, (source) ? mxConstants.STYLE_STARTARROW : mxConstants.STYLE_ENDARROW);
  83. var p0 = (source) ? pts[1] : pts[n - 2];
  84. var pe = (source) ? pts[0] : pts[n - 1];
  85. if (type != null && p0 != null && pe != null)
  86. {
  87. var count = 1;
  88. // Uses next non-overlapping point
  89. while (count < n - 1 && Math.round(p0.x - pe.x) == 0 && Math.round(p0.y - pe.y) == 0)
  90. {
  91. p0 = (source) ? pts[1 + count] : pts[n - 2 - count];
  92. count++;
  93. }
  94. // Computes the norm and the inverse norm
  95. var dx = pe.x - p0.x;
  96. var dy = pe.y - p0.y;
  97. var dist = Math.max(1, Math.sqrt(dx * dx + dy * dy));
  98. var unitX = dx / dist;
  99. var unitY = dy / dist;
  100. var size = mxUtils.getNumber(this.style, (source) ? mxConstants.STYLE_STARTSIZE : mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE);
  101. // Allow for stroke width in the end point used and the
  102. // orthogonal vectors describing the direction of the marker
  103. var filled = this.style[(source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL] != 0;
  104. result = mxMarker.createMarker(c, this, type, pe, unitX, unitY, size, source, this.strokewidth, filled);
  105. }
  106. return result;
  107. };
  108. /**
  109. * Function: augmentBoundingBox
  110. *
  111. * Augments the bounding box with the strokewidth and shadow offsets.
  112. */
  113. mxConnector.prototype.augmentBoundingBox = function(bbox)
  114. {
  115. mxShape.prototype.augmentBoundingBox.apply(this, arguments);
  116. // Adds marker sizes
  117. var size = 0;
  118. if (mxUtils.getValue(this.style, mxConstants.STYLE_STARTARROW, mxConstants.NONE) != mxConstants.NONE)
  119. {
  120. size = mxUtils.getNumber(this.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_MARKERSIZE) + 1;
  121. }
  122. if (mxUtils.getValue(this.style, mxConstants.STYLE_ENDARROW, mxConstants.NONE) != mxConstants.NONE)
  123. {
  124. size = Math.max(size, mxUtils.getNumber(this.style, mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE)) + 1;
  125. }
  126. bbox.grow(size * this.scale);
  127. };
  128. __mxOutput.mxConnector = typeof mxConnector !== 'undefined' ? mxConnector : undefined;