1 19 24 25 package org.netbeans.swing.tabcontrol.plaf; 26 27 import org.netbeans.swing.tabcontrol.TabData; 28 import org.netbeans.swing.tabcontrol.TabDisplayer; 29 30 import org.openide.awt.HtmlRenderer; 31 32 import javax.swing.*; 33 import javax.swing.border.Border ; 34 import java.awt.*; 35 import java.awt.event.ContainerListener ; 36 import java.awt.event.HierarchyBoundsListener ; 37 import java.awt.event.HierarchyListener ; 38 import java.awt.event.MouseEvent ; 39 40 57 public abstract class AbstractTabCellRenderer extends JLabel 58 implements TabCellRenderer { 59 private int state = TabState.NOT_ONSCREEN; 60 TabPainter leftBorder; 61 TabPainter rightBorder; 62 TabPainter normalBorder; 63 private Dimension padding; 64 65 68 public AbstractTabCellRenderer(TabPainter leftClip, TabPainter noClip, 69 TabPainter rightClip, Dimension padding) { 70 setOpaque(false); 71 setFocusable(false); 72 setBorder(noClip); 73 normalBorder = noClip; 74 leftBorder = leftClip; 75 rightBorder = rightClip; 76 this.padding = padding; 77 } 78 79 public AbstractTabCellRenderer (TabPainter painter, Dimension padding) { 80 this (painter, painter, painter, padding); 81 } 82 83 private boolean showClose = true; 84 public final void setShowCloseButton (boolean b) { 85 showClose = b; 86 } 87 88 public final boolean isShowCloseButton() { 89 return showClose; 90 } 91 92 private Rectangle scratch = new Rectangle(); 93 public String getCommandAtPoint(Point p, int tabState, Rectangle bounds) { 94 setBounds (bounds); 95 setState (tabState); 96 if (supportsCloseButton(getBorder()) && isShowCloseButton()) { 97 TabPainter cbp = (TabPainter) getBorder(); 98 cbp.getCloseButtonRectangle (this, scratch, bounds); 99 if (getClass() != AquaEditorTabCellRenderer.class) { 100 scratch.x -=3; 102 scratch.y -=3; 103 scratch.width += 6; 104 scratch.height += 6; 105 } 106 if (scratch.contains(p)) { 107 return TabDisplayer.COMMAND_CLOSE; 108 } 109 } 110 Polygon tabShape = getTabShape (tabState, bounds); 111 if (tabShape.contains(p)) { 112 return TabDisplayer.COMMAND_SELECT; 113 } 114 return null; 115 } 116 117 public String getCommandAtPoint(Point p, int tabState, Rectangle bounds, int mouseButton, int eventType, int modifiers) { 118 String result = null; 119 if (mouseButton == MouseEvent.BUTTON2 && eventType == MouseEvent.MOUSE_RELEASED) { 120 result = TabDisplayer.COMMAND_CLOSE; 121 } 122 else { 123 result = getCommandAtPoint (p, tabState, bounds); 124 } 125 if (result != null) { 126 if (TabDisplayer.COMMAND_SELECT == result) { 127 boolean clipped = isClipLeft() || isClipRight(); 128 if ((clipped && eventType == MouseEvent.MOUSE_RELEASED && mouseButton == MouseEvent.BUTTON1) || 129 (!clipped && eventType == MouseEvent.MOUSE_PRESSED && mouseButton == MouseEvent.BUTTON1)) { 130 131 return result; 132 } 133 } else if (TabDisplayer.COMMAND_CLOSE == result && eventType == MouseEvent.MOUSE_RELEASED && isShowCloseButton()) { 134 if ((modifiers & MouseEvent.SHIFT_DOWN_MASK) != 0) { 135 return TabDisplayer.COMMAND_CLOSE_ALL; 136 } else if ((modifiers & MouseEvent.ALT_DOWN_MASK) != 0 && mouseButton != MouseEvent.BUTTON2) { 137 return TabDisplayer.COMMAND_CLOSE_ALL_BUT_THIS; 138 } 139 return result; 140 } 141 } 142 return null; 143 } 144 145 147 152 protected final boolean isArmed() { 153 return isPressed() || (state & TabState.ARMED) != 0; 154 } 155 156 161 protected final boolean isActive() { 162 return (state & TabState.ACTIVE) != 0; 163 } 164 165 170 protected final boolean isPressed() { 171 return (state & TabState.PRESSED) != 0; 172 } 173 174 179 protected final boolean isSelected() { 180 return (state & TabState.SELECTED) != 0; 181 } 182 183 187 protected final boolean isClipRight() { 188 return (state & TabState.CLIP_RIGHT) != 0; 189 } 190 191 195 protected final boolean isClipLeft() { 196 return (state & TabState.CLIP_LEFT) != 0; 197 } 198 199 203 protected final boolean isLeftmost() { 204 return (state & TabState.LEFTMOST) != 0; 205 } 206 207 211 protected final boolean isRightmost() { 212 return (state & TabState.RIGHTMOST) != 0; 213 } 214 215 protected final boolean isAttention() { 216 return (state & TabState.ATTENTION) != 0; 217 } 218 219 224 protected final boolean isNextTabSelected() { 225 return (state & TabState.BEFORE_SELECTED) != 0; 226 } 227 228 233 protected final boolean isNextTabArmed() { 234 return (state & TabState.BEFORE_ARMED) != 0; 235 } 236 237 242 protected final boolean isPreviousTabSelected() { 243 return (state & TabState.AFTER_SELECTED) != 0; 244 } 245 246 public Dimension getPadding() { 247 return new Dimension(padding); 248 } 249 250 private int phash = -1; 251 252 259 protected final void setState(int state) { 260 boolean needChange = this.state != state; 262 if (needChange) { 263 int old = this.state; 264 this.state = state; 268 int newState = stateChanged(old, state); 269 if ((newState & this.state) != state) { 270 this.state = state; 271 throw new IllegalStateException ("StateChanged may add, but not remove bits from the " + 272 "state bitmask. Expected state: " + TabState.stateToString( 273 state) + " but got " + TabState.stateToString(this.state)); 274 } 275 this.state = newState; 276 } 277 } 278 279 282 public final int getState() { 283 return state; 284 } 285 286 294 public final javax.swing.JComponent getRendererComponent(TabData data, 295 Rectangle bounds, 296 int state) { 297 setBounds(bounds); 298 setText(data.getText()); 299 setIcon(data.getIcon()); 300 setState(state); 301 return this; 302 } 303 304 311 312 protected int stateChanged(int oldState, int newState) { 313 Color bg = isSelected() ? 314 isActive() ? 315 getSelectedActivatedBackground() : getSelectedBackground() : 316 UIManager.getColor("control"); 317 Color fg = isSelected() ? 318 isActive() ? 319 getSelectedActivatedForeground() : getSelectedForeground() : 320 UIManager.getColor("textText"); 321 322 if (isArmed() && isPressed() && (isClipLeft() || isClipRight())) { 323 bg = getSelectedActivatedBackground(); 326 fg = getSelectedActivatedForeground(); 327 } 328 329 if (isClipLeft()) { 330 setIcon(null); 331 setBorder(leftBorder); 332 } else if (isClipRight()) { 333 setBorder(rightBorder); 334 } else { 335 setBorder(normalBorder); 336 } 337 338 setBackground(bg); 339 setForeground(fg); 340 return newState; 341 } 342 343 344 public void revalidate() { 345 } 347 348 349 public void repaint() { 350 } 352 353 354 public void validate() { 355 } 357 358 359 public void repaint(long tm) { 360 } 362 363 364 public void repaint(long tm, int x, int y, int w, int h) { 365 } 367 368 369 protected final void firePropertyChange(String s, Object a, Object b) { 370 } 372 373 374 public final void addHierarchyBoundsListener(HierarchyBoundsListener hbl) { 375 } 377 378 379 public final void addHierarchyListener(HierarchyListener hl) { 380 } 382 383 384 public final void addContainerListener(ContainerListener cl) { 385 } 387 388 391 public void paintComponent(Graphics g) { 392 g.setColor(getBackground()); 393 if (getBorder() instanceof TabPainter) { 394 ((TabPainter) getBorder()).paintInterior(g, this); 395 } 396 paintIconAndText(g); 397 } 398 399 403 protected int getCaptionYAdjustment() { 404 return -1; 405 } 406 407 411 protected int getIconYAdjustment() { 412 return -1; 413 } 414 415 420 protected void paintIconAndText(Graphics g) { 421 g.setFont(getFont()); 422 FontMetrics fm = g.getFontMetrics(getFont()); 423 int txtH = fm.getHeight(); 425 Insets ins = getInsets(); 426 int availH = getHeight() - (ins.top + ins.bottom); 428 int txtY; 429 if (availH > txtH) { 430 txtY = txtH + ins.top + ((availH / 2) - (txtH / 2)) - 3; 431 } else { 432 txtY = txtH + ins.top; 433 } 434 int txtX; 435 436 int centeringToAdd = getPixelsToAddToSelection() != 0 ? 437 getPixelsToAddToSelection() / 2 : 0; 438 439 Icon icon = getIcon(); 440 if (!isClipLeft() && icon != null && icon.getIconWidth() > 0 442 && icon.getIconHeight() > 0) { 443 int iconY; 444 if (availH > icon.getIconHeight()) { 445 iconY = ins.top 447 + ((availH / 2) - (icon.getIconHeight() / 2)) 448 + 2; 449 } else { 450 iconY = ins.top + 2; 452 } 453 int iconX = ins.left + centeringToAdd; 454 455 iconY += getIconYAdjustment(); 456 457 icon.paintIcon(this, g, iconX, iconY); 458 txtX = iconX + icon.getIconWidth() + getIconTextGap(); 459 } else { 460 txtX = ins.left + centeringToAdd; 461 } 462 463 if (icon != null && icon.getIconWidth() == 0) { 464 txtX += 5; 467 } 468 469 txtY += getCaptionYAdjustment(); 470 471 int txtW = getWidth() - (txtX + ins.right); 473 if (isClipLeft()) { 474 String s = preTruncateString(getText(), g, txtW - 4); HtmlRenderer.renderString(s, g, txtX, txtY, txtW, txtH, getFont(), 477 getForeground(), HtmlRenderer.STYLE_CLIP, true); 478 } else { 479 String s; 480 if (isClipRight()) { 481 s = getText() + "..."; } else { 485 s = getText(); 486 } 487 HtmlRenderer.renderString(s, g, txtX, txtY, txtW, txtH, getFont(), 488 getForeground(), HtmlRenderer.STYLE_TRUNCATE, true); 489 } 490 } 491 492 static String preTruncateString(String s, Graphics g, int availPixels) { 493 if (s.length() < 3) { 494 return s; 495 } 496 s = stripHTML(s); 497 if (s.length() < 2) { 498 return "..." + s; } 500 FontMetrics fm = g.getFontMetrics(); 501 int dotsWidth = fm.stringWidth("..."); int beginIndex = s.length() - 2; 503 String test = s.substring(beginIndex); 504 String result = test; 505 while (fm.stringWidth(test) + dotsWidth < availPixels) { 506 beginIndex--; 507 if (beginIndex <= 0) { 508 break; 509 } else { 510 result = test; 511 test = s.substring(beginIndex); 512 } 513 } 514 return "..." + result; } 516 517 static boolean isHTML(String s) { 518 boolean result = s.startsWith("<html>") 519 || s.startsWith("<HTML>"); return result; 521 } 522 523 static String stripHTML(String s) { 524 if (isHTML(s)) { 525 StringBuffer result = new StringBuffer (s.length()); 526 char[] c = s.toCharArray(); 527 boolean inTag = false; 528 for (int i = 0; i < c.length; i++) { 529 boolean wasInTag = inTag; 531 if (!inTag) { 532 if (c[i] == '<') { 533 inTag = true; 534 } 535 } else { 536 if (c[i] == '>') { 537 inTag = false; 538 } 539 } 540 if (!inTag && wasInTag == inTag) { 541 result.append(c[i]); 542 } 543 } 544 return result.toString(); 545 } else { 546 return s; 547 } 548 } 549 550 557 public Polygon getTabShape(int tabState, Rectangle bounds) { 558 setBounds(bounds); 559 setState(tabState); 560 if (getBorder() instanceof TabPainter) { 561 TabPainter pb = (TabPainter) getBorder(); 562 Polygon p = pb.getInteriorPolygon(this); 563 p.translate(bounds.x, bounds.y); 564 return p; 565 } else { 566 return new Polygon(new int[]{ 568 bounds.x, bounds.x + bounds.width - 1, 569 bounds.x + bounds.width - 1, bounds.x}, new int[]{ 570 bounds.y, bounds.y, bounds.y + bounds.height - 1, 571 bounds.y + bounds.height - 1}, 4); 572 } 573 } 574 575 576 577 578 public Color getSelectedBackground() { 579 Color base = UIManager.getColor("control"); Color towards = UIManager.getColor("controlHighlight"); 582 if (base == null) { 583 base = Color.GRAY; 584 } 585 if (towards == null) { 586 towards = Color.WHITE; 587 } 588 589 Color result = ColorUtil.adjustTowards(base, 30, towards); 590 return result; 591 } 592 593 public Color getSelectedActivatedBackground() { 594 return UIManager.getColor("TabRenderer.selectedActivatedBackground"); 595 } 596 597 public Color getSelectedActivatedForeground() { 598 return UIManager.getColor("TabRenderer.selectedActivatedForeground"); 599 } 600 601 public Color getSelectedForeground() { 602 return UIManager.getColor("TabRenderer.selectedForeground"); 603 } 604 605 protected boolean inCloseButton() { 606 return (state & TabState.CLOSE_BUTTON_ARMED) != 0; 607 } 608 609 613 public int getPixelsToAddToSelection() { 614 return 0; 615 } 616 617 private boolean supportsCloseButton(Border b) { 618 if (b instanceof TabPainter) { 619 return ((TabPainter) b).supportsCloseButton(this); 620 } else { 621 return false; 622 } 623 } 624 } 625 | Popular Tags |