1 7 package javax.swing.text; 8 9 import java.util.Vector ; 10 import java.awt.*; 11 import javax.swing.plaf.*; 12 import javax.swing.*; 13 14 22 public class DefaultHighlighter extends LayeredHighlighter { 23 24 27 public DefaultHighlighter() { 28 drawsLayeredHighlights = true; 29 } 30 31 33 38 public void paint(Graphics g) { 39 int len = highlights.size(); 41 for (int i = 0; i < len; i++) { 42 HighlightInfo info = (HighlightInfo) highlights.elementAt(i); 43 if (!(info instanceof LayeredHighlightInfo)) { 44 Rectangle a = component.getBounds(); 46 Insets insets = component.getInsets(); 47 a.x = insets.left; 48 a.y = insets.top; 49 a.width -= insets.left + insets.right; 50 a.height -= insets.top + insets.bottom; 51 for (; i < len; i++) { 52 info = (HighlightInfo)highlights.elementAt(i); 53 if (!(info instanceof LayeredHighlightInfo)) { 54 Highlighter.HighlightPainter p = info.getPainter(); 55 p.paint(g, info.getStartOffset(), info.getEndOffset(), 56 a, component); 57 } 58 } 59 } 60 } 61 } 62 63 71 public void install(JTextComponent c) { 72 component = c; 73 removeAllHighlights(); 74 } 75 76 83 public void deinstall(JTextComponent c) { 84 component = null; 85 } 86 87 98 public Object addHighlight(int p0, int p1, Highlighter.HighlightPainter p) throws BadLocationException { 99 Document doc = component.getDocument(); 100 HighlightInfo i = (getDrawsLayeredHighlights() && 101 (p instanceof LayeredHighlighter.LayerPainter )) ? 102 new LayeredHighlightInfo() : new HighlightInfo(); 103 i.painter = p; 104 i.p0 = doc.createPosition(p0); 105 i.p1 = doc.createPosition(p1); 106 highlights.addElement(i); 107 safeDamageRange(p0, p1); 108 return i; 109 } 110 111 116 public void removeHighlight(Object tag) { 117 if (tag instanceof LayeredHighlightInfo) { 118 LayeredHighlightInfo lhi = (LayeredHighlightInfo)tag; 119 if (lhi.width > 0 && lhi.height > 0) { 120 component.repaint(lhi.x, lhi.y, lhi.width, lhi.height); 121 } 122 } 123 else { 124 HighlightInfo info = (HighlightInfo) tag; 125 safeDamageRange(info.p0, info.p1); 126 } 127 highlights.removeElement(tag); 128 } 129 130 133 public void removeAllHighlights() { 134 TextUI mapper = component.getUI(); 135 if (getDrawsLayeredHighlights()) { 136 int len = highlights.size(); 137 if (len != 0) { 138 int minX = 0; 139 int minY = 0; 140 int maxX = 0; 141 int maxY = 0; 142 int p0 = -1; 143 int p1 = -1; 144 for (int i = 0; i < len; i++) { 145 HighlightInfo hi = (HighlightInfo)highlights.elementAt(i); 146 if (hi instanceof LayeredHighlightInfo) { 147 LayeredHighlightInfo info = (LayeredHighlightInfo)hi; 148 minX = Math.min(minX, info.x); 149 minY = Math.min(minY, info.y); 150 maxX = Math.max(maxX, info.x + info.width); 151 maxY = Math.max(maxY, info.y + info.height); 152 } 153 else { 154 if (p0 == -1) { 155 p0 = hi.p0.getOffset(); 156 p1 = hi.p1.getOffset(); 157 } 158 else { 159 p0 = Math.min(p0, hi.p0.getOffset()); 160 p1 = Math.max(p1, hi.p1.getOffset()); 161 } 162 } 163 } 164 if (minX != maxX && minY != maxY) { 165 component.repaint(minX, minY, maxX - minX, maxY - minY); 166 } 167 if (p0 != -1) { 168 try { 169 safeDamageRange(p0, p1); 170 } catch (BadLocationException e) {} 171 } 172 highlights.removeAllElements(); 173 } 174 } 175 else if (mapper != null) { 176 int len = highlights.size(); 177 if (len != 0) { 178 int p0 = Integer.MAX_VALUE; 179 int p1 = 0; 180 for (int i = 0; i < len; i++) { 181 HighlightInfo info = (HighlightInfo) highlights.elementAt(i); 182 p0 = Math.min(p0, info.p0.getOffset()); 183 p1 = Math.max(p1, info.p1.getOffset()); 184 } 185 try { 186 safeDamageRange(p0, p1); 187 } catch (BadLocationException e) {} 188 189 highlights.removeAllElements(); 190 } 191 } 192 } 193 194 202 public void changeHighlight(Object tag, int p0, int p1) throws BadLocationException { 203 Document doc = component.getDocument(); 204 if (tag instanceof LayeredHighlightInfo) { 205 LayeredHighlightInfo lhi = (LayeredHighlightInfo)tag; 206 if (lhi.width > 0 && lhi.height > 0) { 207 component.repaint(lhi.x, lhi.y, lhi.width, lhi.height); 208 } 209 lhi.width = lhi.height = 0; 212 lhi.p0 = doc.createPosition(p0); 213 lhi.p1 = doc.createPosition(p1); 214 safeDamageRange(Math.min(p0, p1), Math.max(p0, p1)); 215 } 216 else { 217 HighlightInfo info = (HighlightInfo) tag; 218 int oldP0 = info.p0.getOffset(); 219 int oldP1 = info.p1.getOffset(); 220 if (p0 == oldP0) { 221 safeDamageRange(Math.min(oldP1, p1), 222 Math.max(oldP1, p1)); 223 } else if (p1 == oldP1) { 224 safeDamageRange(Math.min(p0, oldP0), 225 Math.max(p0, oldP0)); 226 } else { 227 safeDamageRange(oldP0, oldP1); 228 safeDamageRange(p0, p1); 229 } 230 info.p0 = doc.createPosition(p0); 231 info.p1 = doc.createPosition(p1); 232 } 233 } 234 235 242 public Highlighter.Highlight [] getHighlights() { 243 int size = highlights.size(); 244 if (size == 0) { 245 return noHighlights; 246 } 247 Highlighter.Highlight [] h = new Highlighter.Highlight [size]; 248 highlights.copyInto(h); 249 return h; 250 } 251 252 264 public void paintLayeredHighlights(Graphics g, int p0, int p1, 265 Shape viewBounds, 266 JTextComponent editor, View view) { 267 for (int counter = highlights.size() - 1; counter >= 0; counter--) { 268 Object tag = highlights.elementAt(counter); 269 if (tag instanceof LayeredHighlightInfo) { 270 LayeredHighlightInfo lhi = (LayeredHighlightInfo)tag; 271 int start = lhi.getStartOffset(); 272 int end = lhi.getEndOffset(); 273 if ((p0 < start && p1 > start) || 274 (p0 >= start && p0 < end)) { 275 lhi.paintLayeredHighlights(g, p0, p1, viewBounds, 276 editor, view); 277 } 278 } 279 } 280 } 281 282 286 private void safeDamageRange(final Position p0, final Position p1) { 287 safeDamager.damageRange(p0, p1); 288 } 289 290 294 private void safeDamageRange(int a0, int a1) throws BadLocationException { 295 Document doc = component.getDocument(); 296 safeDamageRange(doc.createPosition(a0), doc.createPosition(a1)); 297 } 298 299 307 public void setDrawsLayeredHighlights(boolean newValue) { 308 drawsLayeredHighlights = newValue; 309 } 310 311 public boolean getDrawsLayeredHighlights() { 312 return drawsLayeredHighlights; 313 } 314 315 317 private final static Highlighter.Highlight [] noHighlights = 318 new Highlighter.Highlight [0]; 319 private Vector highlights = new Vector (); private JTextComponent component; 321 private boolean drawsLayeredHighlights; 322 private SafeDamager safeDamager = new SafeDamager(); 323 324 325 331 public static final LayeredHighlighter.LayerPainter DefaultPainter = new DefaultHighlightPainter(null); 332 333 334 338 public static class DefaultHighlightPainter extends LayeredHighlighter.LayerPainter { 339 340 346 public DefaultHighlightPainter(Color c) { 347 color = c; 348 } 349 350 355 public Color getColor() { 356 return color; 357 } 358 359 361 370 public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) { 371 Rectangle alloc = bounds.getBounds(); 372 try { 373 TextUI mapper = c.getUI(); 375 Rectangle p0 = mapper.modelToView(c, offs0); 376 Rectangle p1 = mapper.modelToView(c, offs1); 377 378 Color color = getColor(); 380 381 if (color == null) { 382 g.setColor(c.getSelectionColor()); 383 } 384 else { 385 g.setColor(color); 386 } 387 if (p0.y == p1.y) { 388 Rectangle r = p0.union(p1); 390 g.fillRect(r.x, r.y, r.width, r.height); 391 } else { 392 int p0ToMarginWidth = alloc.x + alloc.width - p0.x; 394 g.fillRect(p0.x, p0.y, p0ToMarginWidth, p0.height); 395 if ((p0.y + p0.height) != p1.y) { 396 g.fillRect(alloc.x, p0.y + p0.height, alloc.width, 397 p1.y - (p0.y + p0.height)); 398 } 399 g.fillRect(alloc.x, p1.y, (p1.x - alloc.x), p1.height); 400 } 401 } catch (BadLocationException e) { 402 } 404 } 405 406 419 public Shape paintLayer(Graphics g, int offs0, int offs1, 420 Shape bounds, JTextComponent c, View view) { 421 Color color = getColor(); 422 423 if (color == null) { 424 g.setColor(c.getSelectionColor()); 425 } 426 else { 427 g.setColor(color); 428 } 429 if (offs0 == view.getStartOffset() && 430 offs1 == view.getEndOffset()) { 431 Rectangle alloc; 433 if (bounds instanceof Rectangle) { 434 alloc = (Rectangle)bounds; 435 } 436 else { 437 alloc = bounds.getBounds(); 438 } 439 g.fillRect(alloc.x, alloc.y, alloc.width, alloc.height); 440 return alloc; 441 } 442 else { 443 try { 445 Shape shape = view.modelToView(offs0, Position.Bias.Forward, 447 offs1,Position.Bias.Backward, 448 bounds); 449 Rectangle r = (shape instanceof Rectangle) ? 450 (Rectangle)shape : shape.getBounds(); 451 g.fillRect(r.x, r.y, r.width, r.height); 452 return r; 453 } catch (BadLocationException e) { 454 } 456 } 457 return null; 459 } 460 461 private Color color; 462 463 } 464 465 466 class HighlightInfo implements Highlighter.Highlight { 467 468 public int getStartOffset() { 469 return p0.getOffset(); 470 } 471 472 public int getEndOffset() { 473 return p1.getOffset(); 474 } 475 476 public Highlighter.HighlightPainter getPainter() { 477 return painter; 478 } 479 480 Position p0; 481 Position p1; 482 Highlighter.HighlightPainter painter; 483 } 484 485 486 490 class LayeredHighlightInfo extends HighlightInfo { 491 492 void union(Shape bounds) { 493 if (bounds == null) 494 return; 495 496 Rectangle alloc; 497 if (bounds instanceof Rectangle) { 498 alloc = (Rectangle)bounds; 499 } 500 else { 501 alloc = bounds.getBounds(); 502 } 503 if (width == 0 || height == 0) { 504 x = alloc.x; 505 y = alloc.y; 506 width = alloc.width; 507 height = alloc.height; 508 } 509 else { 510 width = Math.max(x + width, alloc.x + alloc.width); 511 height = Math.max(y + height, alloc.y + alloc.height); 512 x = Math.min(x, alloc.x); 513 width -= x; 514 y = Math.min(y, alloc.y); 515 height -= y; 516 } 517 } 518 519 523 void paintLayeredHighlights(Graphics g, int p0, int p1, 524 Shape viewBounds, JTextComponent editor, 525 View view) { 526 int start = getStartOffset(); 527 int end = getEndOffset(); 528 p0 = Math.max(start, p0); 530 p1 = Math.min(end, p1); 531 union(((LayeredHighlighter.LayerPainter )painter).paintLayer 534 (g, p0, p1, viewBounds, editor, view)); 535 } 536 537 int x; 538 int y; 539 int width; 540 int height; 541 } 542 543 551 class SafeDamager implements Runnable { 552 private Vector p0 = new Vector (10); 553 private Vector p1 = new Vector (10); 554 private Document lastDoc = null; 555 556 559 public synchronized void run() { 560 if (component != null) { 561 TextUI mapper = component.getUI(); 562 if (mapper != null && lastDoc == component.getDocument()) { 563 int len = p0.size(); 566 for (int i = 0; i < len; i++){ 567 mapper.damageRange(component, 568 ((Position )p0.get(i)).getOffset(), 569 ((Position )p1.get(i)).getOffset()); 570 } 571 } 572 } 573 p0.clear(); 574 p1.clear(); 575 576 lastDoc = null; 578 } 579 580 590 public synchronized void damageRange(Position pos0, Position pos1) { 591 if (component == null) { 592 p0.clear(); 593 lastDoc = null; 594 return; 595 } 596 597 boolean addToQueue = p0.isEmpty(); 598 Document curDoc = component.getDocument(); 599 if (curDoc != lastDoc) { 600 if (!p0.isEmpty()) { 601 p0.clear(); 602 p1.clear(); 603 } 604 lastDoc = curDoc; 605 } 606 p0.add(pos0); 607 p1.add(pos1); 608 609 if (addToQueue) { 610 SwingUtilities.invokeLater(this); 611 } 612 } 613 } 614 } 615 | Popular Tags |