FileDocCategorySizeDatePackage
MetalTabbedPaneUI.javaAPI DocJava SE 6 API39506Tue Jun 10 00:26:50 BST 2008javax.swing.plaf.metal

MetalTabbedPaneUI

public class MetalTabbedPaneUI extends BasicTabbedPaneUI
The Metal subclass of BasicTabbedPaneUI.

Warning: Serialized objects of this class will not be compatible with future Swing releases. The current serialization support is appropriate for short term storage or RMI between applications running the same version of Swing. As of 1.4, support for long term storage of all JavaBeansTM has been added to the java.beans package. Please see {@link java.beans.XMLEncoder}.

version
1.19 08/28/98
author
Tom Santos

Fields Summary
protected int
minTabWidth
private Color
unselectedBackground
protected Color
tabAreaBackground
protected Color
selectColor
protected Color
selectHighlight
private boolean
tabsOpaque
private boolean
ocean
private Color
oceanSelectedBorderColor
Constructors Summary
Methods Summary
protected intcalculateMaxTabHeight(int tabPlacement)

        FontMetrics metrics = getFontMetrics();
        int height = metrics.getHeight();
        boolean tallerIcons = false;

        for ( int i = 0; i < tabPane.getTabCount(); ++i ) {
            Icon icon = tabPane.getIconAt( i );
            if ( icon != null ) {
                if ( icon.getIconHeight() > height ) {
                    tallerIcons = true;
                    break;
                }
            }
        }
        return super.calculateMaxTabHeight( tabPlacement ) - 
                  (tallerIcons ? (tabInsets.top + tabInsets.bottom) : 0);
    
protected java.awt.LayoutManagercreateLayoutManager()

	if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) {
            return super.createLayoutManager(); 
	}
        return new TabbedPaneLayout();
    
public static javax.swing.plaf.ComponentUIcreateUI(javax.swing.JComponent x)


           
        return new MetalTabbedPaneUI();
    
protected intgetBaselineOffset()
{@inheritDoc}

since
1.6

        return 0;
    
protected java.awt.ColorgetColorForGap(int currentRun, int x, int y)

        final int shadowWidth = 4;
        int selectedIndex = tabPane.getSelectedIndex();
        int startIndex = tabRuns[ currentRun + 1 ];
        int endIndex = lastTabInRun( tabPane.getTabCount(), currentRun + 1 );
        int tabOverGap = -1;
        // Check each tab in the row that is 'on top' of this row
        for ( int i = startIndex; i <= endIndex; ++i ) {
            Rectangle tabBounds = getTabBounds( tabPane, i );
            int tabLeft = tabBounds.x;
            int tabRight = (tabBounds.x + tabBounds.width) - 1;
            // Check to see if this tab is over the gap
	    if ( MetalUtils.isLeftToRight(tabPane) ) {
                if ( tabLeft <= x && tabRight - shadowWidth > x ) {
                    return selectedIndex == i ? selectColor : getUnselectedBackgroundAt( i );
                }
            }
            else {
	        if ( tabLeft + shadowWidth < x && tabRight >= x ) {
                    return selectedIndex == i ? selectColor : getUnselectedBackgroundAt( i );
                }
            }
        }

        return tabPane.getBackground();
    
intgetRolloverTabIndex()
Returns the tab index of JTabbedPane the mouse is currently over

    	return getRolloverTab();
    
protected intgetTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected)
Overridden to do nothing for the Java L&F.

        return 0; 
    
protected intgetTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected)
Overridden to do nothing for the Java L&F.

        return 0; 
    
protected intgetTabRunOverlay(int tabPlacement)

        // Tab runs laid out vertically should overlap
        // at least as much as the largest slant
        if ( tabPlacement == LEFT || tabPlacement == RIGHT ) {
            int maxTabHeight = calculateMaxTabHeight(tabPlacement);
            return maxTabHeight / 2;
        }
        return 0;
    
private java.awt.ColorgetUnselectedBackgroundAt(int index)
Returns the color to use for the specified tab.

        Color color = tabPane.getBackgroundAt(index);
        if (color instanceof UIResource) {
            if (unselectedBackground != null) {
                return unselectedBackground;
            }
        }
        return color;
    
protected voidinstallDefaults()

        super.installDefaults();

        tabAreaBackground = UIManager.getColor("TabbedPane.tabAreaBackground");
        selectColor = UIManager.getColor("TabbedPane.selected");
        selectHighlight = UIManager.getColor("TabbedPane.selectHighlight");
        tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque");
        unselectedBackground = UIManager.getColor(
                                         "TabbedPane.unselectedBackground");
        ocean = MetalLookAndFeel.usingOcean();
        if (ocean) {
            oceanSelectedBorderColor = UIManager.getColor(
                         "TabbedPane.borderHightlightColor");
        }
    
private booleanisLastInRun(int tabIndex)

        int run = getRunForTab( tabPane.getTabCount(), tabIndex );
	int lastIndex = lastTabInRun( tabPane.getTabCount(), run );
	return tabIndex == lastIndex;
    
public voidpaint(java.awt.Graphics g, javax.swing.JComponent c)

        int tabPlacement = tabPane.getTabPlacement();

        Insets insets = c.getInsets(); Dimension size = c.getSize();

        // Paint the background for the tab area
        if ( tabPane.isOpaque() ) {
            Color bg = UIManager.getColor("TabbedPane.tabAreaBackground");
            if (bg != null) {
                g.setColor(bg);
            }
            else {
                g.setColor( c.getBackground() );
            }
            switch ( tabPlacement ) {
            case LEFT:
                g.fillRect( insets.left, insets.top, 
                            calculateTabAreaWidth( tabPlacement, runCount, maxTabWidth ),
                            size.height - insets.bottom - insets.top );
                break;
            case BOTTOM:
                int totalTabHeight = calculateTabAreaHeight( tabPlacement, runCount, maxTabHeight );
                g.fillRect( insets.left, size.height - insets.bottom - totalTabHeight, 
                            size.width - insets.left - insets.right,
                            totalTabHeight );
                break;
            case RIGHT:
                int totalTabWidth = calculateTabAreaWidth( tabPlacement, runCount, maxTabWidth );
                g.fillRect( size.width - insets.right - totalTabWidth,
                            insets.top, totalTabWidth, 
                            size.height - insets.top - insets.bottom );
                break;
            case TOP:
            default:
                g.fillRect( insets.left, insets.top, 
                            size.width - insets.right - insets.left, 
                            calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight) );
                paintHighlightBelowTab();
            }
        }

        super.paint( g, c );
    
protected voidpaintBottomTabBorder(int tabIndex, java.awt.Graphics g, int x, int y, int w, int h, int btm, int rght, boolean isSelected)

        int tabCount = tabPane.getTabCount();
        int currentRun = getRunForTab( tabCount, tabIndex );
        int lastIndex = lastTabInRun( tabCount, currentRun );
        int firstIndex = tabRuns[ currentRun ];
	boolean leftToRight = MetalUtils.isLeftToRight(tabPane);

        int bottom = h - 1;
        int right = w - 1;

        //
        // Paint Gap
        //

        if ( shouldFillGap( currentRun, tabIndex, x, y ) ) {
            g.translate( x, y );

	    if ( leftToRight ) {
	        g.setColor( getColorForGap( currentRun, x, y ) );
		g.fillRect( 1, bottom - 4, 3, 5 );
		g.fillRect( 4, bottom - 1, 2, 2 );
	    } else {
	        g.setColor( getColorForGap( currentRun, x + w - 1, y ) );
		g.fillRect( right - 3, bottom - 3, 3, 4 );
		g.fillRect( right - 5, bottom - 1, 2, 2 );
		g.drawLine( right - 1, bottom - 4, right - 1, bottom - 4 );
	    }

            g.translate( -x, -y );
        }

        g.translate( x, y );


        //
        // Paint Border
        //

        if (ocean && isSelected) {
            g.setColor(oceanSelectedBorderColor);
        }
        else {
            g.setColor( darkShadow );
        }

	if ( leftToRight ) {

	    // Paint slant
	    g.drawLine( 1, bottom - 5, 6, bottom );

	    // Paint bottom
	    g.drawLine( 6, bottom, right, bottom );

	    // Paint right
	    if ( tabIndex == lastIndex ) {
	        g.drawLine( right, 0, right, bottom );
	    }

	    // Paint left
            if (ocean && isSelected) {
                g.drawLine(0, 0, 0, bottom - 6);
                if ((currentRun == 0 && tabIndex != 0) ||
                    (currentRun > 0 && tabIndex != tabRuns[currentRun - 1])) {
                    g.setColor(darkShadow);
                    g.drawLine(0, bottom - 5, 0, bottom);
                }
            }
            else {
                if (ocean && tabIndex == tabPane.getSelectedIndex() + 1) {
                    g.setColor(oceanSelectedBorderColor);
                }
                if ( tabIndex != tabRuns[ runCount - 1 ] ) {
                    g.drawLine( 0, 0, 0, bottom );
                } else {
                    g.drawLine( 0, 0, 0, bottom - 6 );
                }
            }
	} else {

	    // Paint slant
	    g.drawLine( right - 1, bottom - 5, right - 6, bottom );

	    // Paint bottom
	    g.drawLine( right - 6, bottom, 0, bottom );

	    // Paint left
	    if ( tabIndex==lastIndex ) {
	        // last tab in run
	        g.drawLine( 0, 0, 0, bottom );
	    }

	    // Paint right
            if (ocean && tabIndex == tabPane.getSelectedIndex() + 1) {
                g.setColor(oceanSelectedBorderColor);
                g.drawLine(right, 0, right, bottom);
            }
            else if (ocean && isSelected) {
                g.drawLine(right, 0, right, bottom - 6);
                if (tabIndex != firstIndex) {
                    g.setColor(darkShadow);
                    g.drawLine(right, bottom - 5, right, bottom);
                }
            }
	    else if ( tabIndex != tabRuns[ runCount - 1 ] ) {
	        // not the first tab in the last run
	        g.drawLine( right, 0, right, bottom );
	    } else {
	        // the first tab in the last run
	        g.drawLine( right, 0, right, bottom - 6 );
	    }
	}

        //
        // Paint Highlight
        //

        g.setColor( isSelected ? selectHighlight : highlight );

	if ( leftToRight ) {

	    // Paint slant
	    g.drawLine( 1, bottom - 6, 6, bottom - 1 );

	    // Paint left
	    g.drawLine( 1, 0, 1, bottom - 6 );

	    // paint highlight in the gap on tab behind this one
	    // on the left end (where they all line up)
	    if ( tabIndex==firstIndex && tabIndex!=tabRuns[runCount - 1] ) {
	        //  first tab in run but not first tab in last run
	        if (tabPane.getSelectedIndex()==tabRuns[currentRun+1]) {
		    // tab in front of selected tab
		    g.setColor( selectHighlight );
		}
		else {
		    // tab in front of normal tab
		    g.setColor( highlight );
		}
		g.drawLine( 1, bottom - 4, 1, bottom );
	    }
	} else {

	    // Paint left
	    if ( tabIndex==lastIndex ) {
	        // last tab in run
	        g.drawLine( 1, 0, 1, bottom - 1 );
	    } else {
	        g.drawLine( 0, 0, 0, bottom - 1 );
	    }
	}

        g.translate( -x, -y );
    
protected voidpaintContentBorderBottomEdge(java.awt.Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h)

 
	boolean leftToRight = MetalUtils.isLeftToRight(tabPane);
        int bottom = y + h - 1;
	int right = x + w - 1;
        Rectangle selRect = selectedIndex < 0? null :
	                       getTabBounds(selectedIndex, calcRect);

        g.setColor(darkShadow);

	// Draw unbroken line if tabs are not on BOTTOM, OR
	// selected tab is not in run adjacent to content, OR
	// selected tab is not visible (SCROLL_TAB_LAYOUT)
	//
        if (tabPlacement != BOTTOM || selectedIndex < 0 ||
             (selRect.y - 1 > h) ||
	     (selRect.x < x || selRect.x > x + w)) {
            if (ocean && tabPlacement == BOTTOM) {
                g.setColor(oceanSelectedBorderColor);
            }
            g.drawLine(x, y+h-1, x+w-1, y+h-1);
        } else {
	    // Break line to show visual connection to selected tab
	    boolean lastInRun = isLastInRun(selectedIndex);

            if (ocean) {
                g.setColor(oceanSelectedBorderColor);
            }

	    if ( leftToRight || lastInRun ) {
	        g.drawLine(x, bottom, selRect.x, bottom);
	    } else {
	        g.drawLine(x, bottom, selRect.x - 1, bottom);
	    }

            if (selRect.x + selRect.width < x + w - 2) {
	        if ( leftToRight && !lastInRun ) {
		    g.drawLine(selRect.x + selRect.width, bottom,
			                           right, bottom);
		} else {
		    g.drawLine(selRect.x + selRect.width - 1, bottom,
			                               right, bottom);
		}
            } 
        }
    
protected voidpaintContentBorderLeftEdge(java.awt.Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h)

 
        Rectangle selRect = selectedIndex < 0? null :
	                       getTabBounds(selectedIndex, calcRect);
        if (ocean) {
            g.setColor(oceanSelectedBorderColor);
        }
        else {
            g.setColor(selectHighlight); 
        }

	// Draw unbroken line if tabs are not on LEFT, OR
	// selected tab is not in run adjacent to content, OR
	// selected tab is not visible (SCROLL_TAB_LAYOUT)
	//
        if (tabPlacement != LEFT || selectedIndex < 0 ||
            (selRect.x + selRect.width + 1 < x) ||
	    (selRect.y < y || selRect.y > y + h)) {
            g.drawLine(x, y + 1, x, y+h-2);
            if (ocean && tabPlacement == LEFT) {
                g.setColor(MetalLookAndFeel.getWhite());
                g.drawLine(x + 1, y, x + 1, y + h - 2);
            }
        } else {
	    // Break line to show visual connection to selected tab
            g.drawLine(x, y, x, selRect.y + 1);
            if (selRect.y + selRect.height < y + h - 2) {
	      g.drawLine(x, selRect.y + selRect.height + 1, 
			 x, y+h+2);
            } 
            if (ocean) {
                g.setColor(MetalLookAndFeel.getWhite());
                g.drawLine(x + 1, y + 1, x + 1, selRect.y + 1);
                if (selRect.y + selRect.height < y + h - 2) {
                    g.drawLine(x + 1, selRect.y + selRect.height + 1, 
                               x + 1, y+h+2);
                }
            }
        }
    
protected voidpaintContentBorderRightEdge(java.awt.Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h)

        Rectangle selRect = selectedIndex < 0? null :
	                       getTabBounds(selectedIndex, calcRect);

        g.setColor(darkShadow);
	// Draw unbroken line if tabs are not on RIGHT, OR
	// selected tab is not in run adjacent to content, OR
	// selected tab is not visible (SCROLL_TAB_LAYOUT)
	//
        if (tabPlacement != RIGHT || selectedIndex < 0 ||
             (selRect.x - 1 > w) ||
	     (selRect.y < y || selRect.y > y + h)) {
            if (ocean && tabPlacement == RIGHT) {
                g.setColor(oceanSelectedBorderColor);
            }
            g.drawLine(x+w-1, y, x+w-1, y+h-1);
        } else {
	    // Break line to show visual connection to selected tab
            if (ocean) {
                g.setColor(oceanSelectedBorderColor);
            }
            g.drawLine(x+w-1, y, x+w-1, selRect.y);

            if (selRect.y + selRect.height < y + h - 2) {
                g.drawLine(x+w-1, selRect.y + selRect.height, 
                           x+w-1, y+h-2);
            } 
        }
    
protected voidpaintContentBorderTopEdge(java.awt.Graphics g, int tabPlacement, int selectedIndex, int x, int y, int w, int h)

    
	boolean leftToRight = MetalUtils.isLeftToRight(tabPane);
	int right = x + w - 1;
        Rectangle selRect = selectedIndex < 0? null :
	                       getTabBounds(selectedIndex, calcRect);
        if (ocean) {
            g.setColor(oceanSelectedBorderColor);
        }
        else {
            g.setColor(selectHighlight);
        }

	// Draw unbroken line if tabs are not on TOP, OR
	// selected tab is not in run adjacent to content, OR
	// selected tab is not visible (SCROLL_TAB_LAYOUT)
	//
         if (tabPlacement != TOP || selectedIndex < 0 || 
            (selRect.y + selRect.height + 1 < y) ||
	    (selRect.x < x || selRect.x > x + w)) {
            g.drawLine(x, y, x+w-2, y);
            if (ocean && tabPlacement == TOP) {
                g.setColor(MetalLookAndFeel.getWhite());
                g.drawLine(x, y + 1, x+w-2, y + 1);
            }
        } else {
 	    // Break line to show visual connection to selected tab
	    boolean lastInRun = isLastInRun(selectedIndex);

	    if ( leftToRight || lastInRun ) {
	        g.drawLine(x, y, selRect.x + 1, y);
	    } else {
	        g.drawLine(x, y, selRect.x, y);
	    }

            if (selRect.x + selRect.width < right - 1) {
	        if ( leftToRight && !lastInRun ) {
		    g.drawLine(selRect.x + selRect.width, y, right - 1, y);
		} else {
		    g.drawLine(selRect.x + selRect.width - 1, y, right - 1, y);
		}
            } else {
	        g.setColor(shadow); 
                g.drawLine(x+w-2, y, x+w-2, y);
            }

            if (ocean) {
                g.setColor(MetalLookAndFeel.getWhite());

                if ( leftToRight || lastInRun ) {
                    g.drawLine(x, y + 1, selRect.x + 1, y + 1);
                } else {
                    g.drawLine(x, y + 1, selRect.x, y + 1);
                }

                if (selRect.x + selRect.width < right - 1) {
                    if ( leftToRight && !lastInRun ) {
                        g.drawLine(selRect.x + selRect.width, y + 1,
                                   right - 1, y + 1);
                    } else {
                        g.drawLine(selRect.x + selRect.width - 1, y + 1,
                                   right - 1, y + 1);
                    }
                } else {
                    g.setColor(shadow); 
                    g.drawLine(x+w-2, y + 1, x+w-2, y + 1);
                }
            }
        }
    
protected voidpaintFocusIndicator(java.awt.Graphics g, int tabPlacement, java.awt.Rectangle[] rects, int tabIndex, java.awt.Rectangle iconRect, java.awt.Rectangle textRect, boolean isSelected)

        if ( tabPane.hasFocus() && isSelected ) {
            Rectangle tabRect = rects[tabIndex];
	    boolean lastInRun = isLastInRun( tabIndex );
            g.setColor( focus );
            g.translate( tabRect.x, tabRect.y );
            int right = tabRect.width - 1;
            int bottom = tabRect.height - 1;
	    boolean leftToRight = MetalUtils.isLeftToRight(tabPane);
            switch ( tabPlacement ) {
            case RIGHT:
                g.drawLine( right - 6,2 , right - 2,6 );         // slant
                g.drawLine( 1,2 , right - 6,2 );                 // top
                g.drawLine( right - 2,6 , right - 2,bottom );    // right
                g.drawLine( 1,2 , 1,bottom );                    // left
                g.drawLine( 1,bottom , right - 2,bottom );       // bottom
                break;
            case BOTTOM:
	        if ( leftToRight ) {
		    g.drawLine( 2, bottom - 6, 6, bottom - 2 );   // slant
		    g.drawLine( 6, bottom - 2,
				right, bottom - 2 );              // bottom
		    g.drawLine( 2, 0, 2, bottom - 6 );            // left
		    g.drawLine( 2, 0, right, 0 );                 // top
		    g.drawLine( right, 0, right, bottom - 2 );    // right
		} else {
		    g.drawLine( right - 2, bottom - 6,
				right - 6, bottom - 2 );          // slant
		    g.drawLine( right - 2, 0,
				right - 2, bottom - 6 );          // right
		    if ( lastInRun ) {
			// last tab in run
			g.drawLine( 2, bottom - 2,
				    right - 6, bottom - 2 );      // bottom
			g.drawLine( 2, 0, right - 2, 0 );         // top
			g.drawLine( 2, 0, 2, bottom - 2 );        // left
		    } else {
			g.drawLine( 1, bottom - 2,
				    right - 6, bottom - 2 );      // bottom
			g.drawLine( 1, 0, right - 2, 0 );         // top
			g.drawLine( 1, 0, 1, bottom - 2 );        // left
		    }
		}
                break;
            case LEFT:
                g.drawLine( 2, 6, 6, 2 );                         // slant
                g.drawLine( 2, 6, 2, bottom - 1);                 // left
                g.drawLine( 6, 2, right, 2 );                     // top
                g.drawLine( right, 2, right, bottom - 1 );        // right
                g.drawLine( 2, bottom - 1, 
                            right, bottom - 1 );                  // bottom
                break;
            case TOP:
             default:
		    if ( leftToRight ) {
		        g.drawLine( 2, 6, 6, 2 );                     // slant
			g.drawLine( 2, 6, 2, bottom - 1);             // left
			g.drawLine( 6, 2, right, 2 );                 // top
			g.drawLine( right, 2, right, bottom - 1 );    // right
			g.drawLine( 2, bottom - 1,
				    right, bottom - 1 );              // bottom
		    }
		    else {
		        g.drawLine( right - 2, 6, right - 6, 2 );     // slant
			g.drawLine( right - 2, 6,
				    right - 2, bottom - 1);           // right
			if ( lastInRun ) {
			    // last tab in run
			    g.drawLine( right - 6, 2, 2, 2 );         // top
			    g.drawLine( 2, 2, 2, bottom - 1 );        // left
			    g.drawLine( right - 2, bottom - 1,
					2, bottom - 1 );              // bottom
			}
			else {
			    g.drawLine( right - 6, 2, 1, 2 );         // top
			    g.drawLine( 1, 2, 1, bottom - 1 );        // left
			    g.drawLine( right - 2, bottom - 1,
					1, bottom - 1 );              // bottom
			}
		    }
            }
            g.translate( -tabRect.x, -tabRect.y );
        }
    
protected voidpaintHighlightBelowTab()


    
protected voidpaintLeftTabBorder(int tabIndex, java.awt.Graphics g, int x, int y, int w, int h, int btm, int rght, boolean isSelected)

        int tabCount = tabPane.getTabCount();
        int currentRun = getRunForTab( tabCount, tabIndex );
        int lastIndex = lastTabInRun( tabCount, currentRun );
        int firstIndex = tabRuns[ currentRun ];

        g.translate( x, y );

        int bottom = h - 1;
        int right = w - 1;

        //
        // Paint part of the tab above
        //

        if ( tabIndex != firstIndex && tabsOpaque ) {
            g.setColor( tabPane.getSelectedIndex() == tabIndex - 1 ?
                        selectColor :
                        getUnselectedBackgroundAt( tabIndex - 1 ) );
            g.fillRect( 2, 0, 4, 3 );
            g.drawLine( 2, 3, 2, 3 );
        }


        //
        // Paint Highlight
        //

        if (ocean) {
            g.setColor(isSelected ? selectHighlight :
                       MetalLookAndFeel.getWhite());
        }
        else {
            g.setColor( isSelected ? selectHighlight : highlight );
        }

        // Paint slant
        g.drawLine( 1, 6, 6, 1 );

        // Paint left
        g.drawLine( 1, 6, 1, bottom );

        // Paint top
        g.drawLine( 6, 1, right, 1 );

        if ( tabIndex != firstIndex ) {
            if (tabPane.getSelectedIndex() == tabIndex - 1) {
                g.setColor(selectHighlight);
            } else {
                g.setColor(ocean ? MetalLookAndFeel.getWhite() : highlight);
            }

            g.drawLine( 1, 0, 1, 4 );
        }

        //
        // Paint Border
        //

        if (ocean) {
            if (isSelected) {
                g.setColor(oceanSelectedBorderColor);
            }
            else {
                g.setColor( darkShadow );
            }
        }
        else {
            g.setColor( darkShadow );
        }

        // Paint slant
        g.drawLine( 1, 5, 6, 0 );

        // Paint top
        g.drawLine( 6, 0, right, 0 );

        // Paint bottom
        if ( tabIndex == lastIndex ) {
            g.drawLine( 0, bottom, right, bottom );
        }

        // Paint left
        if (ocean) {
            if (tabPane.getSelectedIndex() == tabIndex - 1) {
                g.drawLine(0, 5, 0, bottom);
                g.setColor(oceanSelectedBorderColor);
                g.drawLine(0, 0, 0, 5);
            }
            else if (isSelected) {
                g.drawLine( 0, 6, 0, bottom );
                if (tabIndex != 0) {
                    g.setColor(darkShadow);
                    g.drawLine(0, 0, 0, 5);
                }
            }
            else if ( tabIndex != firstIndex ) {
                g.drawLine( 0, 0, 0, bottom );
            } else {
                g.drawLine( 0, 6, 0, bottom );
            }
        }
        else { // metal
            if ( tabIndex != firstIndex ) {
                g.drawLine( 0, 0, 0, bottom );
            } else {
                g.drawLine( 0, 6, 0, bottom );
            }
        }

        g.translate( -x, -y );
    
protected voidpaintRightTabBorder(int tabIndex, java.awt.Graphics g, int x, int y, int w, int h, int btm, int rght, boolean isSelected)

        int tabCount = tabPane.getTabCount();
        int currentRun = getRunForTab( tabCount, tabIndex );
        int lastIndex = lastTabInRun( tabCount, currentRun );
        int firstIndex = tabRuns[ currentRun ];

        g.translate( x, y );

        int bottom = h - 1;
        int right = w - 1;

        //
        // Paint part of the tab above
        //

        if ( tabIndex != firstIndex && tabsOpaque ) {
            g.setColor( tabPane.getSelectedIndex() == tabIndex - 1 ?
                        selectColor :
                        getUnselectedBackgroundAt( tabIndex - 1 ) );
            g.fillRect( right - 5, 0, 5, 3 );
            g.fillRect( right - 2, 3, 2, 2 );
        }


        //
        // Paint Highlight
        //

        g.setColor( isSelected ? selectHighlight : highlight );

        // Paint slant
        g.drawLine( right - 6, 1, right - 1, 6 );

        // Paint top
        g.drawLine( 0, 1, right - 6, 1 );

        // Paint left
	if ( !isSelected ) {
	    g.drawLine( 0, 1, 0, bottom );
	}


        //
        // Paint Border
        //

        if (ocean && isSelected) {
            g.setColor(oceanSelectedBorderColor);
        }
        else {
            g.setColor( darkShadow );
        }

        // Paint bottom
        if ( tabIndex == lastIndex ) {
            g.drawLine( 0, bottom, right, bottom );
        }

        // Paint slant
        if (ocean && tabPane.getSelectedIndex() == tabIndex - 1) {
            g.setColor(oceanSelectedBorderColor);
        }
        g.drawLine( right - 6, 0, right, 6 );

        // Paint top
        g.drawLine( 0, 0, right - 6, 0 );

        // Paint right
        if (ocean && isSelected) {
            g.drawLine(right, 6, right, bottom);
            if (tabIndex != firstIndex) {
                g.setColor(darkShadow);
                g.drawLine(right, 0, right, 5);
            }
        }
        else if (ocean && tabPane.getSelectedIndex() == tabIndex - 1) {
            g.setColor(oceanSelectedBorderColor);
            g.drawLine(right, 0, right, 6);
            g.setColor(darkShadow);
            g.drawLine(right, 6, right, bottom);
        }
        else if ( tabIndex != firstIndex ) {
            g.drawLine( right, 0, right, bottom );
        } else {
            g.drawLine( right, 6, right, bottom );
        }

        g.translate( -x, -y );
    
protected voidpaintTabBackground(java.awt.Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected)

        int slantWidth = h / 2;
        if ( isSelected ) {
            g.setColor( selectColor );
        } else {
            g.setColor( getUnselectedBackgroundAt( tabIndex ) );
        }

	if (MetalUtils.isLeftToRight(tabPane)) {
	    switch ( tabPlacement ) {
                case LEFT:
		    g.fillRect( x + 5, y + 1, w - 5, h - 1);
		    g.fillRect( x + 2, y + 4, 3, h - 4 );
		    break;
                case BOTTOM:
		    g.fillRect( x + 2, y, w - 2, h - 4 );
		    g.fillRect( x + 5, y + (h - 1) - 3, w - 5, 3 );
		    break;
                case RIGHT:
		    g.fillRect( x, y + 2, w - 4, h - 2);
		    g.fillRect( x + (w - 1) - 3, y + 5, 3, h - 5 );
		    break;
                case TOP:
                default:
		    g.fillRect( x + 4, y + 2, (w - 1) - 3, (h - 1) - 1 );
		    g.fillRect( x + 2, y + 5, 2, h - 5 );
	    }
	} else {
	    switch ( tabPlacement ) {
                case LEFT:
		    g.fillRect( x + 5, y + 1, w - 5, h - 1);
		    g.fillRect( x + 2, y + 4, 3, h - 4 );
		    break;
                case BOTTOM:
		    g.fillRect( x, y, w - 5, h - 1 );
		    g.fillRect( x + (w - 1) - 4, y, 4, h - 5);
		    g.fillRect( x + (w - 1) - 4, y + (h - 1) - 4, 2, 2);
		    break;
                case RIGHT:
		    g.fillRect( x + 1, y + 1, w - 5, h - 1);
		    g.fillRect( x + (w - 1) - 3, y + 5, 3, h - 5 );
		    break;
                case TOP:
                default:
		    g.fillRect( x, y + 2, (w - 1) - 3, (h - 1) - 1 );
		    g.fillRect( x + (w - 1) - 3, y + 5, 3, h - 3 );
	    }
	}
    
protected voidpaintTabBorder(java.awt.Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected)

        int bottom = y + (h-1);
        int right = x + (w-1);

        switch ( tabPlacement ) {
        case LEFT:
            paintLeftTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected);
            break;
        case BOTTOM:
            paintBottomTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected);
            break;
        case RIGHT:
            paintRightTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected);
            break;
        case TOP:
        default:
            paintTopTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected);
        }
    
protected voidpaintTopTabBorder(int tabIndex, java.awt.Graphics g, int x, int y, int w, int h, int btm, int rght, boolean isSelected)

        int currentRun = getRunForTab( tabPane.getTabCount(), tabIndex );
        int lastIndex = lastTabInRun( tabPane.getTabCount(), currentRun );
        int firstIndex = tabRuns[ currentRun ];
	boolean leftToRight = MetalUtils.isLeftToRight(tabPane);
        int selectedIndex = tabPane.getSelectedIndex();
        int bottom = h - 1;
        int right = w - 1;

        //
        // Paint Gap
        //

        if (shouldFillGap( currentRun, tabIndex, x, y ) ) {
            g.translate( x, y );

	    if ( leftToRight ) {
	        g.setColor( getColorForGap( currentRun, x, y + 1 ) );
		g.fillRect( 1, 0, 5, 3 );
		g.fillRect( 1, 3, 2, 2 );
	    } else {
	        g.setColor( getColorForGap( currentRun, x + w - 1, y + 1 ) );
		g.fillRect( right - 5, 0, 5, 3 );
		g.fillRect( right - 2, 3, 2, 2 );
	    }

            g.translate( -x, -y );
        }

        g.translate( x, y );

        //
        // Paint Border
        //

        if (ocean && isSelected) {
            g.setColor(oceanSelectedBorderColor);
        }
        else {
            g.setColor( darkShadow );
        }

	if ( leftToRight ) {

	    // Paint slant
	    g.drawLine( 1, 5, 6, 0 );

	    // Paint top
	    g.drawLine( 6, 0, right, 0 );

	    // Paint right
	    if ( tabIndex==lastIndex ) {
	        // last tab in run
	        g.drawLine( right, 1, right, bottom );
	    }

            if (ocean && tabIndex - 1 == selectedIndex &&
                                currentRun == getRunForTab(
                                tabPane.getTabCount(), selectedIndex)) {
                g.setColor(oceanSelectedBorderColor);
            }

	    // Paint left
	    if ( tabIndex != tabRuns[ runCount - 1 ] ) {
	        // not the first tab in the last run
                if (ocean && isSelected) {
                    g.drawLine(0, 6, 0, bottom);
                    g.setColor(darkShadow);
                    g.drawLine(0, 0, 0, 5);
                }
                else {
                    g.drawLine( 0, 0, 0, bottom );
                }
	    } else {
	        // the first tab in the last run
	        g.drawLine( 0, 6, 0, bottom );
	    }
	} else {

	    // Paint slant
	    g.drawLine( right - 1, 5, right - 6, 0 );

	    // Paint top
	    g.drawLine( right - 6, 0, 0, 0 );

	    // Paint left
	    if ( tabIndex==lastIndex ) {
	        // last tab in run
	        g.drawLine( 0, 1, 0, bottom );
	    }

            // Paint right
            if (ocean && tabIndex - 1 == selectedIndex &&
                                currentRun == getRunForTab(
                                tabPane.getTabCount(), selectedIndex)) {
                g.setColor(oceanSelectedBorderColor);
                g.drawLine(right, 0, right, bottom);
            }
            else if (ocean && isSelected) {
                g.drawLine(right, 6, right, bottom);
                if (tabIndex != 0) {
                    g.setColor(darkShadow);
                    g.drawLine(right, 0, right, 5);
                }
            }
            else {
                if ( tabIndex != tabRuns[ runCount - 1 ] ) {
                    // not the first tab in the last run
                    g.drawLine( right, 0, right, bottom );
                } else {
                    // the first tab in the last run
                    g.drawLine( right, 6, right, bottom );
                }
            }
	}

        //
        // Paint Highlight
        //

        g.setColor( isSelected ? selectHighlight : highlight );

	if ( leftToRight ) {

	    // Paint slant
	    g.drawLine( 1, 6, 6, 1 );

	    // Paint top
            g.drawLine( 6, 1, (tabIndex == lastIndex) ? right - 1 : right, 1 );

	    // Paint left
	    g.drawLine( 1, 6, 1, bottom );

	    // paint highlight in the gap on tab behind this one
	    // on the left end (where they all line up)
	    if ( tabIndex==firstIndex && tabIndex!=tabRuns[runCount - 1] ) {
	        //  first tab in run but not first tab in last run
	        if (tabPane.getSelectedIndex()==tabRuns[currentRun+1]) {
		    // tab in front of selected tab
		    g.setColor( selectHighlight );
		}
		else {
		    // tab in front of normal tab
		    g.setColor( highlight );
		}
		g.drawLine( 1, 0, 1, 4 );
	    }
	} else {

	    // Paint slant
	    g.drawLine( right - 1, 6, right - 6, 1 );

	    // Paint top
	    g.drawLine( right - 6, 1, 1, 1 );

	    // Paint left
	    if ( tabIndex==lastIndex ) {
	        // last tab in run
	        g.drawLine( 1, 1, 1, bottom );
	    } else {
	        g.drawLine( 0, 1, 0, bottom );
	    }
	}

        g.translate( -x, -y );
    
protected booleanshouldFillGap(int currentRun, int tabIndex, int x, int y)

        boolean result = false;

        if (!tabsOpaque) {
            return false;
        }
        
        if ( currentRun == runCount - 2 ) {  // If it's the second to last row.
            Rectangle lastTabBounds = getTabBounds( tabPane, tabPane.getTabCount() - 1 );
	    Rectangle tabBounds = getTabBounds( tabPane, tabIndex );
            if (MetalUtils.isLeftToRight(tabPane)) {
	        int lastTabRight = lastTabBounds.x + lastTabBounds.width - 1;

		// is the right edge of the last tab to the right
		// of the left edge of the current tab?
		if ( lastTabRight > tabBounds.x + 2 ) {
		    return true;
		}
	    } else {
	        int lastTabLeft = lastTabBounds.x;
		int currentTabRight = tabBounds.x + tabBounds.width - 1;

		// is the left edge of the last tab to the left
		// of the right edge of the current tab?
		if ( lastTabLeft < currentTabRight - 2 ) {
		    return true;
		}
            }
        } else {
	    // fill in gap for all other rows except last row
            result = currentRun != runCount - 1;
        }

        return result;
    
protected booleanshouldPadTabRun(int tabPlacement, int run)

        return runCount > 1 && run < runCount - 1;
    
protected booleanshouldRotateTabRuns(int tabPlacement, int selectedRun)

        return false;
    
public voidupdate(java.awt.Graphics g, javax.swing.JComponent c)

	if ( c.isOpaque() ) {
	    g.setColor( tabAreaBackground );
	    g.fillRect( 0, 0, c.getWidth(),c.getHeight() );
	}
	paint( g, c );