| 1 7 8 package javax.swing.plaf.metal; 9 10 import javax.swing.*; 11 import javax.swing.event.*; 12 import java.awt.*; 13 import java.awt.event.*; 14 import javax.swing.plaf.*; 15 import java.io.Serializable ; 16 import javax.swing.plaf.basic.BasicTabbedPaneUI ; 17 18 33 34 public class MetalTabbedPaneUI extends BasicTabbedPaneUI { 35 36 protected int minTabWidth = 40; 37 private Color unselectedBackground; 40 protected Color tabAreaBackground; 41 protected Color selectColor; 42 protected Color selectHighlight; 43 private boolean tabsOpaque = true; 44 45 private boolean ocean; 48 private Color oceanSelectedBorderColor; 50 51 public static ComponentUI createUI( JComponent x ) { 52 return new MetalTabbedPaneUI (); 53 } 54 55 protected LayoutManager createLayoutManager() { 56 if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { 57 return super.createLayoutManager(); 58 } 59 return new TabbedPaneLayout(); 60 } 61 62 protected void installDefaults() { 63 super.installDefaults(); 64 65 tabAreaBackground = UIManager.getColor("TabbedPane.tabAreaBackground"); 66 selectColor = UIManager.getColor("TabbedPane.selected"); 67 selectHighlight = UIManager.getColor("TabbedPane.selectHighlight"); 68 tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque"); 69 unselectedBackground = UIManager.getColor( 70 "TabbedPane.unselectedBackground"); 71 ocean = MetalLookAndFeel.usingOcean(); 72 if (ocean) { 73 oceanSelectedBorderColor = UIManager.getColor( 74 "TabbedPane.borderHightlightColor"); 75 } 76 } 77 78 79 protected void paintTabBorder( Graphics g, int tabPlacement, 80 int tabIndex, int x, int y, int w, int h, 81 boolean isSelected) { 82 int bottom = y + (h-1); 83 int right = x + (w-1); 84 85 switch ( tabPlacement ) { 86 case LEFT: 87 paintLeftTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected); 88 break; 89 case BOTTOM: 90 paintBottomTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected); 91 break; 92 case RIGHT: 93 paintRightTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected); 94 break; 95 case TOP: 96 default: 97 paintTopTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected); 98 } 99 } 100 101 102 protected void paintTopTabBorder( int tabIndex, Graphics g, 103 int x, int y, int w, int h, 104 int btm, int rght, 105 boolean isSelected ) { 106 int currentRun = getRunForTab( tabPane.getTabCount(), tabIndex ); 107 int lastIndex = lastTabInRun( tabPane.getTabCount(), currentRun ); 108 int firstIndex = tabRuns[ currentRun ]; 109 boolean leftToRight = MetalUtils.isLeftToRight(tabPane); 110 int selectedIndex = tabPane.getSelectedIndex(); 111 int bottom = h - 1; 112 int right = w - 1; 113 114 118 if (shouldFillGap( currentRun, tabIndex, x, y ) ) { 119 g.translate( x, y ); 120 121 if ( leftToRight ) { 122 g.setColor( getColorForGap( currentRun, x, y + 1 ) ); 123 g.fillRect( 1, 0, 5, 3 ); 124 g.fillRect( 1, 3, 2, 2 ); 125 } else { 126 g.setColor( getColorForGap( currentRun, x + w - 1, y + 1 ) ); 127 g.fillRect( right - 5, 0, 5, 3 ); 128 g.fillRect( right - 2, 3, 2, 2 ); 129 } 130 131 g.translate( -x, -y ); 132 } 133 134 g.translate( x, y ); 135 136 140 if (ocean && isSelected) { 141 g.setColor(oceanSelectedBorderColor); 142 } 143 else { 144 g.setColor( darkShadow ); 145 } 146 147 if ( leftToRight ) { 148 149 g.drawLine( 1, 5, 6, 0 ); 151 152 g.drawLine( 6, 0, right, 0 ); 154 155 if ( tabIndex==lastIndex ) { 157 g.drawLine( right, 1, right, bottom ); 159 } 160 161 if (ocean && tabIndex - 1 == selectedIndex && 162 currentRun == getRunForTab( 163 tabPane.getTabCount(), selectedIndex)) { 164 g.setColor(oceanSelectedBorderColor); 165 } 166 167 if ( tabIndex != tabRuns[ runCount - 1 ] ) { 169 if (ocean && isSelected) { 171 g.drawLine(0, 6, 0, bottom); 172 g.setColor(darkShadow); 173 g.drawLine(0, 0, 0, 5); 174 } 175 else { 176 g.drawLine( 0, 0, 0, bottom ); 177 } 178 } else { 179 g.drawLine( 0, 6, 0, bottom ); 181 } 182 } else { 183 184 g.drawLine( right - 1, 5, right - 6, 0 ); 186 187 g.drawLine( right - 6, 0, 0, 0 ); 189 190 if ( tabIndex==lastIndex ) { 192 g.drawLine( 0, 1, 0, bottom ); 194 } 195 196 if (ocean && tabIndex - 1 == selectedIndex && 198 currentRun == getRunForTab( 199 tabPane.getTabCount(), selectedIndex)) { 200 g.setColor(oceanSelectedBorderColor); 201 g.drawLine(right, 0, right, bottom); 202 } 203 else if (ocean && isSelected) { 204 g.drawLine(right, 6, right, bottom); 205 if (tabIndex != 0) { 206 g.setColor(darkShadow); 207 g.drawLine(right, 0, right, 5); 208 } 209 } 210 else { 211 if ( tabIndex != tabRuns[ runCount - 1 ] ) { 212 g.drawLine( right, 0, right, bottom ); 214 } else { 215 g.drawLine( right, 6, right, bottom ); 217 } 218 } 219 } 220 221 225 g.setColor( isSelected ? selectHighlight : highlight ); 226 227 if ( leftToRight ) { 228 229 g.drawLine( 1, 6, 6, 1 ); 231 232 g.drawLine( 6, 1, right, 1 ); 234 235 g.drawLine( 1, 6, 1, bottom ); 237 238 if ( tabIndex==firstIndex && tabIndex!=tabRuns[runCount - 1] ) { 241 if (tabPane.getSelectedIndex()==tabRuns[currentRun+1]) { 243 g.setColor( selectHighlight ); 245 } 246 else { 247 g.setColor( highlight ); 249 } 250 g.drawLine( 1, 0, 1, 4 ); 251 } 252 } else { 253 254 g.drawLine( right - 1, 6, right - 6, 1 ); 256 257 g.drawLine( right - 6, 1, 1, 1 ); 259 260 if ( tabIndex==lastIndex ) { 262 g.drawLine( 1, 1, 1, bottom ); 264 } else { 265 g.drawLine( 0, 1, 0, bottom ); 266 } 267 } 268 269 g.translate( -x, -y ); 270 } 271 272 protected boolean shouldFillGap( int currentRun, int tabIndex, int x, int y ) { 273 boolean result = false; 274 275 if (!tabsOpaque) { 276 return false; 277 } 278 279 if ( currentRun == runCount - 2 ) { Rectangle lastTabBounds = getTabBounds( tabPane, tabPane.getTabCount() - 1 ); 281 Rectangle tabBounds = getTabBounds( tabPane, tabIndex ); 282 if (MetalUtils.isLeftToRight(tabPane)) { 283 int lastTabRight = lastTabBounds.x + lastTabBounds.width - 1; 284 285 if ( lastTabRight > tabBounds.x + 2 ) { 288 return true; 289 } 290 } else { 291 int lastTabLeft = lastTabBounds.x; 292 int currentTabRight = tabBounds.x + tabBounds.width - 1; 293 294 if ( lastTabLeft < currentTabRight - 2 ) { 297 return true; 298 } 299 } 300 } else { 301 result = currentRun != runCount - 1; 303 } 304 305 return result; 306 } 307 308 protected Color getColorForGap( int currentRun, int x, int y ) { 309 final int shadowWidth = 4; 310 int selectedIndex = tabPane.getSelectedIndex(); 311 int startIndex = tabRuns[ currentRun + 1 ]; 312 int endIndex = lastTabInRun( tabPane.getTabCount(), currentRun + 1 ); 313 int tabOverGap = -1; 314 for ( int i = startIndex; i <= endIndex; ++i ) { 316 Rectangle tabBounds = getTabBounds( tabPane, i ); 317 int tabLeft = tabBounds.x; 318 int tabRight = (tabBounds.x + tabBounds.width) - 1; 319 if ( MetalUtils.isLeftToRight(tabPane) ) { 321 if ( tabLeft <= x && tabRight - shadowWidth > x ) { 322 if (ocean) { 323 if (selectedIndex == i) { 324 return oceanSelectedBorderColor; 325 } 326 return getUnselectedBackgroundAt(i); 327 } 328 return selectedIndex == i ? selectColor : getUnselectedBackgroundAt( i ); 329 } 330 } 331 else { 332 if ( tabLeft + shadowWidth < x && tabRight >= x ) { 333 if (ocean) { 334 if (selectedIndex == i) { 335 return oceanSelectedBorderColor; 336 } 337 return getUnselectedBackgroundAt(i); 338 } 339 return selectedIndex == i ? selectColor : getUnselectedBackgroundAt( i ); 340 } 341 } 342 } 343 344 return tabPane.getBackground(); 345 } 346 347 protected void paintLeftTabBorder( int tabIndex, Graphics g, 348 int x, int y, int w, int h, 349 int btm, int rght, 350 boolean isSelected ) { 351 int tabCount = tabPane.getTabCount(); 352 int currentRun = getRunForTab( tabCount, tabIndex ); 353 int lastIndex = lastTabInRun( tabCount, currentRun ); 354 int firstIndex = tabRuns[ currentRun ]; 355 356 g.translate( x, y ); 357 358 int bottom = h - 1; 359 int right = w - 1; 360 361 365 if ( tabIndex != firstIndex && tabsOpaque ) { 366 g.setColor( tabPane.getSelectedIndex() == tabIndex - 1 ? 367 selectColor : 368 getUnselectedBackgroundAt( tabIndex - 1 ) ); 369 g.fillRect( 2, 0, 4, 3 ); 370 g.drawLine( 2, 3, 2, 3 ); 371 } 372 373 374 378 if (ocean) { 379 g.setColor(isSelected ? selectHighlight : 380 MetalLookAndFeel.getWhite()); 381 } 382 else { 383 g.setColor( isSelected ? selectHighlight : highlight ); 384 } 385 386 g.drawLine( 1, 6, 6, 1 ); 388 389 g.drawLine( 1, 6, 1, bottom ); 391 392 g.drawLine( 6, 1, right, 1 ); 394 395 if ( tabIndex != firstIndex ) { 396 if (ocean) { 397 g.setColor(MetalLookAndFeel.getWhite()); 398 } 399 g.drawLine( 1, 0, 1, 4 ); 400 } 401 402 406 if (ocean) { 407 if (isSelected) { 408 g.setColor(oceanSelectedBorderColor); 409 } 410 else { 411 g.setColor( darkShadow ); 412 } 413 } 414 else { 415 g.setColor( darkShadow ); 416 } 417 418 g.drawLine( 1, 5, 6, 0 ); 420 421 g.drawLine( 6, 0, right, 0 ); 423 424 if ( tabIndex == lastIndex ) { 426 g.drawLine( 0, bottom, right, bottom ); 427 } 428 429 if (ocean) { 431 if (tabPane.getSelectedIndex() == tabIndex - 1) { 432 g.drawLine(0, 5, 0, bottom); 433 g.setColor(oceanSelectedBorderColor); 434 g.drawLine(0, 0, 0, 5); 435 } 436 else if (isSelected) { 437 g.drawLine( 0, 5, 0, bottom ); 438 if (tabIndex != 0) { 439 g.setColor(darkShadow); 440 g.drawLine(0, 0, 0, 5); 441 } 442 } 443 else if ( tabIndex != firstIndex ) { 444 g.drawLine( 0, 0, 0, bottom ); 445 } else { 446 g.drawLine( 0, 6, 0, bottom ); 447 } 448 } 449 else { if ( tabIndex != firstIndex ) { 451 g.drawLine( 0, 0, 0, bottom ); 452 } else { 453 g.drawLine( 0, 6, 0, bottom ); 454 } 455 } 456 457 g.translate( -x, -y ); 458 } 459 460 461 protected void paintBottomTabBorder( int tabIndex, Graphics g, 462 int x, int y, int w, int h, 463 int btm, int rght, 464 boolean isSelected ) { 465 int tabCount = tabPane.getTabCount(); 466 int currentRun = getRunForTab( tabCount, tabIndex ); 467 int lastIndex = lastTabInRun( tabCount, currentRun ); 468 int firstIndex = tabRuns[ currentRun ]; 469 boolean leftToRight = MetalUtils.isLeftToRight(tabPane); 470 471 int bottom = h - 1; 472 int right = w - 1; 473 474 478 if ( shouldFillGap( currentRun, tabIndex, x, y ) ) { 479 g.translate( x, y ); 480 481 if ( leftToRight ) { 482 g.setColor( getColorForGap( currentRun, x, y ) ); 483 g.fillRect( 1, bottom - 4, 3, 5 ); 484 g.fillRect( 4, bottom - 1, 2, 2 ); 485 } else { 486 g.setColor( getColorForGap( currentRun, x + w - 1, y ) ); 487 g.fillRect( right - 3, bottom - 3, 3, 4 ); 488 g.fillRect( right - 5, bottom - 1, 2, 2 ); 489 g.drawLine( right - 1, bottom - 4, right - 1, bottom - 4 ); 490 } 491 492 g.translate( -x, -y ); 493 } 494 495 g.translate( x, y ); 496 497 498 502 if (ocean && isSelected) { 503 g.setColor(oceanSelectedBorderColor); 504 } 505 else { 506 g.setColor( darkShadow ); 507 } 508 509 if ( leftToRight ) { 510 511 g.drawLine( 1, bottom - 5, 6, bottom ); 513 514 g.drawLine( 6, bottom, right, bottom ); 516 517 if ( tabIndex == lastIndex ) { 519 g.drawLine( right, 0, right, bottom ); 520 } 521 522 if (ocean && isSelected) { 524 g.drawLine(0, 0, 0, bottom - 5); 525 if ((currentRun == 0 && tabIndex != 0) || 526 (currentRun > 0 && tabIndex != tabRuns[currentRun - 1])) { 527 g.setColor(darkShadow); 528 g.drawLine(0, bottom - 5, 0, bottom); 529 } 530 } 531 else { 532 if (ocean && tabIndex == tabPane.getSelectedIndex() + 1) { 533 g.setColor(oceanSelectedBorderColor); 534 } 535 if ( tabIndex != tabRuns[ runCount - 1 ] ) { 536 g.drawLine( 0, 0, 0, bottom ); 537 } else { 538 g.drawLine( 0, 0, 0, bottom - 6 ); 539 } 540 } 541 } else { 542 543 g.drawLine( right - 1, bottom - 5, right - 6, bottom ); 545 546 g.drawLine( right - 6, bottom, 0, bottom ); 548 549 if ( tabIndex==lastIndex ) { 551 g.drawLine( 0, 0, 0, bottom ); 553 } 554 555 if (ocean && tabIndex == tabPane.getSelectedIndex() + 1) { 557 g.setColor(oceanSelectedBorderColor); 558 g.drawLine(right, 0, right, bottom); 559 } 560 else if (ocean && isSelected) { 561 g.drawLine(right, 0, right, bottom - 6); 562 if (tabIndex != firstIndex) { 563 g.setColor(darkShadow); 564 g.drawLine(right, bottom - 5, right, bottom); 565 } 566 } 567 else if ( tabIndex != tabRuns[ runCount - 1 ] ) { 568 g.drawLine( right, 0, right, bottom ); 570 } else { 571 g.drawLine( right, 0, right, bottom - 6 ); 573 } 574 } 575 576 580 g.setColor( isSelected ? selectHighlight : highlight ); 581 582 if ( leftToRight ) { 583 584 g.drawLine( 1, bottom - 6, 6, bottom - 1 ); 586 587 g.drawLine( 1, 0, 1, bottom - 6 ); 589 590 if ( tabIndex==firstIndex && tabIndex!=tabRuns[runCount - 1] ) { 593 if (tabPane.getSelectedIndex()==tabRuns[currentRun+1]) { 595 g.setColor( selectHighlight ); 597 } 598 else { 599 g.setColor( highlight ); 601 } 602 g.drawLine( 1, bottom - 4, 1, bottom ); 603 } 604 } else { 605 606 if ( tabIndex==lastIndex ) { 608 g.drawLine( 1, 0, 1, bottom - 1 ); 610 } else { 611 g.drawLine( 0, 0, 0, bottom - 1 ); 612 } 613 } 614 615 g.translate( -x, -y ); 616 } 617 618 protected void paintRightTabBorder( int tabIndex, Graphics g, 619 int x, int y, int w, int h, 620 int btm, int rght, 621 boolean isSelected ) { 622 int tabCount = tabPane.getTabCount(); 623 int currentRun = getRunForTab( tabCount, tabIndex ); 624 int lastIndex = lastTabInRun( tabCount, currentRun ); 625 int firstIndex = tabRuns[ currentRun ]; 626 627 g.translate( x, y ); 628 629 int bottom = h - 1; 630 int right = w - 1; 631 632 636 if ( tabIndex != firstIndex && tabsOpaque ) { 637 g.setColor( tabPane.getSelectedIndex() == tabIndex - 1 ? 638 tabAreaBackground : 639 getUnselectedBackgroundAt( tabIndex - 1 ) ); 640 g.fillRect( right - 5, 0, 5, 3 ); 641 g.fillRect( right - 2, 3, 2, 2 ); 642 } 643 644 645 649 g.setColor( isSelected ? selectHighlight : highlight ); 650 651 g.drawLine( right - 6, 1, right - 1, 6 ); 653 654 g.drawLine( 0, 1, right - 6, 1 ); 656 657 if ( !isSelected ) { 659 g.drawLine( 0, 1, 0, bottom ); 660 } 661 662 663 667 if (ocean && isSelected) { 668 g.setColor(oceanSelectedBorderColor); 669 } 670 else { 671 g.setColor( darkShadow ); 672 } 673 674 if ( tabIndex == lastIndex ) { 676 g.drawLine( 0, bottom, right, bottom ); 677 } 678 679 if (ocean && tabPane.getSelectedIndex() == tabIndex - 1) { 681 g.setColor(oceanSelectedBorderColor); 682 } 683 g.drawLine( right - 6, 0, right, 6 ); 684 685 g.drawLine( 0, 0, right - 6, 0 ); 687 688 if (ocean && isSelected) { 690 g.drawLine(right, 6, right, bottom); 691 if (tabIndex != firstIndex) { 692 g.setColor(darkShadow); 693 g.drawLine(right, 0, right, 5); 694 } 695 } 696 else if (ocean && tabPane.getSelectedIndex() == tabIndex - 1) { 697 g.setColor(oceanSelectedBorderColor); 698 g.drawLine(right, 0, right, 6); 699 g.setColor(darkShadow); 700 g.drawLine(right, 6, right, bottom); 701 } 702 else if ( tabIndex != firstIndex ) { 703 g.drawLine( right, 0, right, bottom ); 704 } else { 705 g.drawLine( right, 6, right, bottom ); 706 } 707 708 g.translate( -x, -y ); 709 } 710 711 public void update( Graphics g, JComponent c ) { 712 if ( c.isOpaque() ) { 713 g.setColor( tabAreaBackground ); 714 g.fillRect( 0, 0, c.getWidth(),c.getHeight() ); 715 } 716 paint( g, c ); 717 } 718 719 protected void paintTabBackground( Graphics g, int tabPlacement, 720 int tabIndex, int x, int y, int w, int h, boolean isSelected ) { 721 int slantWidth = h / 2; 722 if ( isSelected ) { 723 g.setColor( selectColor ); 724 } else { 725 g.setColor( getUnselectedBackgroundAt( tabIndex ) ); 726 } 727 728 if (MetalUtils.isLeftToRight(tabPane)) { 729 switch ( tabPlacement ) { 730 case LEFT: 731 g.fillRect( x + 5, y + 1, w - 5, h - 1); 732 g.fillRect( x + 2, y + 4, 3, h - 4 ); 733 break; 734 case BOTTOM: 735 g.fillRect( x + 2, y, w - 2, h - 4 ); 736 g.fillRect( x + 5, y + (h - 1) - 3, w - 5, 3 ); 737 break; 738 case RIGHT: 739 g.fillRect( x, y + 1, w - 4, h - 1); 740 g.fillRect( x + (w - 1) - 3, y + 5, 3, h - 5 ); 741 break; 742 case TOP: 743 default: 744 g.fillRect( x + 4, y + 2, (w - 1) - 3, (h - 1) - 1 ); 745 g.fillRect( x + 2, y + 5, 2, h - 5 ); 746 } 747 } else { 748 switch ( tabPlacement ) { 749 case LEFT: 750 g.fillRect( x + 5, y + 1, w - 5, h - 1); 751 g.fillRect( x + 2, y + 4, 3, h - 4 ); 752 break; 753 case BOTTOM: 754 g.fillRect( x, y, w - 5, h - 1 ); 755 g.fillRect( x + (w - 1) - 4, y, 4, h - 5); 756 g.fillRect( x + (w - 1) - 4, y + (h - 1) - 4, 2, 2); 757 break; 758 case RIGHT: 759 g.fillRect( x + 1, y + 1, w - 5, h - 1); 760 g.fillRect( x + (w - 1) - 3, y + 5, 3, h - 5 ); 761 break; 762 case TOP: 763 default: 764 g.fillRect( x, y + 2, (w - 1) - 3, (h - 1) - 1 ); 765 g.fillRect( x + (w - 1) - 3, y + 4, 3, h - 4 ); 766 } 767 } 768 } 769 770 773 protected int getTabLabelShiftX( int tabPlacement, int tabIndex, boolean isSelected ) { 774 return 0; 775 } 776 777 778 781 protected int getTabLabelShiftY( int tabPlacement, int tabIndex, boolean isSelected ) { 782 return 0; 783 } 784 785 786 public void paint( Graphics g, JComponent c ) { 787 int tabPlacement = tabPane.getTabPlacement(); 788 789 Insets insets = c.getInsets(); Dimension size = c.getSize(); 790 791 if ( tabPane.isOpaque() ) { 793 Color bg = UIManager.getColor("TabbedPane.tabAreaBackground"); 794 if (bg != null) { 795 g.setColor(bg); 796 } 797 else { 798 g.setColor( c.getBackground() ); 799 } 800 switch ( tabPlacement ) { 801 case LEFT: 802 g.fillRect( insets.left, insets.top, 803 calculateTabAreaWidth( tabPlacement, runCount, maxTabWidth ), 804 size.height - insets.bottom - insets.top ); 805 break; 806 case BOTTOM: 807 int totalTabHeight = calculateTabAreaHeight( tabPlacement, runCount, maxTabHeight ); 808 g.fillRect( insets.left, size.height - insets.bottom - totalTabHeight, 809 size.width - insets.left - insets.right, 810 totalTabHeight ); 811 break; 812 case RIGHT: 813 int totalTabWidth = calculateTabAreaWidth( tabPlacement, runCount, maxTabWidth ); 814 g.fillRect( size.width - insets.right - totalTabWidth, 815 insets.top, totalTabWidth, 816 size.height - insets.top - insets.bottom ); 817 break; 818 case TOP: 819 default: 820 g.fillRect( insets.left, insets.top, 821 size.width - insets.right - insets.left, 822 calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight) ); 823 paintHighlightBelowTab(); 824 } 825 } 826 827 super.paint( g, c ); 828 } 829 830 protected void paintHighlightBelowTab( ) { 831 832 } 833 834 835 protected void paintFocusIndicator(Graphics g, int tabPlacement, 836 Rectangle[] rects, int tabIndex, 837 Rectangle iconRect, Rectangle textRect, 838 boolean isSelected) { 839 if ( tabPane.hasFocus() && isSelected ) { 840 Rectangle tabRect = rects[tabIndex]; 841 boolean lastInRun = isLastInRun( tabIndex ); 842 g.setColor( focus ); 843 g.translate( tabRect.x, tabRect.y ); 844 int right = tabRect.width - 1; 845 int bottom = tabRect.height - 1; 846 boolean leftToRight = MetalUtils.isLeftToRight(tabPane); 847 switch ( tabPlacement ) { 848 case RIGHT: 849 &n
|