/*
 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.swing.plaf.metal;

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.plaf.*;
import java.io.Serializable;
import javax.swing.plaf.basic.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 JavaBeans™ has been added to the java.beans package. Please see XMLEncoder.

Author:Tom Santos
/** * The Metal subclass of BasicTabbedPaneUI. * <p> * <strong>Warning:</strong> * 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 JavaBeans&trade; * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @author Tom Santos */
public class MetalTabbedPaneUI extends BasicTabbedPaneUI { protected int minTabWidth = 40; // Background color for unselected tabs that don't have an explicitly // set color. private Color unselectedBackground; protected Color tabAreaBackground; protected Color selectColor; protected Color selectHighlight; private boolean tabsOpaque = true; // Whether or not we're using ocean. This is cached as it is used // extensively during painting. private boolean ocean; // Selected border color for ocean. private Color oceanSelectedBorderColor; public static ComponentUI createUI( JComponent x ) { return new MetalTabbedPaneUI(); } protected LayoutManager createLayoutManager() { if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { return super.createLayoutManager(); } return new TabbedPaneLayout(); } protected void installDefaults() { 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"); } } protected void paintTabBorder( 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 void paintTopTabBorder( int tabIndex, 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 boolean shouldFillGap( 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 Color getColorForGap( 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(); } protected void paintLeftTabBorder( int tabIndex, 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 void paintBottomTabBorder( int tabIndex, 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 void paintRightTabBorder( int tabIndex, 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 ); } public void update( Graphics g, JComponent c ) { if ( c.isOpaque() ) { g.setColor( tabAreaBackground ); g.fillRect( 0, 0, c.getWidth(),c.getHeight() ); } paint( g, c ); } protected void paintTabBackground( 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 ); } } }
Overridden to do nothing for the Java L&F.
/** * Overridden to do nothing for the Java L&amp;F. */
protected int getTabLabelShiftX( int tabPlacement, int tabIndex, boolean isSelected ) { return 0; }
Overridden to do nothing for the Java L&F.
/** * Overridden to do nothing for the Java L&amp;F. */
protected int getTabLabelShiftY( int tabPlacement, int tabIndex, boolean isSelected ) { return 0; }
{@inheritDoc}
Since:1.6
/** * {@inheritDoc} * * @since 1.6 */
protected int getBaselineOffset() { return 0; } public void paint( Graphics g, 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 background = c.getBackground(); if (background instanceof UIResource && tabAreaBackground != null) { g.setColor(tabAreaBackground); } else { g.setColor(background); } 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 void paintHighlightBelowTab( ) { } protected void paintFocusIndicator(Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex, Rectangle iconRect, 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 void paintContentBorderTopEdge( 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 void paintContentBorderBottomEdge(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 void paintContentBorderLeftEdge(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 void paintContentBorderRightEdge(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 int calculateMaxTabHeight( 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 int getTabRunOverlay( 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; } // Don't rotate runs! protected boolean shouldRotateTabRuns( int tabPlacement, int selectedRun ) { return false; } // Don't pad last run protected boolean shouldPadTabRun( int tabPlacement, int run ) { return runCount > 1 && run < runCount - 1; } private boolean isLastInRun( int tabIndex ) { int run = getRunForTab( tabPane.getTabCount(), tabIndex ); int lastIndex = lastTabInRun( tabPane.getTabCount(), run ); return tabIndex == lastIndex; }
Returns the color to use for the specified tab.
/** * Returns the color to use for the specified tab. */
private Color getUnselectedBackgroundAt(int index) { Color color = tabPane.getBackgroundAt(index); if (color instanceof UIResource) { if (unselectedBackground != null) { return unselectedBackground; } } return color; }
Returns the tab index of JTabbedPane the mouse is currently over
/** * Returns the tab index of JTabbedPane the mouse is currently over */
int getRolloverTabIndex() { return getRolloverTab(); }
This class should be treated as a "protected" inner class. Instantiate it only within subclasses of MetalTabbedPaneUI.
/** * This class should be treated as a &quot;protected&quot; inner class. * Instantiate it only within subclasses of {@code MetalTabbedPaneUI}. */
public class TabbedPaneLayout extends BasicTabbedPaneUI.TabbedPaneLayout { public TabbedPaneLayout() { MetalTabbedPaneUI.this.super(); } protected void normalizeTabRuns( int tabPlacement, int tabCount, int start, int max ) { // Only normalize the runs for top & bottom; normalizing // doesn't look right for Metal's vertical tabs // because the last run isn't padded and it looks odd to have // fat tabs in the first vertical runs, but slimmer ones in the // last (this effect isn't noticeable for horizontal tabs). if ( tabPlacement == TOP || tabPlacement == BOTTOM ) { super.normalizeTabRuns( tabPlacement, tabCount, start, max ); } } // Don't rotate runs! protected void rotateTabRuns( int tabPlacement, int selectedRun ) { } // Don't pad selected tab protected void padSelectedTab( int tabPlacement, int selectedIndex ) { } } }