1 30 31 package com.jgoodies.looks.plastic; 32 33 import java.awt.Color ; 34 import java.awt.Component ; 35 import java.awt.Container ; 36 import java.awt.Dimension ; 37 import java.awt.Font ; 38 import java.awt.FontMetrics ; 39 import java.awt.Graphics ; 40 import java.awt.Graphics2D ; 41 import java.awt.Insets ; 42 import java.awt.LayoutManager ; 43 import java.awt.Point ; 44 import java.awt.Polygon ; 45 import java.awt.Rectangle ; 46 import java.awt.Shape ; 47 import java.awt.event.ActionEvent ; 48 import java.awt.event.ActionListener ; 49 import java.awt.event.MouseEvent ; 50 import java.beans.PropertyChangeEvent ; 51 import java.beans.PropertyChangeListener ; 52 53 import javax.swing.AbstractAction ; 54 import javax.swing.Action ; 55 import javax.swing.ActionMap ; 56 import javax.swing.Icon ; 57 import javax.swing.JButton ; 58 import javax.swing.JComponent ; 59 import javax.swing.JPanel ; 60 import javax.swing.JTabbedPane ; 61 import javax.swing.JViewport ; 62 import javax.swing.SwingConstants ; 63 import javax.swing.SwingUtilities ; 64 import javax.swing.UIManager ; 65 import javax.swing.event.ChangeEvent ; 66 import javax.swing.event.ChangeListener ; 67 import javax.swing.plaf.ComponentUI ; 68 import javax.swing.plaf.UIResource ; 69 import javax.swing.plaf.basic.BasicTabbedPaneUI ; 70 import javax.swing.plaf.metal.MetalTabbedPaneUI ; 71 import javax.swing.text.View ; 72 73 import com.jgoodies.looks.LookUtils; 74 import com.jgoodies.looks.Options; 75 76 112 public final class PlasticTabbedPaneUI extends MetalTabbedPaneUI { 113 114 115 117 120 private static boolean isTabIconsEnabled = Options.isTabIconsEnabled(); 121 122 127 private Boolean noContentBorder; 128 129 135 private Boolean embeddedTabs; 136 137 140 private AbstractRenderer renderer; 141 142 143 144 private ScrollableTabSupport tabScroller; 145 146 151 public static ComponentUI createUI(JComponent tabPane) { 152 return new PlasticTabbedPaneUI(); 153 } 154 155 160 public void installUI(JComponent c) { 161 super.installUI(c); 162 embeddedTabs = (Boolean ) c.getClientProperty(Options.EMBEDDED_TABS_KEY); 163 noContentBorder = (Boolean ) c.getClientProperty(Options.NO_CONTENT_BORDER_KEY); 164 renderer = createRenderer(tabPane); 165 } 166 167 171 public void uninstallUI(JComponent c) { 172 renderer = null; 173 super.uninstallUI(c); 174 } 175 176 181 protected void installComponents() { 182 if (scrollableTabLayoutEnabled()) { 183 if (tabScroller == null) { 184 tabScroller = new ScrollableTabSupport(tabPane.getTabPlacement()); 185 tabPane.add(tabScroller.viewport); 186 } 187 } 188 } 189 190 195 protected void uninstallComponents() { 196 if (scrollableTabLayoutEnabled()) { 197 tabPane.remove(tabScroller.viewport); 198 tabPane.remove(tabScroller.scrollForwardButton); 199 tabPane.remove(tabScroller.scrollBackwardButton); 200 tabScroller = null; 201 } 202 } 203 204 protected void installListeners() { 205 super.installListeners(); 206 if ((mouseListener != null) && (LookUtils.IS_JAVA_1_4)) { 213 if (scrollableTabLayoutEnabled()) { 214 tabPane.removeMouseListener(mouseListener); 215 tabScroller.tabPanel.addMouseListener(mouseListener); 216 } 217 } 218 } 219 220 protected void uninstallListeners() { 221 if ((mouseListener != null) && (LookUtils.IS_JAVA_1_4)) { 222 if (scrollableTabLayoutEnabled()) { tabScroller.tabPanel.removeMouseListener(mouseListener); 224 } else { tabPane.removeMouseListener(mouseListener); 226 } 227 mouseListener = null; 228 } 229 super.uninstallListeners(); 230 } 231 232 protected void installKeyboardActions() { 233 super.installKeyboardActions(); 234 if (scrollableTabLayoutEnabled()) { 238 Action forwardAction = new ScrollTabsForwardAction(); 239 Action backwardAction = new ScrollTabsBackwardAction(); 240 ActionMap am = SwingUtilities.getUIActionMap(tabPane); 241 am.put("scrollTabsForwardAction", forwardAction); 242 am.put("scrollTabsBackwardAction", backwardAction); 243 tabScroller.scrollForwardButton.setAction(forwardAction); 244 tabScroller.scrollBackwardButton.setAction(backwardAction); 245 } 246 } 247 248 253 private boolean hasNoContentBorder() { 254 return Boolean.TRUE.equals(noContentBorder); 255 } 256 257 260 private boolean hasEmbeddedTabs() { 261 return Boolean.TRUE.equals(embeddedTabs); 262 } 263 264 269 private AbstractRenderer createRenderer(JTabbedPane tabbedPane) { 270 return hasEmbeddedTabs() 271 ? AbstractRenderer.createEmbeddedRenderer(tabbedPane) 272 : AbstractRenderer.createRenderer(tabPane); 273 } 274 275 280 protected PropertyChangeListener createPropertyChangeListener() { 281 return new MyPropertyChangeHandler(); 282 } 283 284 protected ChangeListener createChangeListener() { 285 return new TabSelectionHandler(); 286 } 287 288 291 private void doLayout() { 292 tabPane.revalidate(); 293 tabPane.repaint(); 294 } 295 296 300 private void tabPlacementChanged() { 301 renderer = createRenderer(tabPane); 302 if (scrollableTabLayoutEnabled()) { 303 tabScroller.createButtons(); 304 } 305 doLayout(); 306 } 307 308 312 private void embeddedTabsPropertyChanged(Boolean newValue) { 313 embeddedTabs = newValue; 314 renderer = createRenderer(tabPane); 315 doLayout(); 316 } 317 318 323 private void noContentBorderPropertyChanged(Boolean newValue) { 324 noContentBorder = newValue; 325 tabPane.repaint(); 326 } 327 328 public void paint(Graphics g, JComponent c) { 329 int selectedIndex = tabPane.getSelectedIndex(); 330 int tabPlacement = tabPane.getTabPlacement(); 331 332 ensureCurrentLayout(); 333 334 if (!scrollableTabLayoutEnabled()) { paintTabArea(g, tabPlacement, selectedIndex); 340 } 341 342 paintContentBorder(g, tabPlacement, selectedIndex); 344 } 345 346 protected void paintTab(Graphics g, int tabPlacement, Rectangle [] rects, 347 int tabIndex, Rectangle iconRect, Rectangle textRect) { 348 Rectangle tabRect = rects[tabIndex]; 349 int selectedIndex = tabPane.getSelectedIndex(); 350 boolean isSelected = selectedIndex == tabIndex; 351 Graphics2D g2 = null; 352 Polygon cropShape = null; 353 Shape save = null; 354 int cropx = 0; 355 int cropy = 0; 356 357 if (scrollableTabLayoutEnabled()) { 358 if (g instanceof Graphics2D ) { 359 g2 = (Graphics2D ) g; 360 361 Rectangle viewRect = tabScroller.viewport.getViewRect(); 363 int cropline; 364 switch (tabPlacement) { 365 case LEFT: 366 case RIGHT: 367 cropline = viewRect.y + viewRect.height; 368 if ((tabRect.y < cropline) 369 && (tabRect.y + tabRect.height > cropline)) { 370 cropShape = createCroppedTabClip(tabPlacement, tabRect, 371 cropline); 372 cropx = tabRect.x; 373 cropy = cropline - 1; 374 } 375 break; 376 case TOP: 377 case BOTTOM: 378 default: 379 cropline = viewRect.x + viewRect.width; 380 if ((tabRect.x < cropline) 381 && (tabRect.x + tabRect.width > cropline)) { 382 cropShape = createCroppedTabClip(tabPlacement, tabRect, 383 cropline); 384 cropx = cropline - 1; 385 cropy = tabRect.y; 386 } 387 } 388 if (cropShape != null) { 389 save = g2.getClip(); 390 g2.clip(cropShape); 391 } 392 } 393 } 394 395 paintTabBackground(g, tabPlacement, tabIndex, tabRect.x, tabRect.y, 396 tabRect.width, tabRect.height, isSelected); 397 398 paintTabBorder(g, tabPlacement, tabIndex, tabRect.x, tabRect.y, 399 tabRect.width, tabRect.height, isSelected); 400 401 String title = tabPane.getTitleAt(tabIndex); 402 Font font = tabPane.getFont(); 403 FontMetrics metrics = g.getFontMetrics(font); 404 Icon icon = getIconForTab(tabIndex); 405 406 layoutLabel(tabPlacement, metrics, tabIndex, title, icon, tabRect, 407 iconRect, textRect, isSelected); 408 409 paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, 410 isSelected); 411 412 paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected); 413 414 paintFocusIndicator(g, tabPlacement, rects, tabIndex, iconRect, 415 textRect, isSelected); 416 417 if (cropShape != null) { 418 paintCroppedTabEdge(g, tabPlacement, tabIndex, isSelected, cropx, 419 cropy); 420 g2.setClip(save); 421 } 422 } 423 424 446 private int xCropLen[] = { 1, 1, 0, 0, 1, 1, 2, 2 }; 447 448 private int yCropLen[] = { 0, 3, 3, 6, 6, 9, 9, 12 }; 449 450 private static final int CROP_SEGMENT = 12; 451 452 private Polygon createCroppedTabClip(int tabPlacement, Rectangle tabRect, 453 int cropline) { 454 int rlen = 0; 455 int start = 0; 456 int end = 0; 457 int ostart = 0; 458 459 switch (tabPlacement) { 460 case LEFT: 461 case RIGHT: 462 rlen = tabRect.width; 463 start = tabRect.x; 464 end = tabRect.x + tabRect.width; 465 ostart = tabRect.y; 466 break; 467 case TOP: 468 case BOTTOM: 469 default: 470 rlen = tabRect.height; 471 start = tabRect.y; 472 end = tabRect.y + tabRect.height; 473 ostart = tabRect.x; 474 } 475 int rcnt = rlen / CROP_SEGMENT; 476 if (rlen % CROP_SEGMENT > 0) { 477 rcnt++; 478 } 479 int npts = 2 + (rcnt * 8); 480 int xp[] = new int[npts]; 481 int yp[] = new int[npts]; 482 int pcnt = 0; 483 484 xp[pcnt] = ostart; 485 yp[pcnt++] = end; 486 xp[pcnt] = ostart; 487 yp[pcnt++] = start; 488 for (int i = 0; i < rcnt; i++) { 489 for (int j = 0; j < xCropLen.length; j++) { 490 xp[pcnt] = cropline - xCropLen[j]; 491 yp[pcnt] = start + (i * CROP_SEGMENT) + yCropLen[j]; 492 if (yp[pcnt] >= end) { 493 yp[pcnt] = end; 494 pcnt++; 495 break; 496 } 497 pcnt++; 498 } 499 } 500 if (tabPlacement == SwingConstants.TOP 501 || tabPlacement == SwingConstants.BOTTOM) { 502 return new Polygon (xp, yp, pcnt); 503 504 } 505 return new Polygon (yp, xp, pcnt); 507 } 508 509 512 private void paintCroppedTabEdge(Graphics g, int tabPlacement, 513 int tabIndex, boolean isSelected, int x, int y) { 514 switch (tabPlacement) { 515 case LEFT: 516 case RIGHT: 517 int xx = x; 518 g.setColor(shadow); 519 while (xx <= x + rects[tabIndex].width) { 520 for (int i = 0; i < xCropLen.length; i += 2) { 521 g.drawLine(xx + yCropLen[i], y - xCropLen[i], xx 522 + yCropLen[i + 1] - 1, y - xCropLen[i + 1]); 523 } 524 xx += CROP_SEGMENT; 525 } 526 break; 527 case TOP: 528 case BOTTOM: 529 default: 530 int yy = y; 531 g.setColor(shadow); 532 while (yy <= y + rects[tabIndex].height) { 533 for (int i = 0; i < xCropLen.length; i += 2) { 534 g.drawLine(x - xCropLen[i], yy + yCropLen[i], x 535 - xCropLen[i + 1], yy + yCropLen[i + 1] - 1); 536 } 537 yy += CROP_SEGMENT; 538 } 539 } 540 } 541 542 private void ensureCurrentLayout() { 543 if (!tabPane.isValid()) { 544 tabPane.validate(); 545 } 546 550 if (!tabPane.isValid()) { 551 TabbedPaneLayout layout = (TabbedPaneLayout) tabPane.getLayout(); 552 layout.calculateLayoutInfo(); 553 } 554 } 555 556 560 public int tabForCoordinate(JTabbedPane pane, int x, int y) { 561 ensureCurrentLayout(); 562 Point p = new Point (x, y); 563 564 if (scrollableTabLayoutEnabled()) { 565 translatePointToTabPanel(x, y, p); 566 Rectangle viewRect = tabScroller.viewport.getViewRect(); 567 if (!viewRect.contains(p)) { 568 return -1; 569 } 570 } 571 int tabCount = tabPane.getTabCount(); 572 for (int i = 0; i < tabCount; i++) { 573 if (rects[i].contains(p.x, p.y)) { 574 return i; 575 } 576 } 577 return -1; 578 } 579 580 protected Rectangle getTabBounds(int tabIndex, Rectangle dest) { 581 dest.width = rects[tabIndex].width; 582 dest.height = rects[tabIndex].height; 583 if (scrollableTabLayoutEnabled()) { Point vpp = tabScroller.viewport.getLocation(); 587 Point viewp = tabScroller.viewport.getViewPosition(); 588 dest.x = rects[tabIndex].x + vpp.x - viewp.x; 589 dest.y = rects[tabIndex].y + vpp.y - viewp.y; 590 } else { dest.x = rects[tabIndex].x; 592 dest.y = rects[tabIndex].y; 593 } 594 return dest; 595 } 596 597 601 private int getClosestTab(int x, int y) { 602 int min = 0; 603 int tabCount = Math.min(rects.length, tabPane.getTabCount()); 604 int max = tabCount; 605 int tabPlacement = tabPane.getTabPlacement(); 606 boolean useX = (tabPlacement == TOP || tabPlacement == BOTTOM); 607 int want = (useX) ? x : y; 608 609 while (min != max) { 610 int current = (max + min) / 2; 611 int minLoc; 612 int maxLoc; 613 614 if (useX) { 615 minLoc = rects[current].x; 616 maxLoc = minLoc + rects[current].width; 617 } else { 618 minLoc = rects[current].y; 619 maxLoc = minLoc + rects[current].height; 620 } 621 if (want < minLoc) { 622 max = current; 623 if (min == max) { 624 return Math.max(0, current - 1); 625 } 626 } else if (want >= maxLoc) { 627 min = current; 628 if (max - min <= 1) { 629 return Math.max(current + 1, tabCount - 1); 630 } 631 } else { 632 return current; 633 } 634 } 635 return min; 636 } 637 638 643 private Point translatePointToTabPanel(int srcx, int srcy, Point dest) { 644 Point vpp = tabScroller.viewport.getLocation(); 645 Point viewp = tabScroller.viewport.getViewPosition(); 646 dest.x = srcx - vpp.x + viewp.x; 647 dest.y = srcy - vpp.y + viewp.y; 648 return dest; 649 } 650 651 protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) { 652 int tabCount = tabPane.getTabCount(); 653 654 Rectangle iconRect = new Rectangle (), 655 textRect = new Rectangle (); 656 Rectangle clipRect = g.getClipBounds(); 657 658 for (int i = runCount - 1; i >= 0; i--) { 660 int start = tabRuns[i]; 661 int next = tabRuns[(i == runCount - 1)? 0 : i + 1]; 662 int end = (next != 0? next - 1: tabCount - 1); 663 for (int j = end; j >= start; j--) { 664 if (j != selectedIndex && rects[j].intersects(clipRect)) { 665 paintTab(g, tabPlacement, rects, j, iconRect, textRect); 666 } 667 } 668 } 669 670 if (selectedIndex >= 0 && rects[selectedIndex].intersects(clipRect)) { 673 paintTab(g, tabPlacement, rects, selectedIndex, iconRect, textRect); 674 } 675 } 676 677 681 protected void layoutLabel( 682 int tabPlacement, 683 FontMetrics metrics, 684 int tabIndex, 685 String title, 686 Icon icon, 687 Rectangle tabRect, 688 Rectangle iconRect, 689 Rectangle textRect, 690 boolean isSelected) { 691 textRect.x = textRect.y = iconRect.x = iconRect.y = 0; 692 View v = getTextViewForTab(tabIndex); 694 if (v != null) { 695 tabPane.putClientProperty("html", v); 696 } 697 698 Rectangle calcRectangle = new Rectangle (tabRect); 699 if (isSelected) { 700 Insets calcInsets = getSelectedTabPadInsets(tabPlacement); 701 calcRectangle.x += calcInsets.left; 702 calcRectangle.y += calcInsets.top; 703 calcRectangle.width -= calcInsets.left + calcInsets.right ; 704 calcRectangle.height -= calcInsets.bottom + calcInsets.top; 705 } 706 int xNudge = getTabLabelShiftX(tabPlacement, tabIndex, isSelected); 707 int yNudge = getTabLabelShiftY(tabPlacement, tabIndex, isSelected); 708 if ((tabPlacement == RIGHT || tabPlacement == LEFT) && icon != null && title != null && !title.equals("")) { 709 SwingUtilities.layoutCompoundLabel( 710 tabPane, 711 metrics, 712 title, 713 icon, 714 SwingConstants.CENTER, 715 SwingConstants.LEFT, 716 SwingConstants.CENTER, 717 SwingConstants.TRAILING, 718 calcRectangle, 719 iconRect, 720 textRect, 721 textIconGap); 722 xNudge += 4; 723 } else { 724 SwingUtilities.layoutCompoundLabel( 725 tabPane, 726 metrics, 727 title, 728 icon, 729 SwingConstants.CENTER, 730 SwingConstants.CENTER, 731 SwingConstants.CENTER, 732 SwingConstants.TRAILING, 733 calcRectangle, 734 iconRect, 735 textRect, 736 textIconGap); 737 iconRect.y += calcRectangle.height %2; 738 } 739 740 tabPane.putClientProperty("html", null); 742 743 iconRect.x += xNudge; 744 iconRect.y += yNudge; 745 textRect.x += xNudge; 746 textRect.y += yNudge; 747 } 748 749 754 protected Icon getIconForTab(int tabIndex) { 755 String title = tabPane.getTitleAt(tabIndex); 756 boolean hasTitle = (title != null) && (title.length() > 0); 757 return !isTabIconsEnabled && hasTitle 758 ? null 759 : super.getIconForTab(tabIndex); 760 } 761 762 765 protected LayoutManager createLayoutManager() { 766 if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { 767 return new TabbedPaneScrollLayout(); 768 } 769 770 return new TabbedPaneLayout(); 771 } 772 773 778 private boolean scrollableTabLayoutEnabled() { 779 return tabPane.getLayout() instanceof TabbedPaneScrollLayout; 780 } 781 782 protected boolean isTabInFirstRun(int tabIndex) { 783 return getRunForTab(tabPane.getTabCount(), tabIndex) == 0; 784 } 785 786 protected void paintContentBorder(Graphics g, int tabPlacement, int selectedIndex) { 787 int width = tabPane.getWidth(); 788 int height = tabPane.getHeight(); 789 Insets insets = tabPane.getInsets(); 790 791 int x = insets.left; 792 int y = insets.top; 793 int w = width - insets.right - insets.left; 794 int h = height - insets.top - insets.bottom; 795 796 switch (tabPlacement) { 797 case LEFT : 798 x += calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth); 799 w -= (x - insets.left); 800 break; 801 case RIGHT : 802 w -= calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth); 803 break; 804 case BOTTOM : 805 h -= calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); 806 break; 807 case TOP : 808 default : 809 y += calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); 810 h -= (y - insets.top); 811 } 812 g.setColor(selectColor == null 814 ? tabPane.getBackground() 815 : selectColor); 816 g.fillRect(x, y, w, h); 817 818 Rectangle selRect; 819 selRect = (selectedIndex < 0) ? null : getTabBounds(selectedIndex, calcRect); 820 boolean drawBroken = selectedIndex >= 0 && isTabInFirstRun(selectedIndex); 821 boolean isContentBorderPainted = !hasNoContentBorder(); 822 renderer.paintContentBorderTopEdge (g, x, y, w, h, drawBroken, selRect, isContentBorderPainted); 827 renderer.paintContentBorderLeftEdge (g, x, y, w, h, drawBroken, selRect, isContentBorderPainted); 828 renderer.paintContentBorderBottomEdge(g, x, y, w, h, drawBroken, selRect, isContentBorderPainted); 829 renderer.paintContentBorderRightEdge (g, x, y, w, h, drawBroken, selRect, isContentBorderPainted); 830 } 831 832 839 protected Insets getContentBorderInsets(int tabPlacement) { 840 return renderer.getContentBorderInsets(super.getContentBorderInsets(tabPlacement)); 841 } 842 843 846 protected Insets getTabAreaInsets(int tabPlacement) { 847 return renderer.getTabAreaInsets(super.getTabAreaInsets(tabPlacement)); 848 } 849 850 853 protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) { 854 return renderer.getTabLabelShiftX(tabIndex, isSelected); 855 } 856 857 860 protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected) { 861 return renderer.getTabLabelShiftY(tabIndex, isSelected); 862 } 863 864 867 protected int getTabRunOverlay(int tabPlacement) { 868 return renderer.getTabRunOverlay(tabRunOverlay); 869 } 870 871 875 protected boolean shouldPadTabRun(int tabPlacement, int run) { 876 return renderer.shouldPadTabRun(run, super.shouldPadTabRun(tabPlacement, run)); 877 } 878 879 884 protected int getTabRunIndent(int tabPlacement, int run) { 885 return renderer.getTabRunIndent(run); 886 } 887 888 891 protected Insets getTabInsets(int tabPlacement, int tabIndex) { 892 return renderer.getTabInsets(tabIndex, tabInsets); 893 } 894 895 898 protected Insets getSelectedTabPadInsets(int tabPlacement) { 899 return renderer.getSelectedTabPadInsets(); 900 } 901 902 905 protected void paintFocusIndicator( 906 Graphics g, 907 int tabPlacement, 908 Rectangle [] rectangles, 909 int tabIndex, 910 Rectangle iconRect, 911 Rectangle textRect, 912 boolean isSelected) { 913 renderer.paintFocusIndicator(g, rectangles, tabIndex, iconRect, textRect, isSelected); 914 } 915 916 921 protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 922 renderer.paintTabBackground(g, tabIndex, x, y, w, h, isSelected); 923 } 924 925 930 protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 931 renderer.paintTabBorder(g, tabIndex, x, y, w, h, isSelected); 932 } 933 934 939 protected boolean shouldRotateTabRuns(int tabPlacement) { 940 return false; 941 } 942 943 private class TabSelectionHandler implements ChangeListener { 944 945 private Rectangle rect = new Rectangle (); 946 947 public void stateChanged(ChangeEvent e) { 948 JTabbedPane tabPane = (JTabbedPane )e.getSource(); 949 tabPane.revalidate(); 950 tabPane.repaint(); 951 952 if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { 953 int index = tabPane.getSelectedIndex(); 954 if (index < rects.length && index != -1) { 955 rect.setBounds(rects[index]); 956 Point viewPosition = tabScroller.viewport.getViewPosition(); 957 if (rect.x < viewPosition.x) { 958 rect.x -= renderer.getTabsOverlay(); 959 } else { 960 rect.x += renderer.getTabsOverlay(); 961 } 962 tabScroller.tabPanel.scrollRectToVisible(rect); 963 } 964 } 965 } 966 } 967 968 973 private class MyPropertyChangeHandler 974 extends BasicTabbedPaneUI.PropertyChangeHandler { 975 public void propertyChange(PropertyChangeEvent e) { 976 String pName = e.getPropertyName(); 977 978 if (null == pName) { 979 return; 980 } 981 982 super.propertyChange(e); 983 984 if (pName.equals("tabPlacement")) { 985 tabPlacementChanged(); 986 return; 987 } 988 if (pName.equals(Options.EMBEDDED_TABS_KEY)) { 989 embeddedTabsPropertyChanged((Boolean ) e.getNewValue()); 990 return; 991 } 992 if (pName.equals(Options.NO_CONTENT_BORDER_KEY)) { 993 noContentBorderPropertyChanged((Boolean ) e.getNewValue()); 994 return; 995 } 996 } 997 } 998 999 1003 private class TabbedPaneLayout extends BasicTabbedPaneUI.TabbedPaneLayout implements LayoutManager { 1004 1005 protected void calculateTabRects(int tabPlacement, int tabCount) { 1006 FontMetrics metrics = getFontMetrics(); 1007 Dimension size = tabPane.getSize(); 1008 Insets insets = tabPane.getInsets(); 1009 Insets theTabAreaInsets = getTabAreaInsets(tabPlacement); 1010 int fontHeight = metrics.getHeight(); 1011 int selectedIndex = tabPane.getSelectedIndex(); 1012 int theTabRunOverlay; 1013 int i, j; 1014 int x, y; 1015 int returnAt; 1016 boolean verticalTabRuns = (tabPlacement == LEFT || tabPlacement == RIGHT); 1017 boolean leftToRight = PlasticUtils.isLeftToRight(tabPane); 1018 1019 switch (tabPlacement) { 1023 case LEFT : 1024 maxTabWidth = calculateMaxTabWidth(tabPlacement); 1025 x = insets.left + theTabAreaInsets.left; 1026 y = insets.top + theTabAreaInsets.top; 1027 returnAt = size.height - (insets.bottom + theTabAreaInsets.bottom); 1028 break; 1029 case RIGHT : 1030 maxTabWidth = calculateMaxTabWidth(tabPlacement); 1031 x = size.width - insets.right - theTabAreaInsets.right - maxTabWidth; 1032 y = insets.top + theTabAreaInsets.top; 1033 returnAt = size.height - (insets.bottom + theTabAreaInsets.bottom); 1034 break; 1035 case BOTTOM : 1036 maxTabHeight = calculateMaxTabHeight(tabPlacement); 1037 x = insets.left + theTabAreaInsets.left; 1038 y = size.height - insets.bottom - theTabAreaInsets.bottom - maxTabHeight; 1039 returnAt = size.width - (insets.right + theTabAreaInsets.right); 1040 break; 1041 case TOP : 1042 default : 1043 maxTabHeight = calculateMaxTabHeight(tabPlacement); 1044 x = insets.left + theTabAreaInsets.left; 1045 y = insets.top + theTabAreaInsets.top; 1046 returnAt = size.width - (insets.right + theTabAreaInsets.right); 1047 break; 1048 } 1049 1050 theTabRunOverlay = getTabRunOverlay(tabPlacement); 1051 1052 runCount = 0; 1053 selectedRun = -1; 1054 int tabInRun = -1; 1059 int runReturnAt = returnAt; 1062 1063 if (tabCount == 0) { 1064 return; 1065 } 1066 1067 Rectangle rect; 1069 for (i = 0; i < tabCount; i++) { 1070 rect = rects[i]; 1071 tabInRun++; 1072 1073 if (!verticalTabRuns) { 1074 if (i > 0) { 1076 rect.x = rects[i - 1].x + rects[i - 1].width; 1077 } else { 1078 tabRuns[0] = 0; 1079 runCount = 1; 1080 maxTabWidth = 0; 1081 rect.x = x; 1082 } 1084 rect.width = calculateTabWidth(tabPlacement, i, metrics); 1085 maxTabWidth = Math.max(maxTabWidth, rect.width); 1086 1087 if (tabInRun != 0 && rect.x + rect.width > runReturnAt) { 1094 if (runCount > tabRuns.length - 1) { 1095 expandTabRunsArray(); 1096 } 1097 tabInRun = 0; 1099 tabRuns[runCount] = i; 1100 runCount++; 1101 rect.x = x; 1102 runReturnAt = runReturnAt - 2 * getTabRunIndent(tabPlacement, runCount); 1103 } 1104 rect.y = y; 1106 rect.height = maxTabHeight ; 1107 1108 } else { 1109 if (i > 0) { 1111 rect.y = rects[i - 1].y + rects[i - 1].height; 1112 } else { 1113 tabRuns[0] = 0; 1114 runCount = 1; 1115 maxTabHeight = 0; 1116 rect.y = y; 1117 } 1119 rect.height = calculateTabHeight(tabPlacement, i, fontHeight); 1120 maxTabHeight = Math.max(maxTabHeight, rect.height); 1121 1122 if (tabInRun != 0 && rect.y + rect.height > runReturnAt) { 1127 if (runCount > tabRuns.length - 1) { 1128 expandTabRunsArray(); 1129 } 1130 tabRuns[runCount] = i; 1131 runCount++; 1132 rect.y = y; 1133 tabInRun = 0; 1134 runReturnAt -= 2 * getTabRunIndent(tabPlacement, runCount); 1135 } 1136 rect.x = x; 1138 rect.width = maxTabWidth ; 1139 1140 } 1141 if (i == selectedIndex) { 1142 selectedRun = runCount - 1; 1143 } 1144 } 1145 1146 if (runCount > 1) { 1147 1153 if (shouldRotateTabRuns(tabPlacement)) { 1155 rotateTabRuns(tabPlacement, selectedRun); 1156 } 1157 } 1158 1159 for (i = runCount - 1; i >= 0; i--) { 1162 int start = tabRuns[i]; 1163 int next = tabRuns[i == (runCount - 1) ? 0 : i + 1]; 1164 int end = (next != 0 ? next - 1 : tabCount - 1); 1165 int indent = getTabRunIndent(tabPlacement, i); 1166 if (!verticalTabRuns) { 1167 for (j = start; j <= end; j++) { 1168 rect = rects[j]; 1169 rect.y = y; 1170 rect.x += indent; 1171 } 1174 if (shouldPadTabRun(tabPlacement, i)) { 1175 padTabRun(tabPlacement, start, end, returnAt - 2 * indent); 1176 } 1177 if (tabPlacement == BOTTOM) { 1178 y -= (maxTabHeight - theTabRunOverlay); 1179 } else { 1180 y += (maxTabHeight - theTabRunOverlay); 1181 } 1182 } else { 1183 for (j = start; j <= end; j++) { 1184 rect = rects[j]; 1185 rect.x = x; 1186 rect.y += indent; 1187 } 1188 if (shouldPadTabRun(tabPlacement, i)) { 1189 padTabRun(tabPlacement, start, end, returnAt - 2 * indent); 1190 } 1191 if (tabPlacement == RIGHT) { 1192 x -= (maxTabWidth - theTabRunOverlay); 1193 } else { 1194 x += (maxTabWidth - theTabRunOverlay); 1195 } 1196 } 1197 } 1198 1199 padSelectedTab(tabPlacement, selectedIndex); 1201 1202 if (!leftToRight && !verticalTabRuns) { 1205 int rightMargin = size.width - (insets.right + theTabAreaInsets.right); 1206 for (i = 0; i < tabCount; i++) { 1207 rects[i].x = rightMargin - rects[i].x - rects[i].width 1208 + renderer.getTabsOverlay(); 1209 } 1210 } 1211 } 1212 } 1213 1214 1215 private boolean requestFocusForVisibleComponent() { 1216 Component visibleComponent = getVisibleComponent(); 1217 if (visibleComponent.isFocusable()) { 1218 visibleComponent.requestFocus(); 1219 return true; 1220 } else if (visibleComponent instanceof JComponent ) { 1221 if (((JComponent ) visibleComponent).requestDefaultFocus()) { 1222 return true; 1223 } 1224 } 1225 return false; 1226 } 1227 1228 private static class ScrollTabsForwardAction extends AbstractAction { 1229 1230 public void actionPerformed(ActionEvent e) { 1231 JTabbedPane pane = null; 1232 Object src = e.getSource(); 1233 if (src instanceof JTabbedPane ) { 1234 pane = (JTabbedPane ) src; 1235 } else if (src instanceof PlasticArrowButton) { 1236 pane = (JTabbedPane ) ((PlasticArrowButton) src).getParent(); 1237 } else { 1238 return; } 1240 PlasticTabbedPaneUI ui = (PlasticTabbedPaneUI) pane.getUI(); 1241 1242 if (ui.scrollableTabLayoutEnabled()) { 1243 ui.tabScroller.scrollForward(pane.getTabPlacement()); 1244 } 1245 } 1246 } 1247 1248 private static class ScrollTabsBackwardAction extends AbstractAction { 1249 1250 public void actionPerformed(ActionEvent e) { 1251 JTabbedPane pane = null; 1252 Object src = e.getSource(); 1253 if (src instanceof JTabbedPane ) { 1254 pane = (JTabbedPane ) src; 1255 } else if (src instanceof PlasticArrowButton) { 1256 pane = (JTabbedPane ) ((PlasticArrowButton) src).getParent(); 1257 } else { 1258 return; } 1260 PlasticTabbedPaneUI ui = (PlasticTabbedPaneUI) pane.getUI(); 1261 1262 if (ui.scrollableTabLayoutEnabled()) { 1263 ui.tabScroller.scrollBackward(pane.getTabPlacement()); 1264 } 1265 } 1266 } 1267 1268 private class TabbedPaneScrollLayout extends TabbedPaneLayout { 1269 1270 protected int preferredTabAreaHeight(int tabPlacement, int width) { 1271 return calculateMaxTabHeight(tabPlacement); 1272 } 1273 1274 protected int preferredTabAreaWidth(int tabPlacement, int height) { 1275 return calculateMaxTabWidth(tabPlacement); 1276 } 1277 1278 public void layoutContainer(Container parent) { 1279 int tabPlacement = tabPane.getTabPlacement(); 1280 int tabCount = tabPane.getTabCount(); 1281 Insets insets = tabPane.getInsets(); 1282 int selectedIndex = tabPane.getSelectedIndex(); 1283 Component visibleComponent = getVisibleComponent(); 1284 1285 calculateLayoutInfo(); 1286 1287 if (selectedIndex < 0) { 1288 if (visibleComponent != null) { 1289 setVisibleComponent(null); 1291 } 1292 } else { 1293 Component selectedComponent = tabPane.getComponentAt(selectedIndex); 1294 boolean shouldChangeFocus = false; 1295 1296 if (selectedComponent != null) { 1304 if (selectedComponent != visibleComponent && 1305 visibleComponent != null) { 1306 if (SwingUtilities.findFocusOwner(visibleComponent) != null) { 1307 shouldChangeFocus = true; 1308 } 1309 } 1310 setVisibleComponent(selectedComponent); 1311 } 1312 int tx, ty, tw, th; int cx, cy, cw, ch; Insets contentInsets = getContentBorderInsets(tabPlacement); 1315 Rectangle bounds = tabPane.getBounds(); 1316 int numChildren = tabPane.getComponentCount(); 1317 1318 if (numChildren > 0) { 1319 switch (tabPlacement) { 1320 case LEFT: 1321 tw = calculateTabAreaWidth(tabPlacement, runCount, 1323 maxTabWidth); 1324 th = bounds.height - insets.top - insets.bottom; 1325 tx = insets.left; 1326 ty = insets.top; 1327 1328 cx = tx + tw + contentInsets.left; 1330 cy = ty + contentInsets.top; 1331 cw = bounds.width - insets.left - insets.right - tw 1332 - contentInsets.left - contentInsets.right; 1333 ch = bounds.height - insets.top - insets.bottom 1334 - contentInsets.top - contentInsets.bottom; 1335 break; 1336 case RIGHT: 1337 tw = calculateTabAreaWidth(tabPlacement, runCount, 1339 maxTabWidth); 1340 th = bounds.height - insets.top - insets.bottom; 1341 tx = bounds.width - insets.right - tw; 1342 ty = insets.top; 1343 1344 cx = insets.left + contentInsets.left; 1346 cy = insets.top + contentInsets.top; 1347 cw = bounds.width - insets.left - insets.right - tw 1348 - contentInsets.left - contentInsets.right; 1349 ch = bounds.height - insets.top - insets.bottom 1350 - contentInsets.top - contentInsets.bottom; 1351 break; 1352 case BOTTOM: 1353 tw = bounds.width - insets.left - insets.right; 1355 th = calculateTabAreaHeight(tabPlacement, runCount, 1356 maxTabHeight); 1357 tx = insets.left; 1358 ty = bounds.height - insets.bottom - th; 1359 1360 cx = insets.left + contentInsets.left; 1362 cy = insets.top + contentInsets.top; 1363 cw = bounds.width - insets.left - insets.right 1364 - contentInsets.left - contentInsets.right; 1365 ch = bounds.height - insets.top - insets.bottom - th 1366 - contentInsets.top - contentInsets.bottom; 1367 break; 1368 case TOP: 1369 default: 1370 tw = bounds.width - insets.left - insets.right; 1372 th = calculateTabAreaHeight(tabPlacement, runCount, 1373 maxTabHeight); 1374 tx = insets.left; 1375 ty = insets.top; 1376 1377 cx = tx + contentInsets.left; 1379 cy = ty + th + contentInsets.top; 1380 cw = bounds.width - insets.left - insets.right 1381 - contentInsets.left - contentInsets.right; 1382 ch = bounds.height - insets.top - insets.bottom - th 1383 - contentInsets.top - contentInsets.bottom; 1384 } 1385 1386 for (int i=0; i < numChildren; i++) { 1387 Component child = tabPane.getComponent(i); 1388 1389 if (tabScroller != null && child == tabScroller.viewport) { 1390 JViewport viewport = (JViewport )child; 1391 Rectangle viewRect = viewport.getViewRect(); 1392 int vw = tw; 1393 int vh = th; 1394 Dimension butSize = tabScroller.scrollForwardButton.getPreferredSize(); 1395 switch (tabPlacement) { 1396 case LEFT: 1397 case RIGHT: 1398 int totalTabHeight = rects[tabCount - 1].y 1399 + rects[tabCount - 1].height; 1400 if (totalTabHeight > th) { 1401 vh = (th > 2 * butSize.height) ? th - 2 1403 * butSize.height : 0; 1404 if (totalTabHeight - viewRect.y <= vh) { 1405 vh = totalTabHeight - viewRect.y; 1410 } 1411 } 1412 break; 1413 case BOTTOM: 1414 case TOP: 1415 default: 1416 int totalTabWidth = rects[tabCount - 1].x 1417 + rects[tabCount - 1].width + renderer.getTabsOverlay(); 1418 if (totalTabWidth > tw) { 1419 vw = (tw > 2 * butSize.width) ? tw - 2 1421 * butSize.width : 0; 1422 if (totalTabWidth - viewRect.x <= vw) { 1423 vw = totalTabWidth - viewRect.x; 1428 } 1429 } 1430 } 1431 child.setBounds(tx, ty, vw, vh); 1432 1433 } else if (tabScroller != null && 1434 (child == tabScroller.scrollForwardButton || 1435 child == tabScroller.scrollBackwardButton)) { 1436 Component scrollbutton = child; 1437 Dimension bsize = scrollbutton.getPreferredSize(); 1438 int bx = 0; 1439 int by = 0; 1440 int bw = bsize.width; 1441 int bh = bsize.height; 1442 boolean visible = false; 1443 1444 switch (tabPlacement) { 1445 case LEFT: 1446 case RIGHT: 1447 int totalTabHeight = rects[tabCount - 1].y 1448 + rects[tabCount - 1].height; 1449 if (totalTabHeight > th) { 1450 visible = true; 1451 bx = (tabPlacement == LEFT ? tx + tw 1452 - bsize.width : tx); 1453 by = (child == tabScroller.scrollForwardButton) ? bounds.height 1454 - insets.bottom - bsize.height 1455 : bounds.height - insets.bottom - 2 1456 * bsize.height; 1457 } 1458 break; 1459 1460 case BOTTOM: 1461 case TOP: 1462 default: 1463 int totalTabWidth = rects[tabCount - 1].x 1464 + rects[tabCount - 1].width; 1465 1466 if (totalTabWidth > tw) { 1467 visible = true; 1468 bx = (child == tabScroller.scrollForwardButton) ? bounds.width 1469 - insets.left - bsize.width 1470 : bounds.width - insets.left - 2 1471 * bsize.width; 1472 by = (tabPlacement == TOP ? ty + th 1473 - bsize.height : ty); 1474 } 1475 } 1476 child.setVisible(visible); 1477 if (visible) { 1478 child.setBounds(bx, by, bw, bh); 1479 } 1480 1481 } else { 1482 child.setBounds(cx, cy, cw, ch); 1484 } 1485 } 1486 if (shouldChangeFocus) { 1487 if (!requestFocusForVisibleComponent()) { 1488 tabPane.requestFocus(); 1489 } 1490 } 1491 } 1492 } 1493 } 1494 1495 protected void calculateTabRects(int tabPlacement, int tabCount) { 1496 FontMetrics metrics = getFontMetrics(); 1497 Dimension size = tabPane.getSize(); 1498 Insets insets = tabPane.getInsets(); 1499 Insets tabAreaInsets = getTabAreaInsets(tabPlacement); 1500 int fontHeight = metrics.getHeight(); 1501 int selectedIndex = tabPane.getSelectedIndex(); 1502 int i, j; 1503 boolean verticalTabRuns = (tabPlacement == LEFT || tabPlacement == RIGHT); 1504 boolean leftToRight = PlasticUtils.isLeftToRight(tabPane); 1505 int x = tabAreaInsets.left; 1506 int y = tabAreaInsets.top; 1507 int totalWidth = 0; 1508 int totalHeight = 0; 1509 1510 switch(tabPlacement) { 1514 case LEFT: 1515 case RIGHT: 1516 maxTabWidth = calculateMaxTabWidth(tabPlacement); 1517 break; 1518 case BOTTOM: 1519 case TOP: 1520 default: 1521 maxTabHeight = calculateMaxTabHeight(tabPlacement); 1522 } 1523 1524 runCount = 0; 1525 selectedRun = -1; 1526 1527 if (tabCount == 0) { 1528 return; 1529 } 1530 1531 selectedRun = 0; 1532 runCount = 1; 1533 1534 Rectangle rect; 1536 for (i = 0; i < tabCount; i++) { 1537 rect = rects[i]; 1538 1539 if (!verticalTabRuns) { 1540 if (i > 0) { 1542 rect.x = rects[i-1].x + rects[i-1].width; 1543 } else { 1544 tabRuns[0] = 0; 1545 maxTabWidth = 0; 1546 totalHeight += maxTabHeight; 1547 rect.x = x; 1548 } 1549 rect.width = calculateTabWidth(tabPlacement, i, metrics); 1550 totalWidth = rect.x + rect.width + renderer.getTabsOverlay(); 1551 maxTabWidth = Math.max(maxTabWidth, rect.width); 1552 1553 rect.y = y; 1554 rect.height = maxTabHeight; 1555 1556 } else { 1557 if (i > 0) { 1559 rect.y = rects[i-1].y + rects[i-1].height; 1560 } else { 1561 tabRuns[0] = 0; 1562 maxTabHeight = 0; 1563 totalWidth = maxTabWidth; 1564 rect.y = y; 1565 } 1566 rect.height = calculateTabHeight(tabPlacement, i, fontHeight); 1567 totalHeight = rect.y + rect.height; 1568 maxTabHeight = Math.max(maxTabHeight, rect.height); 1569 1570 rect.x = x; 1571 rect.width = maxTabWidth; 1572 1573 } 1574 } 1575 1576 padSelectedTab(tabPlacement, selectedIndex); 1578 1579 if (!leftToRight && !verticalTabRuns) { 1582 int rightMargin = size.width 1583 - (insets.right + tabAreaInsets.right); 1584 for (i = 0; i < tabCount; i++) { 1585 rects[i].x = rightMargin - rects[i].x - rects[i].width; 1586 } 1587 } 1588 tabScroller.tabPanel.setPreferredSize(new Dimension (totalWidth, totalHeight)); 1589 } 1590 } 1591 1592 private class ScrollableTabSupport implements ActionListener , 1593 ChangeListener { 1594 1595 public ScrollableTabViewport viewport; 1596 public ScrollableTabPanel tabPanel; 1597 public JButton scrollForwardButton; 1598 public JButton scrollBackwardButton; 1599 public int leadingTabIndex; 1600 private Point tabViewPosition = new Point (0, 0); 1601 1602 ScrollableTabSupport(int tabPlacement) { 1603 viewport = new ScrollableTabViewport(); 1604 tabPanel = new ScrollableTabPanel(); 1605 viewport.setView(tabPanel); 1606 viewport.addChangeListener(this); 1607 createButtons(); 1608 } 1609 1610 1613 void createButtons() { 1614 if (scrollForwardButton != null) { 1615 tabPane.remove(scrollForwardButton); 1616 scrollForwardButton.removeActionListener(this); 1617 tabPane.remove(scrollBackwardButton); 1618 scrollBackwardButton.removeActionListener(this); 1619 } 1620 int tabPlacement = tabPane.getTabPlacement(); 1621 int width = UIManager.getInt("ScrollBar.width"); 1622 if (tabPlacement == TOP || tabPlacement == BOTTOM) { 1623 scrollForwardButton = new ArrowButton(EAST, width); 1624 scrollBackwardButton = new ArrowButton(WEST, width); 1625 } else { scrollForwardButton = new ArrowButton(SOUTH, width); 1627 scrollBackwardButton = new ArrowButton(NORTH, width); 1628 } 1629 scrollForwardButton.addActionListener(this); 1630 scrollBackwardButton.addActionListener(this); 1631 tabPane.add(scrollForwardButton); 1632 tabPane.add(scrollBackwardButton); 1633 } 1634 1635 public void scrollForward(int tabPlacement) { 1636 Dimension viewSize = viewport.getViewSize(); 1637 Rectangle viewRect = viewport.getViewRect(); 1638 1639 if (tabPlacement == TOP || tabPlacement == BOTTOM) { 1640 if (viewRect.width >= viewSize.width - viewRect.x) { 1641 return; } 1643 } else { if (viewRect.height >= viewSize.height - viewRect.y) { 1645 return; 1646 } 1647 } 1648 setLeadingTabIndex(tabPlacement, leadingTabIndex + 1); 1649 } 1650 1651 public void scrollBackward(int tabPlacement) { 1652 if (leadingTabIndex == 0) { 1653 return; } 1655 setLeadingTabIndex(tabPlacement, leadingTabIndex - 1); 1656 } 1657 1658 public void setLeadingTabIndex(int tabPlacement, int index) { 1659 leadingTabIndex = index; 1660 Dimension viewSize = viewport.getViewSize(); 1661 Rectangle viewRect = viewport.getViewRect(); 1662 1663 switch (tabPlacement) { 1664 case TOP: 1665 case BOTTOM: 1666 tabViewPosition.x = leadingTabIndex == 0 ? 0 1667 : rects[leadingTabIndex].x - renderer.getTabsOverlay(); 1668 1669 if ((viewSize.width - tabViewPosition.x) < viewRect.width) { 1670 Dimension extentSize = new Dimension (viewSize.width 1674 - tabViewPosition.x, viewRect.height); 1675 viewport.setExtentSize(extentSize); 1676 } 1677 break; 1678 case LEFT: 1679 case RIGHT: 1680 tabViewPosition.y = leadingTabIndex == 0 ? 0 1681 : rects[leadingTabIndex].y; 1682 1683 if ((viewSize.height - tabViewPosition.y) < viewRect.height) { 1684 Dimension extentSize = new Dimension (viewRect.width, 1688 viewSize.height - tabViewPosition.y); 1689 viewport.setExtentSize(extentSize); 1690 } 1691 } 1692 viewport.setViewPosition(tabViewPosition); 1693 } 1694 1695 public void stateChanged(ChangeEvent e) { 1696 JViewport viewport = (JViewport ) e.getSource(); 1697 int tabPlacement = tabPane.getTabPlacement(); 1698 int tabCount = tabPane.getTabCount(); 1699 Rectangle vpRect = viewport.getBounds(); 1700 Dimension viewSize = viewport.getViewSize(); 1701 Rectangle viewRect = viewport.getViewRect(); 1702 1703 leadingTabIndex = getClosestTab(viewRect.x, viewRect.y); 1704 1705 if (leadingTabIndex + 1 < tabCount) { 1707 switch (tabPlacement) { 1708 case TOP: 1709 case BOTTOM: 1710 if (rects[leadingTabIndex].x < viewRect.x) { 1711 leadingTabIndex++; 1712 } 1713 break; 1714 case LEFT: 1715 case RIGHT: 1716 if (rects[leadingTabIndex].y < viewRect.y) { 1717 leadingTabIndex++; 1718 } 1719 break; 1720 } 1721 } 1722 Insets contentInsets = getContentBorderInsets(tabPlacement); 1723 switch (tabPlacement) { 1724 case LEFT: 1725 tabPane.repaint(vpRect.x + vpRect.width, vpRect.y, 1726 contentInsets.left, vpRect.height); 1727 scrollBackwardButton.setEnabled(viewRect.y > 0 1728 && leadingTabIndex > 0); 1729 scrollForwardButton.setEnabled(leadingTabIndex < tabCount - 1 1730 && viewSize.height - viewRect.y > viewRect.height); 1731 break; 1732 case RIGHT: 1733 tabPane.repaint(vpRect.x - contentInsets.right, vpRect.y, 1734 contentInsets.right, vpRect.height); 1735 scrollBackwardButton.setEnabled(viewRect.y > 0 1736 && leadingTabIndex > 0); 1737 scrollForwardButton.setEnabled(leadingTabIndex < tabCount - 1 1738 && viewSize.height - viewRect.y > viewRect.height); 1739 break; 1740 case BOTTOM: 1741 tabPane.repaint(vpRect.x, vpRect.y - contentInsets.bottom, 1742 vpRect.width, contentInsets.bottom); 1743 scrollBackwardButton.setEnabled(viewRect.x > 0 1744 && leadingTabIndex > 0); 1745 scrollForwardButton.setEnabled(leadingTabIndex < tabCount - 1 1746 && viewSize.width - viewRect.x > viewRect.width); 1747 break; 1748 case TOP: 1749 default: 1750 tabPane.repaint(vpRect.x, vpRect.y + vpRect.height, 1751 vpRect.width, contentInsets.top); 1752 scrollBackwardButton.setEnabled(viewRect.x > 0 1753 && leadingTabIndex > 0); 1754 scrollForwardButton.setEnabled(leadingTabIndex < tabCount - 1 1755 && viewSize.width - viewRect.x > viewRect.width); 1756 } 1757 } 1758 1759 1762 public void actionPerformed(ActionEvent e) { 1763 ActionMap map = tabPane.getActionMap(); 1764 1765 if (map != null) { 1766 String actionKey; 1767 1768 if (e.getSource() == scrollForwardButton) { 1769 actionKey = "scrollTabsForwardAction"; 1770 } else { 1771 actionKey = "scrollTabsBackwardAction"; 1772 } 1773 Action action = map.get(actionKey); 1774 1775 if (action != null && action.isEnabled()) { 1776 action.actionPerformed(new ActionEvent (tabPane, 1777 ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e 1778 .getModifiers())); 1779 } 1780 } 1781 } 1782 1783 } 1784 1785 private class ScrollableTabViewport extends JViewport implements UIResource { 1786 1787 public ScrollableTabViewport() { 1788 super(); 1789 setName("TabbedPane.scrollableViewport"); 1790 setScrollMode(SIMPLE_SCROLL_MODE); 1791 setOpaque(tabPane.isOpaque()); 1792 Color bgColor = UIManager.getColor("TabbedPane.tabAreaBackground"); 1793 if (bgColor == null) { 1794 bgColor = tabPane.getBackground(); 1795 } 1796 setBackground(bgColor); 1797 } 1798 } 1799 1800 private class ScrollableTabPanel extends JPanel implements UIResource { 1801 1802 public ScrollableTabPanel() { 1803 super(null); 1804 setOpaque(tabPane.isOpaque()); 1805 Color bgColor = UIManager.getColor("TabbedPane.tabAreaBackground"); 1806 if (bgColor == null) { 1807 bgColor = tabPane.getBackground(); 1808 } 1809 setBackground(bgColor); 1810 } 1811 1812 public void paintComponent(Graphics g) { 1813 super.paintComponent(g); 1814 PlasticTabbedPaneUI.this.paintTabArea(g, tabPane.getTabPlacement(), 1815 tabPane.getSelectedIndex()); 1816 1817 } 1818 } 1819 1820 private static class ArrowButton extends JButton implements UIResource { 1821 1822 private final int buttonWidth; 1823 private final int direction; 1824 private boolean mouseIsOver; 1825 1826 ArrowButton(int direction, int buttonWidth) { 1827 this.direction = direction; 1828 this.buttonWidth = buttonWidth; 1829 setRequestFocusEnabled(false); 1830 } 1831 1832 protected void processMouseEvent(MouseEvent e) { 1833 super.processMouseEvent(e); 1834 switch (e.getID()) { 1835 case MouseEvent.MOUSE_ENTERED: 1836 mouseIsOver = true; 1837 revalidate(); 1838 repaint(); 1839 break; 1840 case MouseEvent.MOUSE_EXITED: 1841 mouseIsOver = false; 1842 revalidate(); 1843 repaint(); 1844 break; 1845 } 1846 } 1847 1848 protected void paintBorder(Graphics g) { 1849 if (mouseIsOver && isEnabled()) { 1850 super.paintBorder(g); 1851 } 1852 } 1853 1854 protected void paintComponent(Graphics g) { 1855 if (mouseIsOver) { 1856 super.paintComponent(g); 1857 } else { 1858 g.setColor(getBackground()); 1859 g.fillRect(0, 0, getWidth(), getHeight()); 1860 } 1861 paintArrow(g); 1862 } 1863 1864 private void paintArrow(Graphics g) { 1865 Color oldColor = g.getColor(); 1866 1867 boolean isEnabled = isEnabled(); 1868 g.setColor(isEnabled ? PlasticLookAndFeel.getControlInfo() 1869 : PlasticLookAndFeel.getControlDisabled()); 1870 1871 int arrowWidth, arrowHeight; 1872 switch (direction) { 1873 case NORTH: 1874 case SOUTH: 1875 arrowWidth = 9; 1876 arrowHeight = 5; 1877 break; 1878 case WEST: 1879 case EAST: 1880 default: 1881 arrowWidth = 5; 1882 arrowHeight = 9; 1883 break; 1884 } 1885 int x = (getWidth() - arrowWidth ) / 2; 1886 int y = (getHeight() - arrowHeight) / 2; 1887 g.translate(x, y); 1888 1889 boolean paintShadow = !mouseIsOver || !isEnabled; 1890 Color shadow = isEnabled ? PlasticLookAndFeel.getControlShadow() 1891 : UIManager.getColor("ScrollBar.highlight"); 1892 1893 switch (direction) { 1894 case NORTH: 1895 g.fillRect(0, 4, 9, 1); 1896 g.fillRect(1, 3, 7, 1); 1897 g.fillRect(2, 2, 5, 1); 1898 g.fillRect(3, 1, 3, 1); 1899 g.fillRect(4, 0, 1, 1); 1900 if (paintShadow) { 1901 g.setColor(shadow); 1902 g.fillRect(1, 5, 9, 1); 1903 } 1904 break; 1905 case SOUTH: 1906 g.fillRect(0, 0, 9, 1); 1907 g.fillRect(1, 1, 7, 1); 1908 g.fillRect(2, 2, 5, 1); 1909 g.fillRect(3, 3, 3, 1); 1910 g.fillRect(4, 4, 1, 1); 1911 if (paintShadow) { 1912 g.setColor(shadow); 1913 g.drawLine(5, 4, 8, 1); 1914 g.drawLine(5, 5, 9, 1); 1915 } 1916 break; 1917 case WEST: 1918 g.fillRect(0, 4, 1, 1); 1919 g.fillRect(1, 3, 1, 3); 1920 g.fillRect(2, 2, 1, 5); 1921 g.fillRect(3, 1, 1, 7); 1922 g.fillRect(4, 0, 1, 9); 1923 if (paintShadow) { 1924 g.setColor(shadow); 1925 g.fillRect(5, 1, 1, 9); 1926 } 1927 break; 1928 case EAST: 1929 g.fillRect(0, 0, 1, 9); 1930 g.fillRect(1, 1, 1, 7); 1931 g.fillRect(2, 2, 1, 5); 1932 g.fillRect(3, 3, 1, 3); 1933 g.fillRect(4, 4, 1, 1); 1934 if (paintShadow) { 1935 g.setColor(shadow); 1936 g.drawLine(1, 8, 4, 5); 1937 g.drawLine(1, 9, 5, 5); 1938 } 1939 break; 1940 } 1941 1942 g.translate(-x, -y); 1943 g.setColor(oldColor); 1944 } 1945 1946 public Dimension getPreferredSize() { 1947 return new Dimension (buttonWidth, buttonWidth); 1948 } 1949 1950 public Dimension getMinimumSize() { 1951 return getPreferredSize(); 1952 } 1953 1954 public Dimension getMaximumSize() { 1955 return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE); 1956 } 1957 } 1958 1959 1963 private static abstract class AbstractRenderer { 1964 1965 protected static final Insets EMPTY_INSETS = new Insets (0, 0, 0, 0); 1966 protected static final Insets NORTH_INSETS = new Insets (1, 0, 0, 0); 1967 protected static final Insets WEST_INSETS = new Insets (0, 1, 0, 0); 1968 protected static final Insets SOUTH_INSETS = new Insets (0, 0, 1, 0); 1969 protected static final Insets EAST_INSETS = new Insets (0, 0, 0, 1); 1970 1971 protected final JTabbedPane tabPane; 1972 protected final int tabPlacement; 1973 protected Color shadowColor; 1974 protected Color darkShadow; 1975 protected Color selectColor; 1976 protected Color selectLight; 1977 protected Color selectHighlight; 1978 protected Color lightHighlight; 1979 protected Color focus; 1980 1981 private AbstractRenderer(JTabbedPane tabPane) { 1982 initColors(); 1983 this.tabPane = tabPane; 1984 this.tabPlacement = tabPane.getTabPlacement(); 1985 } 1986 1987 private static AbstractRenderer createRenderer(JTabbedPane tabPane) { 1988 switch (tabPane.getTabPlacement()) { 1989 case SwingConstants.TOP : 1990 return new TopRenderer(tabPane); 1991 case SwingConstants.BOTTOM : 1992 return new BottomRenderer(tabPane); 1993 case SwingConstants.LEFT : 1994 return new LeftRenderer(tabPane); 1995 case SwingConstants.RIGHT : 1996 return new RightRenderer(tabPane); 1997 default : 1998 return new TopRenderer(tabPane); 1999 } 2000 } 2001 2002 private static AbstractRenderer createEmbeddedRenderer(JTabbedPane tabPane) { 2003 switch (tabPane.getTabPlacement()) { 2004 case SwingConstants.TOP : 2005 return new TopEmbeddedRenderer(tabPane); 2006 case SwingConstants.BOTTOM : 2007 return new BottomEmbeddedRenderer(tabPane); 2008 case SwingConstants.LEFT : 2009 return new LeftEmbeddedRenderer(tabPane); 2010 case SwingConstants.RIGHT : 2011 return new RightEmbeddedRenderer(tabPane); 2012 default : 2013 return new TopEmbeddedRenderer(tabPane); 2014 } 2015 } 2016 2017 private void initColors() { 2018 shadowColor = UIManager.getColor("TabbedPane.shadow"); 2019 darkShadow = UIManager.getColor("TabbedPane.darkShadow"); 2020 selectColor = UIManager.getColor("TabbedPane.selected"); 2021 focus = UIManager.getColor("TabbedPane.focus"); 2022 selectHighlight = UIManager.getColor("TabbedPane.selectHighlight"); 2023 lightHighlight = UIManager.getColor("TabbedPane.highlight"); 2024 selectLight = 2025 new Color ( 2026 (2 * selectColor.getRed() + selectHighlight.getRed()) / 3, 2027 (2 * selectColor.getGreen() + selectHighlight.getGreen()) / 3, 2028 (2 * selectColor.getBlue() + selectHighlight.getBlue()) / 3); 2029 } 2030 2031 protected boolean isFirstDisplayedTab(int tabIndex, int position, int paneBorder) { 2032 return tabIndex == 0; 2033 } 2035 2036 protected Insets getTabAreaInsets(Insets defaultInsets) { 2037 return defaultInsets; 2038 } 2039 2040 protected Insets getContentBorderInsets(Insets defaultInsets) { 2041 return defaultInsets; 2042 } 2043 2044 2047 protected int getTabLabelShiftX(int tabIndex, boolean isSelected) { 2048 return 0; 2049 } 2050 2051 2054 protected int getTabLabelShiftY(int tabIndex, boolean isSelected) { 2055 return 0; 2056 } 2057 2058 2061 protected int getTabRunOverlay(int tabRunOverlay) { 2062 return tabRunOverlay; 2063 } 2064 2065 2069 protected boolean shouldPadTabRun(int run, boolean aPriori) { 2070 return aPriori; 2071 } 2072 2073 2078 protected int getTabRunIndent(int run) { 2079 return 0; 2080 } 2081 2082 2085 abstract protected Insets getTabInsets(int tabIndex, Insets tabInsets); 2086 2087 2090 abstract protected void paintFocusIndicator( 2091 Graphics g, 2092 Rectangle [] rects, 2093 int tabIndex, 2094 Rectangle iconRect, 2095 Rectangle textRect, 2096 boolean isSelected); 2097 2098 2102 abstract protected void paintTabBackground(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected); 2103 2104 2107 abstract protected void paintTabBorder(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected); 2108 2109 2113 protected Insets getSelectedTabPadInsets() { 2114 return EMPTY_INSETS; 2115 } 2116 2117 2122 protected void paintContentBorderTopEdge( 2123 Graphics g, 2124 int x, 2125 int y, 2126 int w, 2127 int h, 2128 boolean drawBroken, 2129 Rectangle selRect, 2130 boolean isContentBorderPainted) { 2131 if (isContentBorderPainted) { 2132 g.setColor(selectHighlight); 2133 g.fillRect(x, y, w - 1, 1); 2134 } 2135 } 2136 2137 2142 protected void paintContentBorderBottomEdge( 2143 Graphics g, 2144 int x, 2145 int y, 2146 int w, 2147 int h, 2148 boolean drawBroken, 2149 Rectangle selRect, 2150 boolean isContentBorderPainted) { 2151 if (isContentBorderPainted) { 2152 g.setColor(darkShadow); 2153 g.fillRect(x, y + h - 1, w - 1, 1); 2154 } 2155 } 2156 2157 2162 protected void paintContentBorderLeftEdge( 2163 Graphics g, 2164 int x, 2165 int y, 2166 int w, 2167 int h, 2168 boolean drawBroken, 2169 Rectangle selRect, 2170 boolean isContentBorderPainted) { 2171 if (isContentBorderPainted) { 2172 g.setColor(selectHighlight); 2173 g.fillRect(x, y, 1, h - 1); 2174 } 2175 } 2176 2177 2182 protected void paintContentBorderRightEdge( 2183 Graphics g, 2184 int x, 2185 int y, 2186 int w, 2187 int h, 2188 boolean drawBroken, 2189 Rectangle selRect, 2190 boolean isContentBorderPainted) { 2191 if (isContentBorderPainted) { 2192 g.setColor(darkShadow); 2193 g.fillRect(x + w - 1, y, 1, h); 2194 } 2195 } 2196 2197 2200 protected int getTabsOverlay() { 2201 return 0; 2202 } 2203 } 2204 2205 2209 private static class BottomEmbeddedRenderer extends AbstractRenderer { 2210 2211 private BottomEmbeddedRenderer(JTabbedPane tabPane) { 2212 super(tabPane); 2213 } 2214 2215 protected Insets getTabAreaInsets(Insets insets) { 2216 return EMPTY_INSETS; 2217 } 2218 2219 protected Insets getContentBorderInsets(Insets defaultInsets) { 2220 return SOUTH_INSETS; 2221 } 2222 2223 protected Insets getSelectedTabPadInsets() { 2224 return EMPTY_INSETS; 2225 } 2226 2227 protected Insets getTabInsets(int tabIndex, Insets tabInsets) { 2228 return new Insets (tabInsets.top, tabInsets.left, tabInsets.bottom, tabInsets.right); 2229 } 2230 2233 protected void paintFocusIndicator( 2234 Graphics g, 2235 Rectangle [] rects, 2236 int tabIndex, 2237 Rectangle iconRect, 2238 Rectangle textRect, 2239 boolean isSelected) { 2240 } 2242 2243 protected void paintTabBackground(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2244 2245 g.setColor(selectColor); 2246 g.fillRect(x, y, w + 1, h); 2247 } 2248 2249 protected void paintTabBorder(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2250 2251 int bottom = h; 2252 int right = w + 1; 2253 2254 g.translate(x, y); 2255 if (isFirstDisplayedTab(tabIndex, x, tabPane.getBounds().x)) { 2256 if (isSelected) { 2257 g.setColor(shadowColor); 2259 g.fillRect(right, 0, 1, bottom - 1); 2260 g.fillRect(right - 1, bottom - 1, 1, 1); 2261 g.setColor(selectHighlight); 2267 g.fillRect(0, 0, 1, bottom); 2268 g.fillRect(right - 1, 0, 1, bottom - 1); 2269 g.fillRect(1, bottom - 1, right - 2, 1); 2270 } else { 2271 } 2273 } else { 2274 if (isSelected) { 2275 g.setColor(shadowColor); 2277 g.fillRect(0, 0, 1, bottom - 1); 2278 g.fillRect(1, bottom - 1, 1, 1); 2279 g.fillRect(right, 0, 1, bottom - 1); 2280 g.fillRect(right - 1, bottom - 1, 1, 1); 2281 g.setColor(selectHighlight); 2284 g.fillRect(1, 0, 1, bottom - 1); 2285 g.fillRect(right - 1, 0, 1, bottom - 1); 2286 g.fillRect(2, bottom - 1, right - 3, 1); 2287 } else { 2288 g.setColor(shadowColor); 2289 g.fillRect(1, h / 2, 1, h - (h / 2)); 2290 } 2291 } 2292 g.translate(-x, -y); 2293 } 2294 2295 protected void paintContentBorderBottomEdge( 2296 Graphics g, 2297 int x, 2298 int y, 2299 int w, 2300 int h, 2301 boolean drawBroken, 2302 Rectangle selRect, 2303 boolean isContentBorderPainted) { 2304 2305 g.setColor(shadowColor); 2306 g.fillRect(x, y + h - 1, w, 1); 2307 } 2308 2309 } 2310 2311 2315 private static final class BottomRenderer extends AbstractRenderer { 2316 2317 private BottomRenderer(JTabbedPane tabPane) { 2318 super(tabPane); 2319 } 2320 2321 protected Insets getTabAreaInsets(Insets defaultInsets) { 2322 return new Insets (defaultInsets.top, defaultInsets.left + 5, defaultInsets.bottom, defaultInsets.right); 2323 } 2324 2325 protected int getTabLabelShiftY(int tabIndex, boolean isSelected) { 2326 return isSelected? 0 : -1; 2327 } 2328 2329 protected int getTabRunOverlay(int tabRunOverlay) { 2330 return tabRunOverlay - 2; 2331 } 2332 2333 protected int getTabRunIndent(int run) { 2334 return 6 * run; 2335 } 2336 2337 protected Insets getSelectedTabPadInsets() { 2338 return SOUTH_INSETS; 2339 } 2340 2341 protected Insets getTabInsets(int tabIndex, Insets tabInsets) { 2342 return new Insets (tabInsets.top, tabInsets.left - 2, tabInsets.bottom, tabInsets.right - 2); 2343 } 2344 2345 protected void paintFocusIndicator( 2346 Graphics g, 2347 Rectangle [] rects, 2348 int tabIndex, 2349 Rectangle iconRect, 2350 Rectangle textRect, 2351 boolean isSelected) { 2352 2353 if (!tabPane.hasFocus() || !isSelected) 2354 return; 2355 Rectangle tabRect = rects[tabIndex]; 2356 int top = tabRect.y; 2357 int left = tabRect.x + 6; 2358 int height = tabRect.height - 3; 2359 int width = tabRect.width - 12; 2360 g.setColor(focus); 2361 g.drawRect(left, top, width, height); 2362 } 2363 2364 protected void paintTabBackground(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2365 2366 g.setColor(selectColor); 2367 g.fillRect(x, y, w, h); 2368 } 2369 2370 protected void paintTabBorder(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2371 2372 int bottom = h - 1; 2373 int right = w + 4; 2374 2375 g.translate(x - 3, y); 2376 2377 g.setColor(selectHighlight); 2379 2380 g.fillRect(0, 0, 1, 2); 2382 g.drawLine(0, 2, 4, bottom - 4); 2383 g.fillRect(5, bottom - 3, 1, 2); 2384 g.fillRect(6, bottom - 1, 1, 1); 2385 2386 g.fillRect(7, bottom, 1, 1); 2388 g.setColor(darkShadow); 2389 g.fillRect(8, bottom, right - 13, 1); 2390 2391 g.drawLine(right + 1, 0, right - 3, bottom - 4); 2393 g.fillRect(right - 4, bottom - 3, 1, 2); 2394 g.fillRect(right - 5, bottom - 1, 1, 1); 2395 2396 g.translate(-x + 3, -y); 2397 } 2398 2399 protected void paintContentBorderBottomEdge( 2400 Graphics g, 2401 int x, 2402 int y, 2403 int w, 2404 int h, 2405 boolean drawBroken, 2406 Rectangle selRect, 2407 boolean isContentBorderPainted) { 2408 int bottom = y + h - 1; 2409 int right = x + w - 1; 2410 g.translate(x, bottom); 2411 if (drawBroken && selRect.x >= x && selRect.x <= x + w) { 2412 g.setColor(darkShadow); 2414 g.fillRect(0, 0, selRect.x - x - 2, 1); 2415 if (selRect.x + selRect.width < x + w - 2) { 2416 g.setColor(darkShadow); 2417 g.fillRect(selRect.x + selRect.width + 2 - x, 0, right - selRect.x - selRect.width - 2, 1); 2418 } 2419 } else { 2420 g.setColor(darkShadow); 2421 g.fillRect(0, 0, w - 1, 1); 2422 } 2423 g.translate(-x, -bottom); 2424 } 2425 2426 protected int getTabsOverlay() { 2427 return 4; 2428 } 2429 2430 } 2431 2432 2435 private static class LeftEmbeddedRenderer extends AbstractRenderer { 2436 2437 private LeftEmbeddedRenderer(JTabbedPane tabPane) { 2438 super(tabPane); 2439 } 2440 2441 protected Insets getTabAreaInsets(Insets insets) { 2442 return EMPTY_INSETS; 2443 } 2444 2445 protected Insets getContentBorderInsets(Insets defaultInsets) { 2446 return WEST_INSETS; 2447 } 2448 2449 protected int getTabRunOverlay(int tabRunOverlay) { 2450 return 0; 2451 } 2452 2453 protected boolean shouldPadTabRun(int run, boolean aPriori) { 2454 return false; 2455 } 2456 2457 protected Insets getTabInsets(int tabIndex, Insets tabInsets) { 2458 return new Insets (tabInsets.top, tabInsets.left, tabInsets.bottom, tabInsets.right); 2459 } 2460 2461 protected Insets getSelectedTabPadInsets() { 2462 return EMPTY_INSETS; 2463 } 2464 2465 2468 protected void paintFocusIndicator( 2469 Graphics g, 2470 Rectangle [] rects, 2471 int tabIndex, 2472 Rectangle iconRect, 2473 Rectangle textRect, 2474 boolean isSelected) { 2475 } 2477 2478 protected void paintTabBackground(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2479 g.setColor(selectColor); 2480 g.fillRect(x, y, w, h); 2481 } 2482 2483 protected void paintTabBorder(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2484 2485 int bottom = h; 2486 int right = w; 2487 2488 g.translate(x, y); 2489 2490 if (isFirstDisplayedTab(tabIndex, y, tabPane.getBounds().y)) { 2491 if (isSelected) { 2492 g.setColor(selectHighlight); 2494 g.fillRect(0, 0, right, 1); 2495 g.fillRect(0, 0, 1, bottom - 1); 2496 g.fillRect(1, bottom - 1, right - 1, 1); 2497 g.setColor(shadowColor); 2498 g.fillRect(0, bottom - 1, 1, 1); 2499 g.fillRect(1, bottom, right - 1, 1); 2500 } else { 2503 } 2505 } else { 2506 if (isSelected) { 2507 g.setColor(selectHighlight); 2509 g.fillRect(1, 1, right - 1, 1); 2510 g.fillRect(0, 2, 1, bottom - 2); 2511 g.fillRect(1, bottom - 1, right - 1, 1); 2512 g.setColor(shadowColor); 2513 g.fillRect(1, 0, right - 1, 1); 2514 g.fillRect(0, 1, 1, 1); 2515 g.fillRect(0, bottom - 1, 1, 1); 2516 g.fillRect(1, bottom, right - 1, 1); 2517 } else { 2520 g.setColor(shadowColor); 2521 g.fillRect(0, 0, right / 3, 1); 2522 } 2523 } 2524 2525 g.translate(-x, -y); 2526 } 2527 2528 protected void paintContentBorderLeftEdge( 2529 Graphics g, 2530 int x, 2531 int y, 2532 int w, 2533 int h, 2534 boolean drawBroken, 2535 Rectangle selRect, 2536 boolean isContentBorderPainted) { 2537 g.setColor(shadowColor); 2538 g.fillRect(x, y, 1, h); 2539 } 2540 } 2541 2542 2545 private static class LeftRenderer extends AbstractRenderer { 2546 2547 private LeftRenderer(JTabbedPane tabPane) { 2548 super(tabPane); 2549 } 2550 2551 protected Insets getTabAreaInsets(Insets defaultInsets) { 2552 return new Insets (defaultInsets.top + 4, defaultInsets.left, defaultInsets.bottom, defaultInsets.right); 2553 } 2554 2555 protected int getTabLabelShiftX(int tabIndex, boolean isSelected) { 2556 return 1; 2557 } 2558 2559 protected int getTabRunOverlay(int tabRunOverlay) { 2560 return 1; 2561 } 2562 2563 protected boolean shouldPadTabRun(int run, boolean aPriori) { 2564 return false; 2565 } 2566 2567 protected Insets getTabInsets(int tabIndex, Insets tabInsets) { 2568 return new Insets (tabInsets.top, tabInsets.left - 5, tabInsets.bottom + 1, tabInsets.right - 5); 2569 } 2570 2571 protected Insets getSelectedTabPadInsets() { 2572 return WEST_INSETS; 2573 } 2574 2575 protected void paintFocusIndicator( 2576 Graphics g, 2577 Rectangle [] rects, 2578 int tabIndex, 2579 Rectangle iconRect, 2580 Rectangle textRect, 2581 boolean isSelected) { 2582 2583 if (!tabPane.hasFocus() || !isSelected) 2584 return; 2585 Rectangle tabRect = rects[tabIndex]; 2586 int top = tabRect.y + 2; 2587 int left = tabRect.x + 3; 2588 int height = tabRect.height - 5; 2589 int width = tabRect.width - 6; 2590 g.setColor(focus); 2591 g.drawRect(left, top, width, height); 2592 } 2593 2594 protected void paintTabBackground(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2595 if (!isSelected) { 2596 g.setColor(selectLight); 2597 g.fillRect(x + 1, y + 1, w - 1, h - 2); 2598 } else { 2599 g.setColor(selectColor); 2600 g.fillRect(x + 1, y + 1, w - 3, h - 2); 2601 } 2602 } 2603 2604 protected void paintTabBorder(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2605 2606 int bottom = h - 1; 2607 int left = 0; 2608 g.translate(x, y); 2609 2610 g.setColor(selectHighlight); 2612 g.fillRect(left + 2, 0, w - 2 - left, 1); 2614 2615 g.fillRect(left + 1, 1, 1, 1); 2617 g.fillRect(left, 2, 1, bottom - 3); 2618 g.setColor(darkShadow); 2619 g.fillRect(left + 1, bottom - 1, 1, 1); 2620 2621 g.fillRect(left + 2, bottom, w - 2 - left, 1); 2623 2624 g.translate(-x, -y); 2625 } 2626 2627 protected void paintContentBorderLeftEdge( 2628 Graphics g, 2629 int x, 2630 int y, 2631 int w, 2632 int h, 2633 boolean drawBroken, 2634 Rectangle selRect, 2635 boolean isContentBorderPainted) { 2636 g.setColor(selectHighlight); 2637 if (drawBroken && selRect.y >= y && selRect.y <= y + h) { 2638 g.fillRect(x, y, 1, selRect.y + 1 - y); 2640 if (selRect.y + selRect.height < y + h - 2) { 2641 g.fillRect(x, selRect.y + selRect.height - 1, 1, y + h - selRect.y - selRect.height); 2642 } 2643 } else { 2644 g.fillRect(x, y, 1, h - 1); 2645 } 2646 } 2647 2648 } 2649 2650 2653 private static class RightEmbeddedRenderer extends AbstractRenderer { 2654 2655 private RightEmbeddedRenderer(JTabbedPane tabPane) { 2656 super(tabPane); 2657 } 2658 2659 protected Insets getTabAreaInsets(Insets insets) { 2660 return EMPTY_INSETS; 2661 } 2662 2663 protected Insets getContentBorderInsets(Insets defaultInsets) { 2664 return EAST_INSETS; 2665 } 2666 2667 protected int getTabRunIndent(int run) { 2668 return 4 * run; 2669 } 2670 2671 protected int getTabRunOverlay(int tabRunOverlay) { 2672 return 0; 2673 } 2674 2675 protected boolean shouldPadTabRun(int run, boolean aPriori) { 2676 return false; 2677 } 2678 2679 protected Insets getTabInsets(int tabIndex, Insets tabInsets) { 2680 return new Insets (tabInsets.top, tabInsets.left, tabInsets.bottom, tabInsets.right); 2681 } 2682 2683 protected Insets getSelectedTabPadInsets() { 2684 return EMPTY_INSETS; 2685 } 2686 2687 2690 protected void paintFocusIndicator( 2691 Graphics g, 2692 Rectangle [] rects, 2693 int tabIndex, 2694 Rectangle iconRect, 2695 Rectangle textRect, 2696 boolean isSelected) { 2697 } 2699 2700 protected void paintTabBackground(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2701 2702 g.setColor(selectColor); 2703 g.fillRect(x, y, w, h); 2704 } 2705 2706 protected void paintTabBorder(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2707 2708 int bottom = h; 2709 int right = w - 1; 2710 2711 g.translate(x + 1, y); 2712 2713 if (isFirstDisplayedTab(tabIndex, y, tabPane.getBounds().y)) { 2714 if (isSelected) { 2715 g.setColor(shadowColor); 2717 g.fillRect(right - 1, bottom - 1, 1, 1); 2721 g.fillRect(0, bottom, right - 1, 1); 2722 g.setColor(selectHighlight); 2723 g.fillRect(0, 0, right - 1, 1); 2724 g.fillRect(right - 1, 0, 1, bottom - 1); 2725 g.fillRect(0, bottom - 1, right - 1, 1); 2726 } 2727 } else { 2728 if (isSelected) { 2729 g.setColor(shadowColor); 2731 g.fillRect(0, -1, right - 1, 1); 2732 g.fillRect(right - 1, 0, 1, 1); 2733 g.fillRect(right - 1, bottom - 1, 1, 1); 2736 g.fillRect(0, bottom, right - 1, 1); 2737 g.setColor(selectHighlight); 2738 g.fillRect(0, 0, right - 1, 1); 2739 g.fillRect(right - 1, 1, 1, bottom - 2); 2740 g.fillRect(0, bottom - 1, right - 1, 1); 2741 } else { 2742 g.setColor(shadowColor); 2744 g.fillRect(2 * right / 3, 0, right / 3, 1); 2745 } 2746 } 2747 g.translate(-x - 1, -y); 2748 } 2749 2750 protected void paintContentBorderRightEdge( 2751 Graphics g, 2752 int x, 2753 int y, 2754 int w, 2755 int h, 2756 boolean drawBroken, 2757 Rectangle selRect, 2758 boolean isContentBorderPainted) { 2759 g.setColor(shadowColor); 2760 g.fillRect(x + w - 1, y, 1, h); 2761 } 2762 2763 } 2764 2765 2768 private static class RightRenderer extends AbstractRenderer { 2769 2770 private RightRenderer(JTabbedPane tabPane) { 2771 super(tabPane); 2772 } 2773 2774 protected int getTabLabelShiftX(int tabIndex, boolean isSelected) { 2775 return 1; 2776 } 2777 2778 protected int getTabRunOverlay(int tabRunOverlay) { 2779 return 1; 2780 } 2781 2782 protected boolean shouldPadTabRun(int run, boolean aPriori) { 2783 return false; 2784 } 2785 2786 protected Insets getTabInsets(int tabIndex, Insets tabInsets) { 2787 return new Insets (tabInsets.top, tabInsets.left - 5, tabInsets.bottom + 1, tabInsets.right - 5); 2788 } 2789 2790 protected Insets getSelectedTabPadInsets() { 2791 return EAST_INSETS; 2792 } 2793 2794 protected void paintFocusIndicator( 2795 Graphics g, 2796 Rectangle [] rects, 2797 int tabIndex, 2798 Rectangle iconRect, 2799 Rectangle textRect, 2800 boolean isSelected) { 2801 2802 if (!tabPane.hasFocus() || !isSelected) 2803 return; 2804 Rectangle tabRect = rects[tabIndex]; 2805 int top = tabRect.y + 2; 2806 int left = tabRect.x + 3; 2807 int height = tabRect.height - 5; 2808 int width = tabRect.width - 6; 2809 g.setColor(focus); 2810 g.drawRect(left, top, width, height); 2811 } 2812 2813 protected void paintTabBackground(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2814 if (!isSelected) { 2815 g.setColor(selectLight); 2816 g.fillRect(x, y, w, h); 2817 } else { 2818 g.setColor(selectColor); 2819 g.fillRect(x + 2, y, w - 2, h); 2820 } 2821 } 2822 2823 protected void paintTabBorder(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2824 2825 int bottom = h - 1; 2826 int right = w; 2827 2828 g.translate(x, y); 2829 2830 2832 g.setColor(selectHighlight); 2833 g.fillRect(0, 0, right - 1, 1); 2834 g.setColor(darkShadow); 2836 g.fillRect(right - 1, 1, 1, 1); 2837 g.fillRect(right, 2, 1, bottom - 3); 2838 g.fillRect(right - 1, bottom - 1, 1, 1); 2840 g.fillRect(0, bottom, right - 1, 1); 2841 2842 g.translate(-x, -y); 2843 } 2844 2845 protected void paintContentBorderRightEdge( 2846 Graphics g, 2847 int x, 2848 int y, 2849 int w, 2850 int h, 2851 boolean drawBroken, 2852 Rectangle selRect, 2853 boolean isContentBorderPainted) { 2854 g.setColor(darkShadow); 2855 if (drawBroken && selRect.y >= y && selRect.y <= y + h) { 2856 g.fillRect(x + w - 1, y, 1, selRect.y - y); 2858 if (selRect.y + selRect.height < y + h - 2) { 2859 g.fillRect(x + w - 1, selRect.y + selRect.height, 1, y + h - selRect.y - selRect.height); 2860 } 2861 } else { 2862 g.fillRect(x + w - 1, y, 1, h - 1); 2863 } 2864 } 2865 } 2866 2867 2870 private static class TopEmbeddedRenderer extends AbstractRenderer { 2871 2872 private TopEmbeddedRenderer(JTabbedPane tabPane) { 2873 super(tabPane); 2874 } 2875 2876 protected Insets getTabAreaInsets(Insets insets) { 2877 return EMPTY_INSETS; 2878 } 2879 2880 protected Insets getContentBorderInsets(Insets defaultInsets) { 2881 return NORTH_INSETS; 2882 } 2883 2884 protected Insets getTabInsets(int tabIndex, Insets tabInsets) { 2885 return new Insets (tabInsets.top, tabInsets.left + 1, tabInsets.bottom, tabInsets.right); 2886 } 2887 2888 protected Insets getSelectedTabPadInsets() { 2889 return EMPTY_INSETS; 2890 } 2891 2892 2895 protected void paintFocusIndicator( 2896 Graphics g, 2897 Rectangle [] rects, 2898 int tabIndex, 2899 Rectangle iconRect, 2900 Rectangle textRect, 2901 boolean isSelected) { 2902 } 2904 2905 protected void paintTabBackground(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2906 2907 g.setColor(selectColor); 2908 g.fillRect(x, y, w, h); 2909 } 2910 2911 protected void paintTabBorder(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 2912 2913 g.translate(x, y); 2914 2915 int right = w; 2916 int bottom = h; 2917 2918 if (isFirstDisplayedTab(tabIndex, x, tabPane.getBounds().x)) { 2919 if (isSelected) { 2920 g.setColor(selectHighlight); 2921 g.fillRect(0, 0, 1, bottom); 2923 g.fillRect(0, 0, right - 1, 1); 2925 g.fillRect(right - 1, 0, 1, bottom); 2927 g.setColor(shadowColor); 2928 g.fillRect(right - 1, 0, 1, 1); 2930 g.fillRect(right, 1, 1, bottom); 2932 } 2933 } else { 2934 if (isSelected) { 2935 g.setColor(selectHighlight); 2936 g.fillRect(1, 1, 1, bottom - 1); 2938 g.fillRect(2, 0, right - 3, 1); 2940 g.fillRect(right - 1, 1, 1, bottom - 1); 2942 g.setColor(shadowColor); 2943 g.fillRect(0, 1, 1, bottom - 1); 2945 g.fillRect(1, 0, 1, 1); 2947 g.fillRect(right - 1, 0, 1, 1); 2949 g.fillRect(right, 1, 1, bottom); 2951 } else { 2952 g.setColor(shadowColor); 2953 g.fillRect(0, 0, 1, bottom +2 - bottom / 2); 2954 } 2955 } 2956 g.translate(-x, -y); 2957 } 2958 2959 protected void paintContentBorderTopEdge( 2960 Graphics g, 2961 int x, 2962 int y, 2963 int w, 2964 int h, 2965 boolean drawBroken, 2966 Rectangle selRect, 2967 boolean isContentBorderPainted) { 2968 g.setColor(shadowColor); 2969 g.fillRect(x, y, w, 1); 2970 } 2971 2972 } 2973 2974 2977 private static class TopRenderer extends AbstractRenderer { 2978 2979 private TopRenderer(JTabbedPane tabPane) { 2980 super(tabPane); 2981 } 2982 2983 protected Insets getTabAreaInsets(Insets defaultInsets) { 2984 return new Insets (defaultInsets.top, defaultInsets.left + 4, defaultInsets.bottom, defaultInsets.right); 2985 } 2986 2987 protected int getTabLabelShiftY(int tabIndex, boolean isSelected) { 2988 return isSelected? -1 : 0; 2989 } 2990 2991 protected int getTabRunOverlay(int tabRunOverlay) { 2992 return tabRunOverlay - 2; 2993 } 2994 2995 protected int getTabRunIndent(int run) { 2996 return 6 * run; 2997 } 2998 2999 protected Insets getSelectedTabPadInsets() { 3000 return NORTH_INSETS; 3001 } 3002 3003 protected Insets getTabInsets(int tabIndex, Insets tabInsets) { 3004 return new Insets (tabInsets.top-1, tabInsets.left - 4, tabInsets.bottom, tabInsets.right - 4); 3005 } 3006 3007 protected void paintFocusIndicator( 3008 Graphics g, 3009 Rectangle [] rects, 3010 int tabIndex, 3011 Rectangle iconRect, 3012 Rectangle textRect, 3013 boolean isSelected) { 3014 3015 if (!tabPane.hasFocus() || !isSelected) 3016 return; 3017 Rectangle tabRect = rects[tabIndex]; 3018 int top = tabRect.y +1 ; 3019 int left = tabRect.x + 4; 3020 int height = tabRect.height - 3; 3021 int width = tabRect.width - 9; 3022 g.setColor(focus); 3023 g.drawRect(left, top, width, height); 3024 } 3025 3026 protected void paintTabBackground(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 3027 3028 int sel = (isSelected) ? 0 : 1; 3029 g.setColor(selectColor); 3030 g.fillRect(x, y + sel, w, h / 2); 3031 g.fillRect(x - 1, y + sel + h / 2, w + 2, h - h / 2); 3032 } 3033 3034 protected void paintTabBorder(Graphics g, int tabIndex, int x, int y, int w, int h, boolean isSelected) { 3035 3036 g.translate(x - 4, y); 3037 3038 int top = 0; 3039 int right = w + 6; 3040 3041 g.setColor(selectHighlight); 3043 3044 g.drawLine(1, h - 1, 4, top + 4); 3046 g.fillRect(5, top + 2, 1, 2); 3047 g.fillRect(6, top + 1, 1, 1); 3048 3049 g.fillRect(7, top, right - 12, 1); 3051 3052 g.setColor(darkShadow); 3054 g.drawLine(right, h - 1, right - 3, top + 4); 3055 g.fillRect(right - 4, top + 2, 1, 2); 3056 g.fillRect(right - 5, top + 1, 1, 1); 3057 3058 g.translate(-x + 4, -y); 3059 } 3060 3061 protected void paintContentBorderTopEdge( 3062 Graphics g, 3063 int x, 3064 int y, 3065 int w, 3066 int h, 3067 boolean drawBroken, 3068 Rectangle selRect, 3069 boolean isContentBorderPainted) { 3070 int right = x + w - 1; 3071 int top = y; 3072 g.setColor(selectHighlight); 3073 3074 if (drawBroken && selRect.x >= x && selRect.x <= x + w) { 3075 g.fillRect(x, top, selRect.x - 2 - x, 1); 3077 if (selRect.x + selRect.width < x + w - 2) { 3078 g.fillRect(selRect.x + selRect.width + 2, top, right - 2 - selRect.x - selRect.width, 1); 3079 } else { 3080 g.fillRect(x + w - 2, top, 1, 1); 3081 } 3082 } else { 3083 g.fillRect(x, top, w - 1, 1); 3084 } 3085 } 3086 3087 protected int getTabsOverlay() { 3088 return 6; 3089 } 3090 } 3091 3092} | Popular Tags |