1 6 7 package com.thoughtriver.open.vectorvisuals.meta.connector; 8 9 import java.awt.*; 10 import java.awt.font.*; 11 import java.awt.geom.*; 12 import java.util.*; 13 14 import com.thoughtriver.open.vectorvisuals.*; 15 16 26 public class VisualConnectorObject extends VisualObject { 27 28 32 private EndpointConfiguration endConfig1 = null; 33 34 38 private EndpointConfiguration endConfig2 = null; 39 40 41 private String labelText = null; 42 43 44 private Font labelFont = null; 45 46 47 private Brush labelBrush = null; 48 49 50 private boolean fixedHorizontalLabel = false; 51 52 62 public VisualConnectorObject(final Brush lineBrush, final EndpointConfiguration endpoint1, final EndpointConfiguration endpoint2) { 63 super(new Area(), lineBrush, null); 64 endConfig1 = endpoint1; 65 endConfig2 = endpoint2; 66 } 67 68 76 public void setLabel(final String label, final Font font, final Brush brush) { 77 labelText = label; 78 labelFont = font; 79 labelBrush = brush; 80 } 81 82 89 public String getLabelText() { 90 return labelText; 91 } 92 93 97 @Override 98 public void prepare() { 99 Point2D firstPoint = null; 100 Point2D secondPoint = null; 101 102 AffineTransform trans1 = endConfig1.getObject().getTransformRelativeTo(getParent()); 104 AffineTransform trans2 = endConfig2.getObject().getTransformRelativeTo(getParent()); 105 106 Shape startShape = endConfig1.getObject().getShape(); 108 startShape = trans1.createTransformedShape(startShape); 109 Shape endShape = endConfig2.getObject().getShape(); 110 endShape = trans2.createTransformedShape(endShape); 111 112 RectangularShape bounds = startShape.getBounds2D(); 115 firstPoint = new Point2D.Double(bounds.getCenterX(), bounds.getCenterY()); 116 117 if (endConfig2.isEdge()) { 118 secondPoint = getClosestPointOnShape(firstPoint, endShape); 120 121 } 122 else { 123 bounds = endShape.getBounds2D(); 124 secondPoint = new Point2D.Double(bounds.getCenterX(), bounds.getCenterY()); 125 } 126 127 if (endConfig1.isEdge()) { 129 firstPoint = getClosestPointOnShape(secondPoint, startShape); 130 } 131 132 try { 134 AffineTransform inverseTransform = getTransformRelativeTo(getParent()).createInverse(); 135 firstPoint = inverseTransform.transform(firstPoint, firstPoint); 136 secondPoint = inverseTransform.transform(secondPoint, secondPoint); 137 } 138 catch (NoninvertibleTransformException e) { 139 e.printStackTrace(); 140 } 141 142 Line2D line = new Line2D.Double(firstPoint, secondPoint); 143 setShape(line); 144 } 145 146 152 @Override 153 public void renderOutline(final Graphics2D g) { 154 155 Line2D line = (Line2D) getShape(); 156 if (getLineBrush() != null) { 157 getLineBrush().useOn(g); 158 } 159 g.draw(line); 160 161 renderEndpointShape(g, endConfig1.getShape(), line, false); 163 renderEndpointShape(g, endConfig2.getShape(), line, true); 164 165 if (getLabelText() != null) { 166 renderLabel(g, getLabelText(), line); 167 } 168 169 } 170 171 176 @Override 177 public void renderObject(@SuppressWarnings ("unused") 178 final Graphics2D g) { 179 } 181 182 193 protected void renderEndpointShape(final Graphics2D g, final Shape shape, final Line2D line, final boolean end) { 194 195 if (shape == null) { 197 return; 198 } 199 200 AffineTransform trans = null; 202 if (end) { 203 trans = AffineTransform.getTranslateInstance(line.getX2(), line.getY2()); 204 } 205 else { 206 trans = AffineTransform.getTranslateInstance(line.getX1(), line.getY1()); 207 } 208 209 double xChange = line.getX2() - line.getX1(); 211 double yChange = line.getY2() - line.getY1(); 212 double theta = Math.atan2(yChange, xChange); 213 if (end) { 214 trans.rotate(theta - (Math.PI / 2.0)); 215 } 216 else { 217 trans.rotate((Math.PI / 2.0) + theta); 218 } 219 220 Shape transformedShape = trans.createTransformedShape(shape); 222 223 g.draw(transformedShape); 225 } 226 227 236 protected void renderLabel(final Graphics2D g, final String labelText, final Line2D line) { 237 Graphics2D newGraphics = (Graphics2D) g.create(); 238 239 labelBrush.useOn(newGraphics); 240 241 FontRenderContext frc = g.getFontRenderContext(); 243 GlyphVector glyphVector = labelFont.createGlyphVector(frc, labelText); 244 245 Point2D firstPoint = line.getP1(); 247 Point2D secondPoint = line.getP2(); 248 RectangularShape rect = new Rectangle2D.Double(firstPoint.getX(), firstPoint.getY(), secondPoint.getX() 249 - firstPoint.getX(), secondPoint.getY() - firstPoint.getY()); 250 Point2D halfwayPoint = new Point2D.Double(rect.getCenterX(), rect.getCenterY()); 251 252 Rectangle2D labelRect = glyphVector.getVisualBounds(); 254 double xOffset = -(labelRect.getWidth() / 2); 255 newGraphics.translate(halfwayPoint.getX(), halfwayPoint.getY()); 256 257 if (isFixedHorizontalLabel()) { 258 259 double yOffset = (labelRect.getHeight() / 2); 261 newGraphics.translate(0, yOffset); 262 263 } 264 else { 265 266 double xChange = line.getX2() - line.getX1(); 268 double yChange = line.getY2() - line.getY1(); 269 double theta = Math.atan2(yChange, xChange); 270 newGraphics.rotate(theta); 271 272 newGraphics.translate(0, -3); 274 } 275 276 newGraphics.drawGlyphVector(glyphVector, (float) xOffset, 0); 277 newGraphics.dispose(); 278 } 279 280 288 public boolean isFixedHorizontalLabel() { 289 return fixedHorizontalLabel; 290 } 291 292 300 public void setFixedHorizontalLabel(final boolean horizontal) { 301 fixedHorizontalLabel = horizontal; 302 } 303 304 315 private Point2D getClosestPointOnShape(final Point2D point, final Shape shape) { 316 317 double[] lastCoords = null; 318 double[] lastMoveToCoords = null; 319 PathIterator pIter = shape.getPathIterator(null); 320 ArrayList<SegmentInfo> segments = new ArrayList<SegmentInfo>(); 321 322 while (!pIter.isDone()) { 324 325 SegmentInfo segInfo = new SegmentInfo(); 326 segInfo.type = pIter.currentSegment(segInfo.coords); 327 328 if (segInfo.type == PathIterator.SEG_MOVETO) { 330 lastMoveToCoords = segInfo.coords; 331 332 } 334 else if (segInfo.type == PathIterator.SEG_CLOSE) { 335 segInfo.coords = lastMoveToCoords; 336 } 337 338 segInfo.prevCoords = lastCoords; 339 lastCoords = segInfo.coords; 340 pIter.next(); 341 342 segments.add(segInfo); 343 } 344 345 double shortestDist = Double.MAX_VALUE; 347 int shortestIndex = 0; 348 for (int i = 0; i < segments.size(); i++) { 349 SegmentInfo segInfo = segments.get(i); 350 351 double dist = point.distance(segInfo.getCenterPoint()); 352 if (dist < shortestDist) { 353 shortestDist = dist; 354 shortestIndex = i; 355 } 356 } 357 358 SegmentInfo closestSegment = segments.get(shortestIndex); 359 return closestSegment.getCenterPoint(); 360 } 361 362 366 static private class SegmentInfo { 367 368 369 public int type; 370 371 372 public double[] coords = null; 373 374 375 public double[] prevCoords = null; 376 377 380 public SegmentInfo() { 381 coords = new double[6]; 382 } 383 384 390 public Point2D getCenterPoint() { 391 392 double[] centerCoords = new double[2]; 393 394 if (prevCoords == null) { 395 centerCoords[0] = coords[0]; 396 centerCoords[1] = coords[1]; 397 } 398 else { 399 400 RectangularShape rect = new Rectangle2D.Double(prevCoords[0], prevCoords[1], coords[0] 401 - prevCoords[0], coords[1] - prevCoords[1]); 402 403 centerCoords[0] = rect.getCenterX(); 404 centerCoords[1] = rect.getCenterY(); 405 } 406 407 return new Point2D.Double(centerCoords[0], centerCoords[1]); 408 } 409 410 } 411 412 } 413 | Popular Tags |