1 18 package org.apache.batik.gvt; 19 20 import java.awt.Graphics2D ; 21 import java.awt.Shape ; 22 import java.awt.geom.AffineTransform ; 23 import java.awt.geom.GeneralPath ; 24 import java.awt.geom.Point2D ; 25 import java.awt.geom.Rectangle2D ; 26 import java.text.AttributedCharacterIterator ; 27 import java.text.CharacterIterator ; 28 import java.util.List ; 29 30 import org.apache.batik.gvt.renderer.StrokingTextPainter; 31 import org.apache.batik.gvt.text.AttributedCharacterSpanIterator; 32 import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; 33 import org.apache.batik.gvt.text.Mark; 34 import org.apache.batik.gvt.text.TextHit; 35 import org.apache.batik.gvt.text.TextPaintInfo; 36 import org.apache.batik.gvt.text.TextSpanLayout; 37 38 44 public class TextNode extends AbstractGraphicsNode implements Selectable { 45 46 public static final 47 AttributedCharacterIterator.Attribute PAINT_INFO = 48 GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO; 49 50 54 protected Point2D location = new Point2D.Float (0, 0); 55 56 59 protected AttributedCharacterIterator aci; 60 61 64 protected String text; 65 66 69 protected Mark beginMark = null; 70 71 74 protected Mark endMark = null; 75 76 79 protected List textRuns; 80 81 84 protected TextPainter textPainter = StrokingTextPainter.getInstance(); 85 86 90 private Rectangle2D geometryBounds; 91 92 95 private Rectangle2D primitiveBounds; 96 97 100 private Shape outline; 101 102 105 public TextNode() { 106 } 107 108 115 public void setTextPainter(TextPainter textPainter) { 116 if (textPainter == null) { 117 this.textPainter = StrokingTextPainter.getInstance(); 118 } else { 119 this.textPainter = textPainter; 120 } 121 } 122 123 126 public TextPainter getTextPainter() { 127 return textPainter; 128 } 129 130 133 public List getTextRuns() { 134 return textRuns; 135 } 136 137 142 public void setTextRuns(List textRuns) { 143 this.textRuns = textRuns; 144 } 145 146 149 public String getText() { 150 if (text == null) { 151 StringBuffer buf = new StringBuffer (aci.getEndIndex()); 152 for (char c = aci.first(); 153 c != CharacterIterator.DONE; 154 c = aci.next()) { 155 buf.append(c); 156 } 157 text = buf.toString(); 158 } 159 return text; 160 } 161 162 167 public void setLocation(Point2D newLocation){ 168 fireGraphicsNodeChangeStarted(); 169 invalidateGeometryCache(); 170 this.location = newLocation; 171 fireGraphicsNodeChangeCompleted(); 172 } 173 174 179 public Point2D getLocation(){ 180 return location; 181 } 182 183 public void swapTextPaintInfo(TextPaintInfo newInfo, 184 TextPaintInfo oldInfo) { 185 fireGraphicsNodeChangeStarted(); 186 invalidateGeometryCache(); 187 oldInfo.set(newInfo); 188 fireGraphicsNodeChangeCompleted(); 189 } 190 191 192 197 public void setAttributedCharacterIterator 198 (AttributedCharacterIterator newAci) { 199 fireGraphicsNodeChangeStarted(); 200 invalidateGeometryCache(); 201 this.aci = newAci; 202 text = null; 203 textRuns = null; 204 fireGraphicsNodeChangeCompleted(); 205 } 206 207 212 public AttributedCharacterIterator getAttributedCharacterIterator(){ 213 return aci; 214 } 215 216 220 225 protected void invalidateGeometryCache() { 226 super.invalidateGeometryCache(); 227 primitiveBounds = null; 228 geometryBounds = null; 229 outline = null; 230 } 231 232 235 public Rectangle2D getPrimitiveBounds(){ 236 if (primitiveBounds == null) { 237 if (aci != null) { 238 primitiveBounds = textPainter.getBounds2D(this); 239 } 240 } 241 return primitiveBounds; 242 } 243 244 250 public Rectangle2D getGeometryBounds(){ 251 if (geometryBounds == null){ 252 if (aci != null) { 253 geometryBounds = textPainter.getGeometryBounds(this); 254 } 255 } 256 return geometryBounds; 257 } 258 259 264 public Rectangle2D getSensitiveBounds() { 265 return getGeometryBounds(); 266 } 267 268 271 public Shape getOutline() { 272 if (outline == null) { 273 if (aci != null) { 274 outline = textPainter.getOutline(this); 275 } 276 } 277 return outline; 278 } 279 280 285 public Mark getMarkerForChar(int index, boolean beforeChar) { 286 return textPainter.getMark(this, index, beforeChar); 287 } 288 289 public void setSelection(Mark begin, Mark end) { 293 if ((begin.getTextNode() != this) || 294 (end.getTextNode() != this)) 295 throw new Error ("Markers not from this TextNode"); 296 297 beginMark = begin; 298 endMark = end; 299 } 300 301 306 public boolean selectAt(double x, double y) { 307 beginMark = textPainter.selectAt(x, y, this); 308 return true; } 310 311 316 public boolean selectTo(double x, double y) { 317 Mark tmpMark = textPainter.selectTo(x, y, beginMark); 318 if (tmpMark == null) 319 return false; 320 if (tmpMark != endMark) { 321 endMark = tmpMark; 322 return true; 323 } 324 return false; 325 } 326 327 332 public boolean selectAll(double x, double y) { 333 beginMark = textPainter.selectFirst(this); 334 endMark = textPainter.selectLast(this); 335 return true; 336 } 337 338 343 public Object getSelection() { 344 345 int[] ranges = textPainter.getSelected(beginMark, endMark); 346 Object o = null; 347 348 if ((ranges != null) && (ranges.length > 1)) { 351 if (ranges[0] > ranges[1]) { 353 int temp = ranges[1]; 354 ranges[1] = ranges[0]; 355 ranges[0] = temp; 356 } 357 o = new AttributedCharacterSpanIterator 358 (aci, ranges[0], ranges[1]+1); 359 } 360 return o; 361 } 362 363 368 public Shape getHighlightShape() { 369 Shape highlightShape = 370 textPainter.getHighlightShape(beginMark, endMark); 371 AffineTransform t = getGlobalTransform(); 372 highlightShape = t.createTransformedShape(highlightShape); 373 return highlightShape; 374 } 375 376 380 385 public void primitivePaint(Graphics2D g2d) { 386 Shape clip = g2d.getClip(); 392 if (clip != null && !(clip instanceof GeneralPath )) { 393 g2d.setClip(new GeneralPath (clip)); 394 } 395 textPainter.paint(this, g2d); 397 } 398 399 403 409 public boolean contains(Point2D p) { 410 if (!super.contains(p)) { 414 return false; 415 } 416 List list = getTextRuns(); 417 for (int i = 0 ; i < list.size(); i++) { 419 StrokingTextPainter.TextRun run = 420 (StrokingTextPainter.TextRun)list.get(i); 421 TextSpanLayout layout = run.getLayout(); 422 float x = (float)p.getX(); 423 float y = (float)p.getY(); 424 TextHit textHit = layout.hitTestChar(x, y); 425 if (textHit != null && contains(p, layout.getBounds2D())) { 426 return true; 427 } 428 } 429 return false; 430 } 431 432 protected boolean contains(Point2D p, Rectangle2D b) { 433 if (b == null || !b.contains(p)) { 434 return false; 435 } 436 switch(pointerEventType) { 437 case VISIBLE_PAINTED: 438 case VISIBLE_FILL: 439 case VISIBLE_STROKE: 440 case VISIBLE: 441 return isVisible; 442 case PAINTED: 443 case FILL: 444 case STROKE: 445 case ALL: 446 return true; 447 case NONE: 448 return false; 449 default: 450 return false; 451 } 452 } 453 454 458 public static final class Anchor implements java.io.Serializable { 459 460 463 public static final int ANCHOR_START = 0; 464 465 468 public static final int ANCHOR_MIDDLE = 1; 469 470 473 public static final int ANCHOR_END = 2; 474 475 480 public static final Anchor START = new Anchor(ANCHOR_START); 481 482 487 public static final Anchor MIDDLE = new Anchor(ANCHOR_MIDDLE); 488 489 494 public static final Anchor END = new Anchor(ANCHOR_END); 495 496 499 private int type; 500 501 504 private Anchor(int type) { 505 this.type = type; 506 } 507 508 511 public int getType() { 512 return type; 513 } 514 515 522 private Object readResolve() throws java.io.ObjectStreamException { 523 switch(type){ 524 case ANCHOR_START: 525 return START; 526 case ANCHOR_MIDDLE: 527 return MIDDLE; 528 case ANCHOR_END: 529 return END; 530 default: 531 throw new Error ("Unknown Anchor type"); 532 } 533 } 534 } 535 } 536 537 538 | Popular Tags |