1 19 package org.openide.awt; 20 21 import org.openide.awt.HtmlLabelUI; 22 import org.openide.awt.HtmlRenderer; 23 24 import java.awt.*; 25 import java.awt.event.*; 26 27 import java.beans.PropertyChangeListener ; 28 import java.beans.VetoableChangeListener ; 29 30 import java.io.*; 31 32 import java.lang.ref.Reference ; 33 import java.lang.ref.SoftReference ; 34 35 import javax.swing.*; 36 import javax.swing.border.Border ; 37 import javax.swing.event.AncestorListener ; 38 39 40 55 class HtmlRendererImpl extends JLabel implements HtmlRenderer.Renderer { 56 private static final Rectangle bounds = new Rectangle(); 57 private static final boolean swingRendering = Boolean.getBoolean("nb.useSwingHtmlRendering"); private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0); 59 static final int TYPE_UNKNOWN = -1; 60 static final int TYPE_TREE = 0; 61 static final int TYPE_LIST = 1; 62 static final int TYPE_TABLE = 2; 63 64 private static boolean noCacheGraphics = Boolean.getBoolean("nb.renderer.nocache"); private static Reference <Graphics> scratchGraphics = null; 68 private boolean centered = false; 69 private boolean parentFocused = false; 70 private Boolean html = null; 71 private int indent = 0; 72 private Border border = null; 73 private boolean selected = false; 74 private boolean leadSelection = false; 75 private Dimension prefSize = null; 76 private int type = TYPE_UNKNOWN; 77 private int renderStyle = HtmlRenderer.STYLE_CLIP; 78 private boolean enabled = true; 79 80 81 public void reset() { 82 parentFocused = false; 83 setCentered(false); 84 html = null; 85 indent = 0; 86 border = null; 87 setIcon(null); 88 setOpaque(false); 89 selected = false; 90 leadSelection = false; 91 prefSize = null; 92 type = TYPE_UNKNOWN; 93 renderStyle = HtmlRenderer.STYLE_CLIP; 94 setFont(UIManager.getFont("controlFont")); setIconTextGap(3); 96 setEnabled(true); 97 border = null; 98 99 EMPTY_INSETS.top = 0; 101 EMPTY_INSETS.left = 0; 102 EMPTY_INSETS.right = 0; 103 EMPTY_INSETS.bottom = 0; 104 } 105 106 public Component getTableCellRendererComponent( 107 JTable table, Object value, boolean selected, boolean leadSelection, int row, int column 108 ) { 109 reset(); 110 configureFrom(value, table, selected, leadSelection); 111 type = TYPE_TABLE; 112 113 if (swingRendering && selected) { 114 setBackground(table.getSelectionBackground()); 115 setForeground(table.getSelectionForeground()); 116 setOpaque(true); 117 } 118 119 return this; 120 } 121 122 public Component getTreeCellRendererComponent( 123 JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean leadSelection 124 ) { 125 reset(); 126 configureFrom(value, tree, selected, leadSelection); 127 type = TYPE_TREE; 128 129 if (swingRendering && selected) { 130 if (HtmlLabelUI.isGTK()) { 131 setBackground(HtmlLabelUI.getBackgroundFor(this)); 132 setForeground(HtmlLabelUI.getForegroundFor(this)); 133 } 134 setOpaque(true); 135 } 136 137 return this; 138 } 139 140 public Component getListCellRendererComponent( 141 JList list, Object value, int index, boolean selected, boolean leadSelection 142 ) { 143 reset(); 144 configureFrom(value, list, selected, leadSelection); 145 type = TYPE_LIST; 146 147 if (swingRendering && selected) { 148 setBackground(list.getSelectionBackground()); 149 setForeground(list.getSelectionForeground()); 150 setOpaque(true); 151 } 152 153 if (HtmlLabelUI.isGTK()) { 155 if (index == -1) { 156 Color borderC = UIManager.getColor("controlShadow"); 157 borderC = borderC == null ? Color.GRAY : borderC; 158 setBorder(BorderFactory.createCompoundBorder( 159 BorderFactory.createLineBorder(borderC), 160 BorderFactory.createEmptyBorder(3, 2, 3, 2))); 161 } else { 162 setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); 163 } 164 } 165 166 return this; 167 } 168 169 171 private void configureFrom(Object value, JComponent target, boolean selected, boolean leadSelection) { 172 if (value == null) { 173 value = ""; 174 } 175 176 setText((value == null) ? "" : value.toString()); 177 178 setSelected(selected); 179 180 if (selected) { 181 setParentFocused(checkFocused(target)); 182 } else { 183 setParentFocused(false); 184 } 185 186 setEnabled(target.isEnabled()); 187 188 setLeadSelection(leadSelection); 189 190 setFont(target.getFont()); 191 } 192 193 private boolean checkFocused(JComponent c) { 194 Component focused = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner(); 195 boolean result = c == focused; 196 197 if (!result) { 198 result = c.isAncestorOf(focused); 199 } 200 201 return result; 202 } 203 204 public void addNotify() { 205 if (swingRendering) { 206 super.addNotify(); 207 } 208 } 209 210 public void removeNotify() { 211 if (swingRendering) { 212 super.removeNotify(); 213 } 214 } 215 216 public void setSelected(boolean val) { 217 selected = val; 218 } 219 220 public void setParentFocused(boolean val) { 221 parentFocused = val; 222 } 223 224 public void setLeadSelection(boolean val) { 225 leadSelection = val; 226 } 227 228 public void setCentered(boolean val) { 229 centered = val; 230 231 if (val) { 232 setIconTextGap(5); 233 } 234 235 if (swingRendering) { 236 if (val) { 237 setVerticalTextPosition(JLabel.BOTTOM); 238 setHorizontalAlignment(JLabel.CENTER); 239 setHorizontalTextPosition(JLabel.CENTER); 240 } else { 241 setVerticalTextPosition(JLabel.CENTER); 242 setHorizontalAlignment(JLabel.LEADING); 243 setHorizontalTextPosition(JLabel.TRAILING); 244 } 245 } 246 } 247 248 public void setIndent(int pixels) { 249 this.indent = pixels; 250 } 251 252 public void setHtml(boolean val) { 253 Boolean wasHtml = html; 254 String txt = getText(); 255 html = val ? Boolean.TRUE : Boolean.FALSE; 256 257 if (swingRendering && (html != wasHtml)) { 258 firePropertyChange("text", txt, getText()); } 261 } 262 263 public void setRenderStyle(int style) { 264 renderStyle = style; 265 } 266 267 int getRenderStyle() { 268 return renderStyle; 269 } 270 271 boolean isLeadSelection() { 272 return leadSelection; 273 } 274 275 boolean isCentered() { 276 return centered; 277 } 278 279 boolean isParentFocused() { 280 return parentFocused; 281 } 282 283 boolean isHtml() { 284 if (html == null) { 285 String s = getText(); 286 html = checkHtml(s); 287 } 288 289 return html.booleanValue(); 290 } 291 292 private Boolean checkHtml(String s) { 293 Boolean result; 294 295 if (s == null) { 296 result = Boolean.FALSE; 297 } else if (s.startsWith("<html") || s.startsWith("<HTML")) { result = Boolean.TRUE; 299 } else { 300 result = Boolean.FALSE; 301 } 302 303 return result; 304 } 305 306 boolean isSelected() { 307 return selected; 308 } 309 310 int getIndent() { 311 return indent; 312 } 313 314 int getType() { 315 return type; 316 } 317 318 public Dimension getPreferredSize() { 319 if (!swingRendering) { 320 if (prefSize == null) { 321 prefSize = getUI().getPreferredSize(this); 322 } 323 324 return prefSize; 325 } else { 326 return super.getPreferredSize(); 327 } 328 } 329 330 336 public String getText() { 337 String result = super.getText(); 338 339 if (swingRendering && Boolean.TRUE.equals(html)) { 340 result = ensureHtmlTags(result); 343 } else if (swingRendering && (html == null)) { 344 html = checkHtml(super.getText()); 346 347 if (Boolean.TRUE.equals(html)) { 348 result = ensureHtmlTags(result); 349 } 350 } 351 352 return result; 353 } 354 355 364 private String ensureHtmlTags(String s) { 365 s = ensureLegalFontColorTags(s); 366 367 if (!s.startsWith("<HTML") && !s.startsWith("<html")) { s = "<html>" + s + "</html>"; } 370 371 return s; 372 } 373 374 380 private static String ensureLegalFontColorTags(String s) { 381 String check = s.toUpperCase(); 382 int start = 0; 383 int fidx = check.indexOf("<FONT", start); StringBuffer sb = null; 385 386 if ((fidx != -1) && (fidx <= s.length())) { 387 while ((fidx != -1) && (fidx <= s.length())) { 388 int cidx = check.indexOf("COLOR", start); int tagEnd = check.indexOf('>', start); start = tagEnd + 1; 391 392 if (tagEnd == -1) { 393 break; 394 } 395 396 if (cidx != -1) { 397 if (cidx < tagEnd) { 398 int eidx = check.indexOf('=', cidx); 401 if (eidx != -1) { 402 int bangIdx = check.indexOf('!', eidx); 404 if ((bangIdx != -1) && (bangIdx < tagEnd)) { 405 int colorStart = bangIdx + 1; 406 int colorEnd = tagEnd; 407 408 for (int i = colorStart; i < tagEnd; i++) { 409 char c = s.charAt(i); 410 411 if (!Character.isLetter(c)) { 412 colorEnd = i; 413 414 break; 415 } 416 } 417 418 if (sb == null) { 419 sb = new StringBuffer (s); 420 } 421 422 String colorString = s.substring(colorStart, colorEnd); 423 String converted = convertToStandardColor(colorString); 424 sb.replace(bangIdx, colorEnd, converted); 425 s = sb.toString(); 426 check = s.toUpperCase(); 427 } 428 } 429 } 430 } 431 432 fidx = check.indexOf("<FONT", start); start = fidx; 434 } 435 } 436 437 if (sb != null) { 438 return sb.toString(); 439 } else { 440 return s; 441 } 442 } 443 444 452 private static String convertToStandardColor(String colorString) { 453 Color c = UIManager.getColor(colorString); 454 455 if (c == null) { 456 c = Color.BLACK; 457 } 458 459 StringBuffer sb = new StringBuffer (7); 460 sb.append('#'); 461 sb.append(hexString(c.getRed())); 462 sb.append(hexString(c.getGreen())); 463 sb.append(hexString(c.getBlue())); 464 465 return sb.toString(); 466 } 467 468 475 private static String hexString(int r) { 476 String s = Integer.toHexString(r); 477 478 if (s.length() == 1) { 479 s = '0' + s; 480 } 481 482 return s; 483 } 484 485 487 protected final void firePropertyChange(String name, Object old, Object nue) { 488 if (swingRendering) { 489 if ("text".equals(name) && isHtml()) { 490 nue = getText(); 492 } 493 494 super.firePropertyChange(name, old, nue); 495 } 496 } 497 498 public Border getBorder() { 499 Border result; 500 501 if ((indent != 0) && swingRendering) { 502 result = BorderFactory.createEmptyBorder(0, indent, 0, 0); 503 } else { 504 result = border; 505 } 506 507 return result; 508 } 509 510 public void setBorder(Border b) { 511 Border old = border; 512 border = b; 513 514 if (swingRendering) { 515 firePropertyChange("border", old, b); 516 } 517 } 518 519 public Insets getInsets() { 520 Insets result; 521 522 Border b = getBorder(); 526 527 if (b == null) { 528 result = EMPTY_INSETS; 529 } else { 530 result = b.getBorderInsets(this); 531 } 532 533 return result; 534 } 535 536 public void setEnabled(boolean b) { 537 enabled = b; 539 540 if (swingRendering) { 541 super.setEnabled(b); 542 } 543 } 544 545 public boolean isEnabled() { 546 return enabled; 547 } 548 549 public void updateUI() { 550 if (swingRendering) { 551 super.updateUI(); 552 } else { 553 setUI(HtmlLabelUI.createUI(this)); 554 } 555 } 556 557 561 public Graphics getGraphics() { 562 Graphics result = null; 563 564 if (isDisplayable()) { 565 result = super.getGraphics(); 566 } 567 568 if (result == null) { 569 result = scratchGraphics(); 570 } 571 572 return result; 573 } 574 575 577 private static final Graphics scratchGraphics() { 578 Graphics result = null; 579 580 if (scratchGraphics != null) { 581 result = scratchGraphics.get(); 582 583 if (result != null) { 584 result.setClip(null); } 586 } 587 588 if (result == null) { 589 result = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration() 590 .createCompatibleImage(1, 1).getGraphics(); 591 592 if (!noCacheGraphics) { 593 scratchGraphics = new SoftReference <Graphics>(result); 594 } 595 } 596 597 return result; 598 } 599 600 public void setBounds(int x, int y, int w, int h) { 601 if (swingRendering) { 602 super.setBounds(x, y, w, h); 603 } 604 605 bounds.setBounds(x, y, w, h); 606 } 607 608 public void reshape(int x, int y, int w, int h) { 609 if (swingRendering) { 610 super.reshape(x, y, w, h); 611 } 612 } 613 614 public int getWidth() { 615 return bounds.width; 616 } 617 618 public int getHeight() { 619 return bounds.height; 620 } 621 622 public Point getLocation() { 623 return bounds.getLocation(); 624 } 625 626 627 public void validate() { 628 } 630 631 632 public void repaint(long tm, int x, int y, int w, int h) { 633 } 635 636 637 public void repaint() { 638 } 640 641 642 public void invalidate() { 643 } 645 646 647 public void revalidate() { 648 } 650 651 652 public void addAncestorListener(AncestorListener l) { 653 if (swingRendering) { 654 super.addAncestorListener(l); 655 } 656 } 657 658 659 public void addComponentListener(ComponentListener l) { 660 if (swingRendering) { 661 super.addComponentListener(l); 662 } 663 } 664 665 666 public void addContainerListener(ContainerListener l) { 667 if (swingRendering) { 668 super.addContainerListener(l); 669 } 670 } 671 672 673 public void addHierarchyListener(HierarchyListener l) { 674 if (swingRendering) { 675 super.addHierarchyListener(l); 676 } 677 } 678 679 680 public void addHierarchyBoundsListener(HierarchyBoundsListener l) { 681 if (swingRendering) { 682 super.addHierarchyBoundsListener(l); 683 } 684 } 685 686 687 public void addInputMethodListener(InputMethodListener l) { 688 if (swingRendering) { 689 super.addInputMethodListener(l); 690 } 691 } 692 693 694 public void addFocusListener(FocusListener fl) { 695 if (swingRendering) { 696 super.addFocusListener(fl); 697 } 698 } 699 700 701 public void addMouseListener(MouseListener ml) { 702 if (swingRendering) { 703 super.addMouseListener(ml); 704 } 705 } 706 707 708 public void addMouseWheelListener(MouseWheelListener ml) { 709 if (swingRendering) { 710 super.addMouseWheelListener(ml); 711 } 712 } 713 714 715 public void addMouseMotionListener(MouseMotionListener ml) { 716 if (swingRendering) { 717 super.addMouseMotionListener(ml); 718 } 719 } 720 721 722 public void addVetoableChangeListener(VetoableChangeListener vl) { 723 if (swingRendering) { 724 super.addVetoableChangeListener(vl); 725 } 726 } 727 728 729 public void addPropertyChangeListener(String s, PropertyChangeListener l) { 730 if (swingRendering) { 731 super.addPropertyChangeListener(s, l); 732 } 733 } 734 735 public void addPropertyChangeListener(PropertyChangeListener l) { 736 if (swingRendering) { 737 super.addPropertyChangeListener(l); 738 } 739 } 740 } 741 | Popular Tags |