/* MetalTabbedPaneUI.java
   Copyright (C) 2005, 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.plaf.metal;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.LayoutManager;
import java.awt.Rectangle;

import javax.swing.JComponent;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTabbedPaneUI;

/**
 * A UI delegate for the {@link JTabbedPane} component.
 */
public class MetalTabbedPaneUI extends BasicTabbedPaneUI
{

  /**
   * A {@link LayoutManager} responsible for placing all the tabs and the 
   * visible component inside the {@link JTabbedPane}. This class is only used 
   * for {@link JTabbedPane#WRAP_TAB_LAYOUT}.
   *
   * @specnote Apparently this class was intended to be protected,
   *           but was made public by a compiler bug and is now
   *           public for compatibility.
   */
  public class TabbedPaneLayout 
    extends BasicTabbedPaneUI.TabbedPaneLayout
  {
    /**
     * Creates a new instance of the layout manager.
     */
    public TabbedPaneLayout()
    {
      // Nothing to do here.
    }
    
    /**
     * Overridden to do nothing, because tab runs are not rotated in the 
     * {@link MetalLookAndFeel}.
     * 
     * @param tabPlacement  the tab placement (one of {@link #TOP}, 
     *        {@link #BOTTOM}, {@link #LEFT} or {@link #RIGHT}).
     * @param selectedRun  the index of the selected run.
     */
    protected void rotateTabRuns(int tabPlacement, int selectedRun)
    {
      // do nothing, because tab runs are not rotated in the MetalLookAndFeel
    }
    
    /**
     * Overridden to do nothing, because the selected tab does not have extra
     * padding in the {@link MetalLookAndFeel}.
     * 
     * @param tabPlacement  the tab placement (one of {@link #TOP}, 
     *        {@link #BOTTOM}, {@link #LEFT} or {@link #RIGHT}).
     * @param selectedIndex  the index of the selected tab.
     */
    protected void padSelectedTab(int tabPlacement, int selectedIndex)
    {
      // do nothing, because the selected tab does not have extra padding in 
      // the MetalLookAndFeel
    }

    /**
     * Overridden because tab runs are only normalized for TOP and BOTTOM
     * tab placement in the Metal L&F.
     */
    protected void normalizeTabRuns(int tabPlacement, int tabCount, int start,
                                    int max)
    {
      if (tabPlacement == TOP || tabPlacement == BOTTOM)
        super.normalizeTabRuns(tabPlacement, tabCount, start, max);
    }
  }

  /**
   * The minimum tab width.
   */
  protected int minTabWidth;

  /**
   * The color for the selected tab.
   */
  protected Color selectColor;

  /**
   * The color for a highlighted selected tab.
   */
  protected Color selectHighlight;

  /**
   * The background color used for the tab area.
   */
  protected Color tabAreaBackground;

  /** The graphics to draw the highlight below the tab. */
  private Graphics hg;

  /**
   * Indicates if the tabs are having their background filled.
   */
  private boolean tabsOpaque;

  /**
   * Constructs a new instance of MetalTabbedPaneUI.
   */
  public MetalTabbedPaneUI()
  {
    super();
  }

  /**
   * Returns an instance of MetalTabbedPaneUI.
   *
   * @param component the component for which we return an UI instance
   *
   * @return an instance of MetalTabbedPaneUI
   */
  public static ComponentUI createUI(JComponent component)
  {
    return new MetalTabbedPaneUI();
  }
  
  /**
   * Creates and returns an instance of {@link TabbedPaneLayout}.
   * 
   * @return A layout manager used by this UI delegate.
   */
  protected LayoutManager createLayoutManager()
  {
    return (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
           ? new MetalTabbedPaneUI.TabbedPaneLayout()
           : super.createLayoutManager();
  }
  
  /**
   * Paints the border for a single tab.
   * 
   * @param g  the graphics device.
   * @param tabPlacement  the tab placement ({@link #TOP}, {@link #LEFT}, 
   *        {@link #BOTTOM} or {@link #RIGHT}).
   * @param tabIndex  the index of the tab to draw the border for.
   * @param x  the x-coordinate for the tab's bounding rectangle.
   * @param y  the y-coordinate for the tab's bounding rectangle.
   * @param w  the width for the tab's bounding rectangle.
   * @param h  the height for the tab's bounding rectangle.
   * @param isSelected  indicates whether or not the tab is selected.
   */
  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);
    }
  }

  /**
   * Paints the border for a tab assuming that the tab position is at the top
   * ({@link #TOP}).
   * 
   * @param tabIndex  the tab index.
   * @param g  the graphics device.
   * @param x  the x-coordinate for the tab's bounding rectangle.
   * @param y  the y-coordinate for the tab's bounding rectangle.
   * @param w  the width for the tab's bounding rectangle.
   * @param h  the height for the tab's bounding rectangle.
   * @param btm  the y coordinate of the bottom border
   * @param rght the x coordinate of the right border
   * @param isSelected  indicates whether the tab is selected.
   */
  protected void paintTopTabBorder(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 right = w - 1;
    int bottom = h - 1;

    // Paint gap.
    if (shouldFillGap(currentRun, tabIndex, x, y))
      {
        g.translate(x, y);
        g.setColor(getColorForGap(currentRun, x, y + 1));
        g.fillRect(1, 0, 5, 3);
        g.fillRect(1, 3, 2, 2);
        g.translate(-x, -y);
      }

    g.translate(x, y);

    boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
    Color oceanSelectedBorder =
      UIManager.getColor("TabbedPane.borderHightlightColor");
    if (isOcean && isSelected)
      g.setColor(oceanSelectedBorder);
    else
      g.setColor(darkShadow);

    // Slant
    g.drawLine(1, 5, 6, 0);
    // Top.
    g.drawLine(6, 0, right, 0);
    // Right.
    int lastIndex = lastTabInRun(tabCount, currentRun);
    if (tabIndex == lastIndex)
      g.drawLine(right, 1, right, bottom);
    // Left.
    int selectedIndex = tabPane.getSelectedIndex();
    if (isOcean && tabIndex - 1 == selectedIndex
        && currentRun == getRunForTab(tabCount, selectedIndex))
      {
        g.setColor(oceanSelectedBorder);
      }
    if (tabIndex != tabRuns[runCount - 1])
      {
        if (isOcean && isSelected)
          {
            g.drawLine(0, 6, 0, bottom);
            g.setColor(darkShadow);
            g.drawLine(0, 0, 0, 5);
          }
        else
          {
            g.drawLine(0, 0, 0, bottom);
          }
      }
    else
      {
        g.drawLine(0, 6, 0, bottom);
      }

    // Paint the highlight.
    g.setColor(isSelected ? selectHighlight : highlight);
    // Slant.
    g.drawLine(1, 6, 6, 1);
    // Top.
    g.drawLine(6, 1, right, 1);
    // Left.
    g.drawLine(1, 6, 1, bottom);
    int firstIndex = tabRuns[currentRun];
    if (tabIndex == firstIndex && tabIndex != tabRuns[runCount - 1])
      {
        if (tabPane.getSelectedIndex() == tabRuns[currentRun + 1])
          g.setColor(selectHighlight);
        else
          g.setColor(highlight);
        g.drawLine(1, 0, 1, 4);
      }

    g.translate(-x, -y);
  }
  
  /**
   * Paints the border for a tab assuming that the tab position is at the left
   * ({@link #LEFT}).
   * 
   * @param tabIndex  the tab index.
   * @param g  the graphics device.
   * @param x  the x-coordinate for the tab's bounding rectangle.
   * @param y  the y-coordinate for the tab's bounding rectangle.
   * @param w  the width for the tab's bounding rectangle.
   * @param h  the height for the tab's bounding rectangle.
   * @param btm  ???
   * @param rght  ???
   * @param isSelected  indicates whether the tab is selected.
   */
  protected void paintLeftTabBorder(int tabIndex, Graphics g, int x, int y,
      int w, int h, int btm, int rght, boolean isSelected)
  {
    g.translate(x, y);
    int bottom = h - 1;
    int right = w - 1;

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

    // Paint the part of the above tab.
    if (tabIndex != firstIndex && tabIndex > 0 && tabsOpaque)
      {
        Color c;
        if (tabPane.getSelectedIndex() == tabIndex - 1)
          c = selectColor;
        else
          c = getUnselectedBackground(tabIndex - 1);
        g.setColor(c);
        g.fillRect(2, 0, 4, 3);
        g.drawLine(2, 3, 2, 3);
      }

    // Paint the highlight.
    boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
    if (isOcean)
      {
        g.setColor(isSelected ? selectHighlight : MetalLookAndFeel.getWhite());
      }
    else
      {
        g.setColor(isSelected ? selectHighlight : highlight);
      }
    // Slant.
    g.drawLine(1, 6, 6, 1);
    // Left.
    g.drawLine(1, 6, 1, bottom);
    // Top.
    g.drawLine(6, 1, right, 1);
    if (tabIndex != firstIndex)
      {
        if (isOcean)
          {
            g.setColor(MetalLookAndFeel.getWhite());
          }
        g.drawLine(1, 0, 1, 4);
      }

    // Paint border.
    Color oceanSelectedBorder =
      UIManager.getColor("TabbedPane.borderHightlightColor");
    if (isOcean && isSelected)
      {
        g.setColor(oceanSelectedBorder);
      }
    else
      {
        g.setColor(darkShadow);
      }

    // Slant.
    g.drawLine(1, 5, 6, 0);
    // Top.
    g.drawLine(6, 0, right, 0);
    // Bottom.
    int lastIndex = lastTabInRun(tabCount, currentRun);
    if (tabIndex == lastIndex)
      {
        g.drawLine(0, bottom, right, bottom);
      }
    // Left.
    if (isOcean)
      {
        if (tabPane.getSelectedIndex() == tabIndex - 1)
          {
            g.drawLine(0, 6, 0, bottom);
            if (tabIndex != firstIndex)
              {
                g.setColor(oceanSelectedBorder);
                g.drawLine(0, 0, 0, 5);
              }
          }
        else if (isSelected)
          {
            g.drawLine(0, 5, 0, bottom);
            if (tabIndex != firstIndex)
              {
                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
      {
        if (tabIndex != firstIndex)
          {
            g.drawLine(0, 0, 0, bottom);
          }
        else
          {
            g.drawLine(0, 6, 0, bottom);
          }
      }

    g.translate(-x, -y);
  }
  
  /**
   * Paints the border for a tab assuming that the tab position is at the right
   * ({@link #RIGHT}).
   * 
   * @param tabIndex  the tab index.
   * @param g  the graphics device.
   * @param x  the x-coordinate for the tab's bounding rectangle.
   * @param y  the y-coordinate for the tab's bounding rectangle.
   * @param w  the width for the tab's bounding rectangle.
   * @param h  the height for the tab's bounding rectangle.
   * @param btm  ???
   * @param rght  ???
   * @param isSelected  indicates whether the tab is selected.
   */
  protected void paintRightTabBorder(int tabIndex, Graphics g, int x, int y,
      int w, int h, int btm, int rght, boolean isSelected)
  {
    g.translate(x, y);
    int bottom = h - 1;
    int right = w - 1;

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

    // Paint part of the above tab.
    if (tabIndex != firstIndex && tabIndex > 0 && tabsOpaque)
      {
        Color c;
        if (tabPane.getSelectedIndex() == tabIndex - 1)
          c = selectColor;
        else
          c = getUnselectedBackground(tabIndex - 1);
        g.setColor(c);
        g.fillRect(right - 5, 0, 5, 3);
        g.fillRect(right - 2, 3, 2, 2);
      }

    // Paint highlight.
    g.setColor(isSelected ? selectHighlight : highlight);

    // Slant.
    g.drawLine(right - 6, 1, right - 1, 6);
    // Top.
    g.drawLine(0, 1, right - 6, 1);
    // Left.
    if (! isSelected)
      {
        g.drawLine(0, 1, 0, bottom);
      }

    // Paint border.
    boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
    Color oceanSelectedBorder =
      UIManager.getColor("TabbedPane.borderHightlightColor");
    if (isOcean && isSelected)
      {
        g.setColor(oceanSelectedBorder);
      }
    else
      {
        g.setColor(darkShadow);
      }

    // Bottom.
    int lastIndex = lastTabInRun(tabCount, currentRun);
    if (tabIndex == lastIndex)
      {
        g.drawLine(0, bottom, right, bottom);
      }
    // Slant.
    if (isOcean && tabPane.getSelectedIndex() == tabIndex - 1)
      {
        g.setColor(oceanSelectedBorder);
      }
    g.drawLine(right - 6, 0, right, 6);
    // Top.
    g.drawLine(0, 0, right - 6, 0);
    // Right.
    if (isOcean && isSelected)
      {
        g.drawLine(right, 6, right, bottom);
        if (tabIndex != firstIndex)
          {
            g.setColor(darkShadow);
            g.drawLine(right, 0, right, 5);
          }
      }
    else if (isOcean && tabPane.getSelectedIndex() == tabIndex - 1)
      {
        if (tabIndex != firstIndex)
          {
            g.setColor(oceanSelectedBorder);
            g.drawLine(right, 0, right, 6);
          }
        g.setColor(darkShadow);
        g.drawLine(right, 7, right, bottom);
      }
    else if (tabIndex != firstIndex)
      {
        g.drawLine(right, 0, right, bottom);
      }
    else
      {
        g.drawLine(right, 6, right, bottom);
      }
    g.translate(-x, -y);
  }
  
  /**
   * Paints the border for a tab assuming that the tab position is at the bottom
   * ({@link #BOTTOM}).
   * 
   * @param tabIndex  the tab index.
   * @param g  the graphics device.
   * @param x  the x-coordinate for the tab's bounding rectangle.
   * @param y  the y-coordinate for the tab's bounding rectangle.
   * @param w  the width for the tab's bounding rectangle.
   * @param h  the height for the tab's bounding rectangle.
   * @param btm  ???
   * @param rght  ???
   * @param isSelected  indicates whether the tab is selected.
   */
  protected void paintBottomTabBorder(int tabIndex, Graphics g, int x, int y,
      int w, int h, int btm, int rght, boolean isSelected)
  {
    int bottom = h - 1;
    int right = w - 1;

    int tabCount = tabPane.getTabCount();
    int currentRun = getRunForTab(tabCount, tabIndex);
    // Paint gap if necessary.
    if (shouldFillGap(currentRun, tabIndex, x, y))
      {
        g.translate(x, y);
        g.setColor(getColorForGap(currentRun, x, y));
        g.fillRect(1, bottom - 4, 3, 5);
        g.fillRect(4, bottom - 1, 2, 2);
        g.translate(-x, -y);
      }

    g.translate(x, y);

    // Paint border.
    boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
    Color oceanSelectedBorder =
      UIManager.getColor("TabbedPane.borderHightlightColor");
    if (isOcean && isSelected)
      {
        g.setColor(oceanSelectedBorder);
      }
    else
      {
        g.setColor(darkShadow);
      }
    // Slant.
    g.drawLine(1, bottom - 5, 6, bottom);
    // Bottom.
    g.drawLine(6, bottom, right, bottom);
    // Right.
    int lastIndex = lastTabInRun(tabCount, currentRun);
    if (tabIndex == lastIndex)
      {
        g.drawLine(right, 0, right, bottom);
      }
    // Left.
    if (isOcean && isSelected)
      {
        g.drawLine(0, 0, 0, bottom - 5);
        
        // Paint a connecting line to the tab below for all
        // but the first tab in the last run.
        if (tabIndex != tabRuns[runCount-1])
          {
            g.setColor(darkShadow);
            g.drawLine(0, bottom - 5, 0, bottom);
          }
      }
    else
      {
        if (isOcean && tabIndex == tabPane.getSelectedIndex() + 1)
          {
            g.setColor(oceanSelectedBorder);
          }
        if (tabIndex != tabRuns[runCount - 1])
          {
            g.drawLine(0, 0, 0, bottom);
          }
        else
          {
            g.drawLine(0, 0, 0, bottom - 6);
          }
      }

    // Paint highlight.
    g.setColor(isSelected ? selectHighlight : highlight);
    // Slant.
    g.drawLine(1, bottom - 6, 6, bottom - 1);
    // Left.
    g.drawLine(1, 0, 1, bottom - 6);

    int firstIndex = tabRuns[currentRun];
    if (tabIndex == firstIndex && tabIndex != tabRuns[runCount - 1])
      {
        if (tabPane.getSelectedIndex() == tabRuns[currentRun + 1])
          {
            g.setColor(selectHighlight);
          }
        else
          {
            g.setColor(highlight);
          }
        g.drawLine(1, bottom - 4, 1, bottom);
      }

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

  /**
   * Paints the background for a tab.
   * 
   * @param g  the graphics device.
   * @param tabPlacement  the tab placement ({@link #TOP}, {@link #LEFT}, 
   *        {@link #BOTTOM} or {@link #RIGHT}).
   * @param tabIndex  the index of the tab to draw the border for.
   * @param x  the x-coordinate for the tab's bounding rectangle.
   * @param y  the y-coordinate for the tab's bounding rectangle.
   * @param w  the width for the tab's bounding rectangle.
   * @param h  the height for the tab's bounding rectangle.
   * @param isSelected  indicates whether or not the tab is selected.
   */
  protected void paintTabBackground(Graphics g, int tabPlacement,
      int tabIndex, int x, int y, int w, int h, boolean isSelected)
  {
    if (isSelected)
      g.setColor(selectColor);
    else
      g.setColor(getUnselectedBackground(tabIndex));

    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 - 3);
        g.fillRect(x + 5, y + h - 4, w - 5, 3);
        break;
      case RIGHT:
        g.fillRect(x, y + 1, w - 4, h - 1);
        g.fillRect(x + w - 4, y + 5, 3, h - 5);
        break;
      case TOP:
      default:
        g.fillRect(x + 4, y + 2, w - 4, h - 2);
        g.fillRect(x + 2, y + 5, 2, h - 5);
    }
  }
  
  /**
   * This method paints the focus rectangle around the selected tab.
   *
   * @param g The Graphics object to paint with.
   * @param tabPlacement The JTabbedPane's tab placement.
   * @param rects The array of rectangles keeping track of size and position.
   * @param tabIndex The tab index.
   * @param iconRect The icon bounds.
   * @param textRect The text bounds.
   * @param isSelected Whether this tab is selected.
   */
  protected void paintFocusIndicator(Graphics g, int tabPlacement,
                                     Rectangle[] rects, int tabIndex,
                                     Rectangle iconRect, Rectangle textRect,
                                     boolean isSelected)
  {
    if (tabPane.hasFocus() && isSelected)
      {
        Rectangle rect = rects[tabIndex];

        g.setColor(focus);
        g.translate(rect.x, rect.y);
        
        switch (tabPlacement)
          {
          case LEFT:
            // Top line
            g.drawLine(7, 2, rect.width-2, 2);
            
            // Right line
            g.drawLine(rect.width-1, 2, rect.width-1, rect.height-3);
            
            // Bottom line
            g.drawLine(rect.width-2, rect.height-2, 3, rect.height-2);
            
            // Left line
            g.drawLine(2, rect.height-3, 2, 7);

            // Slant
            g.drawLine(2, 6, 6, 2);
            break;
          case RIGHT:
            // Top line
            g.drawLine(1, 2, rect.width-8, 2);
            
            // Slant
            g.drawLine(rect.width-7, 2, rect.width-3, 6);
            
            // Right line
            g.drawLine(rect.width-3, 7, rect.width-3, rect.height-3);
            
            // Bottom line
            g.drawLine(rect.width-3, rect.height-2, 2, rect.height-2);

            // Left line
            g.drawLine(1, rect.height-2, 1, 2);
            break;
          case BOTTOM:
            // Top line
            g.drawLine(2, 1, rect.width-2, 1);
            
            // Right line
            g.drawLine(rect.width-1, 2, rect.width-1, rect.height-3);
            
            // Bottom line
            g.drawLine(7, rect.height-3, rect.width-2, rect.height-3);
            
            // Slant
            g.drawLine(6, rect.height-3, 2, rect.height-7);
            
            // Left line
            g.drawLine(2, rect.height-8, 2, 2);
            
            break;
          case TOP:
          default:
            // Top line
            g.drawLine(6, 2, rect.width-2, 2);
            
            // Right line
            g.drawLine(rect.width-1, 2, rect.width-1, rect.height-3);
            
            // Bottom line
            g.drawLine(3, rect.height-3, rect.width-2, rect.height-3);
            
            // Left line
            g.drawLine(2, rect.height-3, 2, 7);
            
            // Slant
            g.drawLine(2, 6, 6, 2);
            
          }
        
        g.translate(-rect.x, -rect.y);
      }
  }
  
  /**
   * Returns <code>true</code> if the tabs in the specified run should be 
   * padded to make the run fill the width/height of the {@link JTabbedPane}.
   * 
   * @param tabPlacement  the tab placement for the {@link JTabbedPane} (one of
   *        {@link #TOP}, {@link #BOTTOM}, {@link #LEFT} and {@link #RIGHT}).
   * @param run  the run index.
   * 
   * @return A boolean.
   */
  protected boolean shouldPadTabRun(int tabPlacement, int run)
  {
    // as far as I can tell, all runs should be padded except the last run
    // (which is drawn at the very top for tabPlacement == TOP)
    return run < this.runCount - 1;
  }

  /**
   * Installs the defaults for this UI. This method calls super.installDefaults
   * and then loads the Metal specific defaults for TabbedPane.
   */
  protected void installDefaults()
  {
    super.installDefaults();
    selectColor = UIManager.getColor("TabbedPane.selected");
    selectHighlight = UIManager.getColor("TabbedPane.selectHighlight");
    tabAreaBackground = UIManager.getColor("TabbedPane.tabAreaBackground");
    tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque");
    minTabWidth = 0;
  }
  
  /**
   * Returns the color for the gap.
   * 
   * @param currentRun - The current run to return the color for
   * @param x - The x position of the current run
   * @param y - The y position of the current run
   * 
   * @return the color for the gap in the current run.
   */
  protected Color getColorForGap(int currentRun, int x, int y)
  {
    int index = tabForCoordinate(tabPane, x, y);
    int selected = tabPane.getSelectedIndex();
    if (selected == index)
      return selectColor;
    return tabAreaBackground;
  }
  
  /**
   * Returns true if the gap should be filled in.
   * 
   * @param currentRun - The current run
   * @param tabIndex - The current tab
   * @param x - The x position of the tab
   * @param y - The y position of the tab
   * 
   * @return true if the gap at the current run should be filled 
   */
  protected boolean shouldFillGap(int currentRun, int tabIndex, int x, int y)
  {
    // As far as I can tell, the gap is never filled in.
    return false;
  }
  
  /**
   * Paints the highlight below the tab, if there is one.
   */
  protected void paintHighlightBelowTab()
  {
    int selected = tabPane.getSelectedIndex();
    int tabPlacement = tabPane.getTabPlacement();
    Rectangle bounds = getTabBounds(tabPane, selected);
    
    hg.setColor(selectColor);
    int x = bounds.x;
    int y = bounds.y;
    int w = bounds.width;
    int h = bounds.height;

    if (tabPlacement == TOP) 
        hg.fillRect(x, y + h - 2, w, 30);
    else if (tabPlacement == LEFT)
        hg.fillRect(x + w - 1, y, 20, h);
    else if (tabPlacement == BOTTOM)
        hg.fillRect(x, y - h + 2, w, 30);
    else if (tabPlacement == RIGHT)
        hg.fillRect(x - 18, y, 20, h);
    else 
      throw new AssertionError("Unrecognised 'tabPlacement' argument.");
    hg = null;
  }
  
  /**
   * Returns true if we should rotate the tab runs. 
   * 
   * @param tabPlacement - The current tab placement.
   * @param selectedRun - The selected run.
   * 
   * @return true if the tab runs should be rotated.
   */
  protected boolean shouldRotateTabRuns(int tabPlacement,
                                        int selectedRun)
  {
    // false because tab runs are not rotated in the MetalLookAndFeel
    return false;
  }

  protected int calculateMaxTabHeight(int tabPlacement)
  {
    // FIXME: Why is this overridden?
    return super.calculateMaxTabHeight(tabPlacement);
  }

  /**
   * Returns the amount of overlay among the tabs. In
   * the Metal L&F the overlay for LEFT and RIGHT placement
   * is half of the maxTabHeight. For TOP and BOTTOM placement
   * the tabs do not overlay.
   *
   * @param tabPlacement the placement
   *
   * @return the amount of overlay among the tabs
   */
  protected int getTabRunOverlay(int tabPlacement)
  {
    int overlay = 0;
    if (tabPlacement == LEFT || tabPlacement == RIGHT)
      {
        int maxHeight = calculateMaxTabHeight(tabPlacement);
        overlay = maxTabHeight / 2;
      }
    return overlay;
  }

  /**
   * Paints the upper edge of the content border.
   *
   * @param g the graphics to use for painting
   * @param tabPlacement the tab placement
   * @param selectedIndex the index of the selected tab
   * @param x the upper left coordinate of the content area
   * @param y the upper left coordinate of the content area
   * @param w the width of the content area
   * @param h the height of the content area
   */
  protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
                                           int selectedIndex, int x, int y,
                                           int w, int h)
  {
    Color oceanSelectedBorder =
      UIManager.getColor("TabbedPane.borderHightlightColor");
    boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
    if (isOcean)
      {
        g.setColor(oceanSelectedBorder);
      }
    else
      {
        g.setColor(selectHighlight);
      }

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

    // If tabs are not placed on TOP, or if the selected tab is not in the
    // run directly above the content or the selected tab is not visible,
    // then we draw an unbroken line.
    if (tabPlacement != TOP || selectedIndex < 0
        || rect.y  + rect.height + 1 < y || rect.x < x || rect.x > x + w)
      {
        g.drawLine(x, y, x + w - 2, y);
        if (isOcean && tabPlacement == TOP)
          {
            g.setColor(MetalLookAndFeel.getWhite());
            g.drawLine(x, y + 1, x + w - 2, y + 1);
          }
      }
    else
      {
        boolean isLast = isLastTabInRun(selectedIndex);
        if (isLast)
          {
            g.drawLine(x, y, rect.x + 1, y);
          }
        else
          {
            g.drawLine(x, y, rect.x, y);
          }

        int right = x + w - 1;
        if (rect.x + rect.width < right - 1)
          {
            if (isLast)
              {
                g.drawLine(rect.x + rect.width - 1, y, right - 1, y);
              }
            else
              {
                g.drawLine(rect.x + rect.width, y, right - 1, y);
              }
          }
        else
          {
            g.setColor(shadow);
            g.drawLine(x + w - 2, y, x + w - 2, y);
          }

        // When in OceanTheme, draw another white line.
        if (isOcean)
          {
            g.setColor(MetalLookAndFeel.getWhite());
            if (isLast)
              {
                g.drawLine(x, y + 1, rect.x + 1, y + 1);
              }
            else
              {
                g.drawLine(x, y + 1, rect.x, y + 1);
              }

            if (rect.x + rect.width < right - 1)
              {
                if (isLast)
                  {
                    g.drawLine(rect.x + rect.width - 1, y + 1, right - 1,
                               y + 1);
                  }
                else
                  {
                    g.drawLine(rect.x + rect.width, y + 1, right - 1, y + 1);
                  }
              }
            else
              {
                g.setColor(shadow);
                g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
              }
          }
      }
  }

  /**
   * Paints the lower edge of the content border.
   *
   * @param g the graphics to use for painting
   * @param tabPlacement the tab placement
   * @param selectedIndex the index of the selected tab
   * @param x the upper left coordinate of the content area
   * @param y the upper left coordinate of the content area
   * @param w the width of the content area
   * @param h the height of the content area
   */
  protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement,
                                              int selectedIndex, int x, int y,
                                              int w, int h)
  {
    g.setColor(darkShadow);
    
    // If tabs are not placed on BOTTOM, or if the selected tab is not in the
    // run directly below the content or the selected tab is not visible,
    // then we draw an unbroken line.
    Rectangle rect = selectedIndex < 0 ? null :
                                         getTabBounds(selectedIndex, calcRect);
    boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
    Color oceanSelectedBorder =
      UIManager.getColor("TabbedPane.borderHightlightColor");
    if (tabPlacement != BOTTOM || selectedIndex < 0 || rect.y - 1 > h
        || rect.x < x || rect.x > x + w)
      {
        if (isOcean && tabPlacement == BOTTOM)
          {
            g.setColor(oceanSelectedBorder);
          }
        g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
      }
    else
      {
        boolean isLast = isLastTabInRun(selectedIndex);
        if (isOcean)
          {
            g.setColor(oceanSelectedBorder);
          }

        int bottom = y + h - 1;
        int right = x + w - 1;
        if (isLast)
          {
            g.drawLine(x, bottom, rect.x, bottom);
          }
        else
          {
            g.drawLine(x, bottom, rect.x - 1, bottom);
          }

        if (rect.x + rect.width < x + w - 2)
          {
            if (isLast)
              {
                g.drawLine(rect.x + rect.width - 1, bottom, right, bottom);
              }
            else
              {
                g.drawLine(rect.x + rect.width, bottom, right, bottom);
              }
          }
      }
  }

  /**
   * Paints the left edge of the content border.
   *
   * @param g the graphics to use for painting
   * @param tabPlacement the tab placement
   * @param selectedIndex the index of the selected tab
   * @param x the upper left coordinate of the content area
   * @param y the upper left coordinate of the content area
   * @param w the width of the content area
   * @param h the height of the content area
   */
  protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement,
                                            int selectedIndex, int x, int y,
                                            int w, int h)
  {
    boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
    Color oceanSelectedBorder =
      UIManager.getColor("TabbedPane.borderHightlightColor");
    Rectangle rect = selectedIndex < 0 ? null :
      getTabBounds(selectedIndex, calcRect);

    if (isOcean)
      {
        g.setColor(oceanSelectedBorder);
      }
    else
      {
        g.setColor(selectHighlight);
      }

    // If tabs are not placed on LEFT, or if the selected tab is not in the
    // run directly left to the content or the selected tab is not visible,
    // then we draw an unbroken line.
    if (tabPlacement != LEFT || selectedIndex < 0
        || rect.x + rect.width + 1 < x || rect.y < y || rect.y > y + h)
      {
        g.drawLine(x, y + 1, x, y + h - 2);
        if (isOcean && tabPlacement == LEFT)
          {
            g.setColor(MetalLookAndFeel.getWhite());
            g.drawLine(x, y + 1, x, y + h - 2);
          }       
      }
    else
      {
        g.drawLine(x, y, x, rect.y + 1);
        if (rect.y + rect.height < y + h - 2)
          {
            g.drawLine(x, rect.y + rect.height + 1, x, y + h + 2);
          }
        if (isOcean)
          {
            g.setColor(MetalLookAndFeel.getWhite());
            g.drawLine(x + 1, y + 1, x + 1, rect.y + 1);
            if (rect.y + rect.height < y + h - 2)
              {
                g.drawLine(x + y, rect.y + rect.height + 1, x + 1, y + h + 2);
              }
          }
      }
    
  }

  /**
   * Paints the right edge of the content border.
   *
   * @param g the graphics to use for painting
   * @param tabPlacement the tab placement
   * @param selectedIndex the index of the selected tab
   * @param x the upper left coordinate of the content area
   * @param y the upper left coordinate of the content area
   * @param w the width of the content area
   * @param h the height of the content area
   */
  protected void paintContentBorderRightEdge(Graphics g, int tabPlacement,
                                             int selectedIndex, int x, int y,
                                             int w, int h)
  {
    g.setColor(darkShadow);
    Rectangle rect = selectedIndex < 0 ? null :
      getTabBounds(selectedIndex, calcRect);
    boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
    Color oceanSelectedBorder =
      UIManager.getColor("TabbedPane.borderHightlightColor");

    // If tabs are not placed on RIGHT, or if the selected tab is not in the
    // run directly right to the content or the selected tab is not visible,
    // then we draw an unbroken line.
    if (tabPlacement != RIGHT || selectedIndex < 0 || rect.x - 1 > w
        || rect.y < y || rect.y > y + h)
      {
        if (isOcean && tabPlacement == RIGHT)
          {
            g.setColor(oceanSelectedBorder);
          }
        g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
      }
    else
      {
        if (isOcean)
          {
            g.setColor(oceanSelectedBorder);
          }
        g.drawLine(x + w - 1, y, x + w - 1, rect.y);

        if (rect.y + rect.height < y + h - 2)
          {
            g.drawLine(x + w - 1, rect.y + rect.height, x + w - 1, y + h - 2);
          }
      }
  }

  /**
   * Determines if the specified tab is the last tab in its tab run.
   *
   * @param tabIndex the index of the tab
   *
   * @return if the specified tab is the last tab in its tab run
   */
  private boolean isLastTabInRun(int tabIndex)
  {
    int count = tabPane.getTabCount();
    int run = getRunForTab(count, tabIndex);
    int lastIndex = lastTabInRun(count, run);
    return tabIndex == lastIndex;
  }

  /**
   * Returns the background for an unselected tab. This first asks the
   * JTabbedPane for the background at the specified tab index, if this
   * is an UIResource (that means, it is inherited from the JTabbedPane)
   * and the TabbedPane.unselectedBackground UI property is not null,
   * this returns the value of the TabbedPane.unselectedBackground property,
   * otherwise the value returned by the JTabbedPane.
   *
   * @param tabIndex the index of the tab for which we query the background
   *
   * @return the background for an unselected tab
   */
  private Color getUnselectedBackground(int tabIndex)
  {
    Color bg = tabPane.getBackgroundAt(tabIndex);
    Color unselectedBackground =
      UIManager.getColor("TabbedPane.unselectedBackground");
    if (bg instanceof UIResource && unselectedBackground != null)
      bg = unselectedBackground;
    return bg;
  }
  
  protected int getTabLabelShiftX(int tabPlacement,
                                  int index,
                                  boolean isSelected)
  {
    return 0;
  }

  protected int getTabLabelShiftY(int tabPlacement,
                                  int index,
                                  boolean isSelected)
  {
    return 0;
  }
  
}
