summaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java')
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java861
1 files changed, 759 insertions, 102 deletions
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java
index c6c46ffe614..39dec3d663f 100644
--- a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java
@@ -47,6 +47,7 @@ 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;
/**
@@ -101,6 +102,17 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
// 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);
+ }
}
/**
@@ -125,7 +137,12 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
/** 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.
*/
@@ -153,7 +170,7 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
*/
protected LayoutManager createLayoutManager()
{
- return super.createLayoutManager();
+ return new TabbedPaneLayout();
}
/**
@@ -172,16 +189,24 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
int x, int y, int w, int h, boolean isSelected)
{
- if (tabPlacement == TOP)
- paintTopTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected);
- else if (tabPlacement == LEFT)
- paintLeftTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected);
- else if (tabPlacement == BOTTOM)
- paintBottomTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected);
- else if (tabPlacement == RIGHT)
- paintRightTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected);
- else
- throw new AssertionError("Unrecognised 'tabPlacement' argument.");
+ 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);
+ }
}
/**
@@ -194,35 +219,90 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
* @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 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 currentRun = getRunForTab(tabPane.getTabCount(), tabIndex);
+ 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));
+ g.setColor(getColorForGap(currentRun, x, y + 1));
g.fillRect(1, 0, 5, 3);
g.fillRect(1, 3, 2, 2);
g.translate(-x, -y);
}
-
- if (isSelected)
- {
- g.setColor(MetalLookAndFeel.getControlHighlight());
- g.drawLine(x + 1, y + h, x + 1, y + 6);
- g.drawLine(x + 1, y + 6, x + 6, y + 1);
- g.drawLine(x + 6, y + 1, x + w - 1, y + 1);
- }
- g.setColor(MetalLookAndFeel.getControlDarkShadow());
- g.drawLine(x, y + h - 1, x, y + 6);
- g.drawLine(x, y + 6, x + 6, y);
- g.drawLine(x + 6, y, x + w, y);
- g.drawLine(x + w, y, x + w, y + h - 1);
+
+ 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);
}
/**
@@ -242,18 +322,115 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
protected void paintLeftTabBorder(int tabIndex, Graphics g, int x, int y,
int w, int h, int btm, int rght, boolean isSelected)
{
- if (isSelected)
- {
- g.setColor(MetalLookAndFeel.getControlHighlight());
- g.drawLine(x + 1, y + h, x + 1, y + 6);
- g.drawLine(x + 1, y + 6, x + 6, y + 1);
- g.drawLine(x + 6, y + 1, x + w - 1, y + 1);
- }
- g.setColor(MetalLookAndFeel.getControlDarkShadow());
- g.drawLine(x, y + h, x, y + 6);
- g.drawLine(x, y + 6, x + 6, y);
- g.drawLine(x + 6, y, x + w - 1, y);
- g.drawLine(x, y + h, x + w - 1, y + h);
+ 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, 5, 0, bottom);
+ g.setColor(oceanSelectedBorder);
+ g.drawLine(0, 0, 0, 5);
+ }
+ else if (isSelected)
+ {
+ g.drawLine(0, 5, 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
+ {
+ if (tabIndex != firstIndex)
+ {
+ g.drawLine(0, 0, 0, bottom);
+ }
+ else
+ {
+ g.drawLine(0, 6, 0, bottom);
+ }
+ }
+
+ g.translate(-x, -y);
}
/**
@@ -273,17 +450,92 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
protected void paintRightTabBorder(int tabIndex, Graphics g, int x, int y,
int w, int h, int btm, int rght, boolean isSelected)
{
- if (isSelected)
- {
- g.setColor(MetalLookAndFeel.getControlHighlight());
- g.drawLine(x, y + 1, x + w - 7, y + 1);
- g.drawLine(x + w - 7, y + 1, x + w - 1, y + 7);
- }
- g.setColor(MetalLookAndFeel.getControlDarkShadow());
- g.drawLine(x, y, x + w - 7, y);
- g.drawLine(x + w - 7, y, x + w - 1, y + 6);
- g.drawLine(x + w - 1, y + 6, x + w - 1, y + h - 1);
- g.drawLine(x + w - 1, y + h, x, y + h);
+ 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 = UIManager.getColor("TabbedPane.tabAreaBackground");
+ else
+ c = getUnselectedBackground(tabIndex - 1);
+ 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)
+ {
+ g.setColor(oceanSelectedBorder);
+ 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);
}
/**
@@ -303,27 +555,94 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
protected void paintBottomTabBorder(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 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, h - 5, 3, 5);
- g.fillRect(4, h - 2, 2, 2);
+ g.fillRect(1, bottom - 4, 3, 5);
+ g.fillRect(4, bottom - 1, 2, 2);
g.translate(-x, -y);
}
-
- if (isSelected)
- {
- g.setColor(MetalLookAndFeel.getControlHighlight());
- g.drawLine(x + 1, y, x + 1, y + h - 7);
- g.drawLine(x + 1, y + h - 7, x + 7, y + h - 1);
- }
- g.setColor(MetalLookAndFeel.getControlDarkShadow());
- g.drawLine(x, y, x, y + h - 7);
- g.drawLine(x, y + h - 7, x + 6, y + h - 1);
- g.drawLine(x + 6, y + h - 1, x + w, y + h - 1);
- g.drawLine(x + w, y + h - 1, x + w, 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);
+ if ((currentRun == 0 && tabIndex != 0)
+ || (currentRun > 0 && tabIndex != tabRuns[currentRun - 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);
}
/**
@@ -343,42 +662,29 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
int tabIndex, int x, int y, int w, int h, boolean isSelected)
{
if (isSelected)
- g.setColor(UIManager.getColor("TabbedPane.selected"));
+ g.setColor(selectColor);
else
- {
- // This is only present in the OceanTheme, so we must check if it
- // is actually there
- Color background = UIManager.getColor("TabbedPane.unselectedBackground");
- if (background == null)
- background = UIManager.getColor("TabbedPane.background");
- g.setColor(background);
- }
- int[] px, py;
- if (tabPlacement == TOP)
- {
- px = new int[] {x + 6, x + w - 1, x + w -1, x + 2, x + 2};
- py = new int[] {y + 2, y + 2, y + h - 1, y + h -1, y + 6};
- }
- else if (tabPlacement == LEFT)
- {
- px = new int[] {x + 6, x + w - 1, x + w -1, x + 2, x + 2};
- py = new int[] {y + 2, y + 2, y + h - 1, y + h -1, y + 6};
- }
- else if (tabPlacement == BOTTOM)
- {
- px = new int[] {x + 2, x + w - 1, x + w -1, x + 8, x + 2};
- py = new int[] {y, y, y + h - 1, y + h -1, y + h - 7};
- }
- else if (tabPlacement == RIGHT)
- {
- px = new int[] {x + 2, x + w - 7, x + w - 1, x + w - 1, x + 2};
- py = new int[] {y + 2, y + 2, y + 7, y + h -1, y + h - 1};
- }
- else
- throw new AssertionError("Unrecognised 'tabPlacement' argument.");
- g.fillPolygon(px, py, 5);
- hg = g;
- paintHighlightBelowTab();
+ 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);
+ }
}
/**
@@ -408,6 +714,7 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
selectColor = UIManager.getColor("TabbedPane.selected");
selectHighlight = UIManager.getColor("TabbedPane.selectHighlight");
tabAreaBackground = UIManager.getColor("TabbedPane.tabAreaBackground");
+ tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque");
minTabWidth = 0;
}
@@ -487,4 +794,354 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
// 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;
+ }
}