BasicTabbedPaneUI.java [plain text]
package javax.swing.plaf.basic;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.PanelUI;
import javax.swing.plaf.TabbedPaneUI;
import javax.swing.plaf.UIResource;
import javax.swing.text.View;
public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
public class FocusHandler extends FocusAdapter
{
public void focusGained(FocusEvent e)
{
}
public void focusLost(FocusEvent e)
{
}
}
public class MouseHandler extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
int tabCount = tabPane.getTabCount();
if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
{
if (e.getSource() == incrButton)
{
if (++currentScrollLocation >= tabCount)
currentScrollLocation = tabCount - 1;
int width = 0;
for (int i = currentScrollLocation - 1; i < tabCount; i++)
width += rects[i].width;
if (width < viewport.getWidth())
currentScrollLocation--;
else if (! decrButton.isEnabled())
decrButton.setEnabled(true);
tabPane.revalidate();
tabPane.repaint();
return;
}
else if (e.getSource() == decrButton)
{
if (--currentScrollLocation < 0)
currentScrollLocation = 0;
if (currentScrollLocation == 0)
decrButton.setEnabled(false);
else if (! incrButton.isEnabled())
incrButton.setEnabled(true);
tabPane.revalidate();
tabPane.repaint();
return;
}
}
int index = tabForCoordinate(tabPane, x, y);
if (index != -1 && tabPane.isEnabledAt(index))
tabPane.setSelectedIndex(index);
tabPane.revalidate();
tabPane.repaint();
}
}
public class PropertyChangeHandler implements PropertyChangeListener
{
public void propertyChange(PropertyChangeEvent e)
{
if (e.getPropertyName().equals("tabLayoutPolicy"))
{
layoutManager = createLayoutManager();
tabPane.setLayout(layoutManager);
}
else if (e.getPropertyName().equals("tabPlacement")
&& tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
{
incrButton = createIncreaseButton();
decrButton = createDecreaseButton();
}
tabPane.layout();
tabPane.repaint();
}
}
protected class TabbedPaneLayout implements LayoutManager
{
public void addLayoutComponent(String name, Component comp)
{
}
public void calculateLayoutInfo()
{
calculateTabRects(tabPane.getTabPlacement(), tabPane.getTabCount());
if (tabPane.getSelectedIndex() != -1)
{
Component visible = getVisibleComponent();
Insets insets = getContentBorderInsets(tabPane.getTabPlacement());
if (visible != null)
visible.setBounds(contentRect.x + insets.left,
contentRect.y + insets.top,
contentRect.width - insets.left - insets.right,
contentRect.height - insets.top - insets.bottom);
}
}
protected Dimension calculateSize(boolean minimum)
{
int tabPlacement = tabPane.getTabPlacement();
int width = 0;
int height = 0;
int componentHeight = 0;
int componentWidth = 0;
Component c;
Dimension dims;
for (int i = 0; i < tabPane.getTabCount(); i++)
{
c = tabPane.getComponentAt(i);
if (c == null)
continue;
calcRect = c.getBounds();
dims = c.getPreferredSize();
if (dims != null)
{
componentHeight = Math.max(componentHeight, dims.height);
componentWidth = Math.max(componentWidth, dims.width);
}
}
Insets insets = tabPane.getInsets();
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
int min = calculateMaxTabWidth(tabPlacement);
width = Math.max(min, componentWidth);
int tabAreaHeight = preferredTabAreaHeight(tabPlacement, width);
height = tabAreaHeight + componentHeight;
}
else
{
int min = calculateMaxTabHeight(tabPlacement);
height = Math.max(min, componentHeight);
int tabAreaWidth = preferredTabAreaWidth(tabPlacement, height);
width = tabAreaWidth + componentWidth;
}
return new Dimension(width, height);
}
protected void calculateTabRects(int tabPlacement, int tabCount)
{
if (tabCount == 0)
return;
assureRectsCreated(tabCount);
FontMetrics fm = getFontMetrics();
SwingUtilities.calculateInnerArea(tabPane, calcRect);
Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
Insets insets = tabPane.getInsets();
int max = 0;
int runs = 0;
int start = getTabRunIndent(tabPlacement, 1);
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
int maxHeight = calculateMaxTabHeight(tabPlacement);
calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
max = calcRect.width + tabAreaInsets.left + insets.left;
start += tabAreaInsets.left + insets.left;
int width = 0;
int runWidth = start;
for (int i = 0; i < tabCount; i++)
{
width = calculateTabWidth(tabPlacement, i, fm);
if (runWidth + width > max)
{
runWidth = tabAreaInsets.left + insets.left
+ getTabRunIndent(tabPlacement, ++runs);
rects[i] = new Rectangle(runWidth,
insets.top + tabAreaInsets.top,
width, maxHeight);
runWidth += width;
if (runs > tabRuns.length - 1)
expandTabRunsArray();
tabRuns[runs] = i;
}
else
{
rects[i] = new Rectangle(runWidth,
insets.top + tabAreaInsets.top,
width, maxHeight);
runWidth += width;
}
}
runs++;
tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
tabAreaRect.height = runs * maxTabHeight
- (runs - 1) * tabRunOverlay
+ tabAreaInsets.top + tabAreaInsets.bottom;
contentRect.width = tabAreaRect.width;
contentRect.height = tabPane.getHeight() - insets.top
- insets.bottom - tabAreaRect.height;
contentRect.x = insets.left;
tabAreaRect.x = insets.left;
if (tabPlacement == SwingConstants.BOTTOM)
{
contentRect.y = insets.top;
tabAreaRect.y = contentRect.y + contentRect.height;
}
else
{
tabAreaRect.y = insets.top;
contentRect.y = tabAreaRect.y + tabAreaRect.height;
}
}
else
{
int maxWidth = calculateMaxTabWidth(tabPlacement);
calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
max = calcRect.height + tabAreaInsets.top + insets.top;
int height = 0;
start += tabAreaInsets.top + insets.top;
int runHeight = start;
int fontHeight = fm.getHeight();
for (int i = 0; i < tabCount; i++)
{
height = calculateTabHeight(tabPlacement, i, fontHeight);
if (runHeight + height > max)
{
runHeight = tabAreaInsets.top + insets.top
+ getTabRunIndent(tabPlacement, ++runs);
rects[i] = new Rectangle(insets.left + tabAreaInsets.left,
runHeight, maxWidth, height);
runHeight += height;
if (runs > tabRuns.length - 1)
expandTabRunsArray();
tabRuns[runs] = i;
}
else
{
rects[i] = new Rectangle(insets.left + tabAreaInsets.left,
runHeight, maxWidth, height);
runHeight += height;
}
}
runs++;
tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay
+ tabAreaInsets.left + tabAreaInsets.right;
tabAreaRect.height = tabPane.getHeight() - insets.top
- insets.bottom;
tabAreaRect.y = insets.top;
contentRect.width = tabPane.getWidth() - insets.left - insets.right
- tabAreaRect.width;
contentRect.height = tabAreaRect.height;
contentRect.y = insets.top;
if (tabPlacement == SwingConstants.LEFT)
{
tabAreaRect.x = insets.left;
contentRect.x = tabAreaRect.x + tabAreaRect.width;
}
else
{
contentRect.x = insets.left;
tabAreaRect.x = contentRect.x + contentRect.width;
}
}
runCount = runs;
tabRuns[0] = 0;
normalizeTabRuns(tabPlacement, tabCount, start, max);
selectedRun = getRunForTab(tabCount, tabPane.getSelectedIndex());
if (shouldRotateTabRuns(tabPlacement))
rotateTabRuns(tabPlacement, selectedRun);
for (int i = 0; i < runCount; i++)
{
int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
if (first == tabCount)
first = 0;
int last = lastTabInRun(tabCount, i);
if (shouldPadTabRun(tabPlacement, i))
padTabRun(tabPlacement, first, last, max);
if (tabPlacement == SwingConstants.TOP && i > 0)
{
for (int j = first; j <= last; j++)
rects[j].y += (runCount - i) * maxTabHeight
- (runCount - i) * tabRunOverlay;
}
if (tabPlacement == SwingConstants.BOTTOM)
{
int height = tabPane.getBounds().height - insets.bottom
- tabAreaInsets.bottom;
int adjustment;
if (i == 0)
adjustment = height - maxTabHeight;
else
adjustment = height - (runCount - i + 1) * maxTabHeight
- (runCount - i) * tabRunOverlay;
for (int j = first; j <= last; j++)
rects[j].y = adjustment;
}
if (tabPlacement == SwingConstants.LEFT && i > 0)
{
for (int j = first; j <= last; j++)
rects[j].x += (runCount - i) * maxTabWidth
- (runCount - i) * tabRunOverlay;
}
if (tabPlacement == SwingConstants.RIGHT)
{
int width = tabPane.getBounds().width - insets.right
- tabAreaInsets.right;
int adjustment;
if (i == 0)
adjustment = width - maxTabWidth;
else
adjustment = width - (runCount - i + 1) * maxTabWidth
+ (runCount - i) * tabRunOverlay;
for (int j = first; j <= last; j++)
rects[j].x = adjustment;
}
}
padSelectedTab(tabPlacement, tabPane.getSelectedIndex());
}
public void layoutContainer(Container parent)
{
calculateLayoutInfo();
}
public Dimension minimumLayoutSize(Container parent)
{
return calculateSize(false);
}
protected void normalizeTabRuns(int tabPlacement, int tabCount, int start,
int max)
{
Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
if (tabPlacement == SwingUtilities.TOP
|| tabPlacement == SwingUtilities.BOTTOM)
{
for (int i = 1; i < runCount; i++)
{
Rectangle currRun = rects[lastTabInRun(tabCount, i)];
Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))];
int spaceInCurr = currRun.x + currRun.width;
int spaceInNext = nextRun.x + nextRun.width;
int diffNow = spaceInCurr - spaceInNext;
int diffLater = (spaceInCurr - currRun.width)
- (spaceInNext + currRun.width);
while (Math.abs(diffLater) < Math.abs(diffNow)
&& spaceInNext + currRun.width < max)
{
tabRuns[i]--;
spaceInNext += currRun.width;
spaceInCurr -= currRun.width;
currRun = rects[lastTabInRun(tabCount, i)];
diffNow = spaceInCurr - spaceInNext;
diffLater = (spaceInCurr - currRun.width)
- (spaceInNext + currRun.width);
}
int first = lastTabInRun(tabCount, i) + 1;
int last = lastTabInRun(tabCount, getNextTabRun(i));
int currX = tabAreaInsets.left;
for (int j = first; j <= last; j++)
{
rects[j].x = currX;
currX += rects[j].width;
}
}
}
else
{
for (int i = 1; i < runCount; i++)
{
Rectangle currRun = rects[lastTabInRun(tabCount, i)];
Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))];
int spaceInCurr = currRun.y + currRun.height;
int spaceInNext = nextRun.y + nextRun.height;
int diffNow = spaceInCurr - spaceInNext;
int diffLater = (spaceInCurr - currRun.height)
- (spaceInNext + currRun.height);
while (Math.abs(diffLater) < Math.abs(diffNow)
&& spaceInNext + currRun.height < max)
{
tabRuns[i]--;
spaceInNext += currRun.height;
spaceInCurr -= currRun.height;
currRun = rects[lastTabInRun(tabCount, i)];
diffNow = spaceInCurr - spaceInNext;
diffLater = (spaceInCurr - currRun.height)
- (spaceInNext + currRun.height);
}
int first = lastTabInRun(tabCount, i) + 1;
int last = lastTabInRun(tabCount, getNextTabRun(i));
int currY = tabAreaInsets.top;
for (int j = first; j <= last; j++)
{
rects[j].y = currY;
currY += rects[j].height;
}
}
}
}
protected void padSelectedTab(int tabPlacement, int selectedIndex)
{
Insets insets = getSelectedTabPadInsets(tabPlacement);
rects[selectedIndex].x -= insets.left;
rects[selectedIndex].y -= insets.top;
rects[selectedIndex].width += insets.left + insets.right;
rects[selectedIndex].height += insets.top + insets.bottom;
}
protected void padTabRun(int tabPlacement, int start, int end, int max)
{
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
int runWidth = rects[end].x + rects[end].width;
int spaceRemaining = max - runWidth;
int numTabs = end - start + 1;
int spaceAllocated = spaceRemaining / numTabs;
int currX = rects[start].x;
for (int i = start; i <= end; i++)
{
rects[i].x = currX;
rects[i].width += spaceAllocated;
currX += rects[i].width;
if (i == end && rects[i].x + rects[i].width != max)
rects[i].width = max - rects[i].x;
}
}
else
{
int runHeight = rects[end].y + rects[end].height;
int spaceRemaining = max - runHeight;
int numTabs = end - start + 1;
int spaceAllocated = spaceRemaining / numTabs;
int currY = rects[start].y;
for (int i = start; i <= end; i++)
{
rects[i].y = currY;
rects[i].height += spaceAllocated;
currY += rects[i].height;
if (i == end && rects[i].y + rects[i].height != max)
rects[i].height = max - rects[i].y;
}
}
}
public Dimension preferredLayoutSize(Container parent)
{
return calculateSize(false);
}
protected int preferredTabAreaHeight(int tabPlacement, int width)
{
if (tabPane.getTabCount() == 0)
return calculateTabAreaHeight(tabPlacement, 0, 0);
int runs = 0;
int runWidth = 0;
int tabWidth = 0;
FontMetrics fm = getFontMetrics();
Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
Insets insets = tabPane.getInsets();
width -= tabAreaInsets.left + tabAreaInsets.right + insets.left
+ insets.right;
for (int i = 0; i < tabPane.getTabCount(); i++)
{
tabWidth = calculateTabWidth(tabPlacement, i, fm);
if (runWidth + tabWidth > width)
{
runWidth = tabWidth;
runs++;
}
else
runWidth += tabWidth;
}
runs++;
int maxTabHeight = calculateMaxTabHeight(tabPlacement);
int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs,
maxTabHeight);
return tabAreaHeight;
}
protected int preferredTabAreaWidth(int tabPlacement, int height)
{
if (tabPane.getTabCount() == 0)
return calculateTabAreaHeight(tabPlacement, 0, 0);
int runs = 0;
int runHeight = 0;
int tabHeight = 0;
FontMetrics fm = getFontMetrics();
Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
Insets insets = tabPane.getInsets();
height -= tabAreaInsets.top + tabAreaInsets.bottom + insets.top
+ insets.bottom;
int fontHeight = fm.getHeight();
for (int i = 0; i < tabPane.getTabCount(); i++)
{
tabHeight = calculateTabHeight(tabPlacement, i, fontHeight);
if (runHeight + tabHeight > height)
{
runHeight = tabHeight;
runs++;
}
else
runHeight += tabHeight;
}
runs++;
int maxTabWidth = calculateMaxTabWidth(tabPlacement);
int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth);
return tabAreaWidth;
}
protected void rotateTabRuns(int tabPlacement, int selectedRun)
{
if (runCount == 1 || selectedRun == 1 || selectedRun == -1)
return;
int[] newTabRuns = new int[tabRuns.length];
int currentRun = selectedRun;
int i = 1;
do
{
newTabRuns[i] = tabRuns[currentRun];
currentRun = getNextTabRun(currentRun);
i++;
}
while (i < runCount);
if (runCount > 1)
newTabRuns[0] = tabRuns[currentRun];
tabRuns = newTabRuns;
BasicTabbedPaneUI.this.selectedRun = 1;
}
public void removeLayoutComponent(Component comp)
{
}
}
private class TabbedPaneScrollLayout extends TabbedPaneLayout
{
public Dimension preferredLayoutSize(Container parent)
{
return super.calculateSize(true);
}
public Dimension minimumLayoutSize(Container parent)
{
return super.calculateSize(true);
}
protected int preferredTabAreaHeight(int tabPlacement, int width)
{
if (tabPane.getTabCount() == 0)
return calculateTabAreaHeight(tabPlacement, 0, 0);
int runs = 1;
int maxTabHeight = calculateMaxTabHeight(tabPlacement);
int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs,
maxTabHeight);
return tabAreaHeight;
}
protected int preferredTabAreaWidth(int tabPlacement, int height)
{
if (tabPane.getTabCount() == 0)
return calculateTabAreaHeight(tabPlacement, 0, 0);
int runs = 1;
int maxTabWidth = calculateMaxTabWidth(tabPlacement);
int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth);
return tabAreaWidth;
}
protected void calculateTabRects(int tabPlacement, int tabCount)
{
if (tabCount == 0)
return;
assureRectsCreated(tabCount);
FontMetrics fm = getFontMetrics();
SwingUtilities.calculateInnerArea(tabPane, calcRect);
Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
Insets insets = tabPane.getInsets();
int max = 0;
int runs = 1;
int start = 0;
int top = 0;
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
int maxHeight = calculateMaxTabHeight(tabPlacement);
calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
max = calcRect.width + tabAreaInsets.left + insets.left;
start = tabAreaInsets.left + insets.left;
int width = 0;
int runWidth = start;
top = insets.top + tabAreaInsets.top;
for (int i = 0; i < tabCount; i++)
{
width = calculateTabWidth(tabPlacement, i, fm);
rects[i] = new Rectangle(runWidth, top, width, maxHeight);
runWidth += width;
}
tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
tabAreaRect.height = runs * maxTabHeight
- (runs - 1) * tabRunOverlay
+ tabAreaInsets.top + tabAreaInsets.bottom;
contentRect.width = tabAreaRect.width;
contentRect.height = tabPane.getHeight() - insets.top
- insets.bottom - tabAreaRect.height;
contentRect.x = insets.left;
tabAreaRect.x = insets.left;
if (tabPlacement == SwingConstants.BOTTOM)
{
contentRect.y = insets.top;
tabAreaRect.y = contentRect.y + contentRect.height;
}
else
{
tabAreaRect.y = insets.top;
contentRect.y = tabAreaRect.y + tabAreaRect.height;
}
}
else
{
int maxWidth = calculateMaxTabWidth(tabPlacement);
calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
max = calcRect.height + tabAreaInsets.top;
int height = 0;
start = tabAreaInsets.top + insets.top;
int runHeight = start;
int fontHeight = fm.getHeight();
top = insets.left + tabAreaInsets.left;
for (int i = 0; i < tabCount; i++)
{
height = calculateTabHeight(tabPlacement, i, fontHeight);
rects[i] = new Rectangle(top, runHeight, maxWidth, height);
runHeight += height;
}
tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay
+ tabAreaInsets.left + tabAreaInsets.right;
tabAreaRect.height = tabPane.getHeight() - insets.top
- insets.bottom;
tabAreaRect.y = insets.top;
contentRect.width = tabPane.getWidth() - insets.left - insets.right
- tabAreaRect.width;
contentRect.height = tabAreaRect.height;
contentRect.y = insets.top;
if (tabPlacement == SwingConstants.LEFT)
{
tabAreaRect.x = insets.left;
contentRect.x = tabAreaRect.x + tabAreaRect.width;
}
else
{
contentRect.x = insets.left;
tabAreaRect.x = contentRect.x + contentRect.width;
}
}
runCount = runs;
padSelectedTab(tabPlacement, tabPane.getSelectedIndex());
}
public void layoutContainer(Container pane)
{
super.layoutContainer(pane);
int tabCount = tabPane.getTabCount();
Point p = null;
if (tabCount == 0)
return;
int tabPlacement = tabPane.getTabPlacement();
incrButton.hide();
decrButton.hide();
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
if (tabAreaRect.x + tabAreaRect.width < rects[tabCount - 1].x
+ rects[tabCount - 1].width)
{
Dimension incrDims = incrButton.getPreferredSize();
Dimension decrDims = decrButton.getPreferredSize();
decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
- incrDims.width - decrDims.width,
tabAreaRect.y, decrDims.width,
tabAreaRect.height);
incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
- incrDims.width, tabAreaRect.y,
decrDims.width, tabAreaRect.height);
tabAreaRect.width -= decrDims.width + incrDims.width;
incrButton.show();
decrButton.show();
}
}
if (tabPlacement == SwingConstants.LEFT
|| tabPlacement == SwingConstants.RIGHT)
{
if (tabAreaRect.y + tabAreaRect.height < rects[tabCount - 1].y
+ rects[tabCount - 1].height)
{
Dimension incrDims = incrButton.getPreferredSize();
Dimension decrDims = decrButton.getPreferredSize();
decrButton.setBounds(tabAreaRect.x,
tabAreaRect.y + tabAreaRect.height
- incrDims.height - decrDims.height,
tabAreaRect.width, decrDims.height);
incrButton.setBounds(tabAreaRect.x,
tabAreaRect.y + tabAreaRect.height
- incrDims.height, tabAreaRect.width,
incrDims.height);
tabAreaRect.height -= decrDims.height + incrDims.height;
incrButton.show();
decrButton.show();
}
}
viewport.setBounds(tabAreaRect.x, tabAreaRect.y, tabAreaRect.width,
tabAreaRect.height);
int tabC = tabPane.getTabCount() - 1;
if (tabCount > 0)
{
int w = Math.max(rects[tabC].width + rects[tabC].x, tabAreaRect.width);
int h = Math.max(rects[tabC].height, tabAreaRect.height);
p = findPointForIndex(currentScrollLocation);
panel.setSize(w + p.x, h + p.y);
}
viewport.setViewPosition(p);
viewport.repaint();
}
}
public class TabSelectionHandler implements ChangeListener
{
public void stateChanged(ChangeEvent e)
{
selectedRun = getRunForTab(tabPane.getTabCount(),
tabPane.getSelectedIndex());
tabPane.revalidate();
tabPane.repaint();
}
}
private class ScrollingPanel extends JPanel
{
private class ScrollingPanelUI extends BasicPanelUI
{
public void paint(Graphics g, JComponent c)
{
paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
}
}
public void updateUI()
{
setUI((PanelUI) new ScrollingPanelUI());
}
}
private class ScrollingViewport extends JViewport implements UIResource
{
}
private static class ScrollingButton extends BasicArrowButton
implements UIResource
{
public ScrollingButton(int dir)
{
super(dir);
}
}
private transient ScrollingButton incrButton;
private transient ScrollingButton decrButton;
private transient ScrollingViewport viewport;
private transient ScrollingPanel panel;
private transient int currentScrollLocation;
protected Rectangle calcRect;
protected Rectangle[] rects;
protected Insets contentBorderInsets;
protected Insets selectedTabPadInsets;
protected Insets tabAreaInsets;
protected Insets tabInsets;
protected Color darkShadow;
protected Color focus;
protected Color highlight;
protected Color lightHighlight;
protected Color shadow;
protected int maxTabHeight;
protected int maxTabWidth;
protected int runCount;
protected int selectedRun;
protected int tabRunOverlay;
protected int textIconGap;
protected int[] tabRuns;
protected KeyStroke downKey;
protected KeyStroke leftKey;
protected KeyStroke rightKey;
protected KeyStroke upKey;
protected FocusListener focusListener;
protected MouseListener mouseListener;
protected PropertyChangeListener propertyChangeListener;
protected ChangeListener tabChangeListener;
protected JTabbedPane tabPane;
private transient LayoutManager layoutManager;
private transient Rectangle tabAreaRect;
private transient Rectangle contentRect;
public BasicTabbedPaneUI()
{
super();
}
private ScrollingButton createIncreaseButton()
{
if (incrButton == null)
incrButton = new ScrollingButton(SwingConstants.NORTH);
if (tabPane.getTabPlacement() == SwingConstants.TOP
|| tabPane.getTabPlacement() == SwingConstants.BOTTOM)
incrButton.setDirection(SwingConstants.EAST);
else
incrButton.setDirection(SwingConstants.SOUTH);
return incrButton;
}
private ScrollingButton createDecreaseButton()
{
if (decrButton == null)
decrButton = new ScrollingButton(SwingConstants.SOUTH);
if (tabPane.getTabPlacement() == SwingConstants.TOP
|| tabPane.getTabPlacement() == SwingConstants.BOTTOM)
decrButton.setDirection(SwingConstants.WEST);
else
decrButton.setDirection(SwingConstants.NORTH);
return decrButton;
}
private Point findPointForIndex(int index)
{
int tabPlacement = tabPane.getTabPlacement();
int selectedIndex = tabPane.getSelectedIndex();
Insets insets = getSelectedTabPadInsets(tabPlacement);
int w = 0;
int h = 0;
if (tabPlacement == TOP || tabPlacement == BOTTOM)
{
if (index > 0)
{
w += rects[index - 1].x + rects[index - 1].width;
if (index > selectedIndex)
w -= insets.left + insets.right;
}
}
else
{
if (index > 0)
{
h += rects[index - 1].y + rects[index - 1].height;
if (index > selectedIndex)
h -= insets.top + insets.bottom;
}
}
Point p = new Point(w, h);
return p;
}
public static ComponentUI createUI(JComponent c)
{
return new BasicTabbedPaneUI();
}
public void installUI(JComponent c)
{
super.installUI(c);
if (c instanceof JTabbedPane)
{
tabPane = (JTabbedPane) c;
installComponents();
installDefaults();
installListeners();
installKeyboardActions();
layoutManager = createLayoutManager();
tabPane.setLayout(layoutManager);
tabPane.layout();
}
}
public void uninstallUI(JComponent c)
{
layoutManager = null;
uninstallKeyboardActions();
uninstallListeners();
uninstallDefaults();
uninstallComponents();
tabPane = null;
}
protected LayoutManager createLayoutManager()
{
if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
return new TabbedPaneLayout();
else
{
incrButton = createIncreaseButton();
decrButton = createDecreaseButton();
viewport = new ScrollingViewport();
viewport.setLayout(null);
panel = new ScrollingPanel();
viewport.setView(panel);
tabPane.add(incrButton);
tabPane.add(decrButton);
tabPane.add(viewport);
currentScrollLocation = 0;
decrButton.setEnabled(false);
panel.addMouseListener(mouseListener);
incrButton.addMouseListener(mouseListener);
decrButton.addMouseListener(mouseListener);
viewport.setBackground(Color.LIGHT_GRAY);
return new TabbedPaneScrollLayout();
}
}
protected void installComponents()
{
}
protected void uninstallComponents()
{
}
protected void installDefaults()
{
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
tabPane.setFont(defaults.getFont("TabbedPane.font"));
tabPane.setForeground(defaults.getColor("TabbedPane.foreground"));
tabPane.setBackground(defaults.getColor("TabbedPane.background"));
tabPane.setOpaque(true);
highlight = defaults.getColor("TabbedPane.highlight");
lightHighlight = defaults.getColor("TabbedPane.lightHighlight");
shadow = defaults.getColor("TabbedPane.shadow");
darkShadow = defaults.getColor("TabbedPane.darkShadow");
focus = defaults.getColor("TabbedPane.focus");
textIconGap = defaults.getInt("TabbedPane.textIconGap");
tabRunOverlay = defaults.getInt("TabbedPane.tabRunOverlay");
tabInsets = defaults.getInsets("TabbedPane.tabbedPaneTabInsets");
selectedTabPadInsets = defaults.getInsets("TabbedPane.tabbedPaneTabPadInsets");
tabAreaInsets = defaults.getInsets("TabbedPane.tabbedPaneTabAreaInsets");
contentBorderInsets = defaults.getInsets("TabbedPane.tabbedPaneContentBorderInsets");
calcRect = new Rectangle();
tabRuns = new int[10];
tabAreaRect = new Rectangle();
contentRect = new Rectangle();
}
protected void uninstallDefaults()
{
calcRect = null;
tabAreaRect = null;
contentRect = null;
tabRuns = null;
contentBorderInsets = null;
tabAreaInsets = null;
selectedTabPadInsets = null;
tabInsets = null;
focus = null;
darkShadow = null;
shadow = null;
lightHighlight = null;
highlight = null;
tabPane.setBackground(null);
tabPane.setForeground(null);
tabPane.setFont(null);
}
protected void installListeners()
{
mouseListener = createMouseListener();
tabChangeListener = createChangeListener();
propertyChangeListener = createPropertyChangeListener();
focusListener = createFocusListener();
tabPane.addMouseListener(mouseListener);
tabPane.addChangeListener(tabChangeListener);
tabPane.addPropertyChangeListener(propertyChangeListener);
tabPane.addFocusListener(focusListener);
}
protected void uninstallListeners()
{
tabPane.removeFocusListener(focusListener);
tabPane.removePropertyChangeListener(propertyChangeListener);
tabPane.removeChangeListener(tabChangeListener);
tabPane.removeMouseListener(mouseListener);
focusListener = null;
propertyChangeListener = null;
tabChangeListener = null;
mouseListener = null;
}
protected MouseListener createMouseListener()
{
return new MouseHandler();
}
protected FocusListener createFocusListener()
{
return new FocusHandler();
}
protected ChangeListener createChangeListener()
{
return new TabSelectionHandler();
}
protected PropertyChangeListener createPropertyChangeListener()
{
return new PropertyChangeHandler();
}
protected void installKeyboardActions()
{
}
protected void uninstallKeyboardActions()
{
}
public Dimension getPreferredSize(JComponent c)
{
return layoutManager.preferredLayoutSize(tabPane);
}
public Dimension getMinimumSize(JComponent c)
{
return layoutManager.minimumLayoutSize(tabPane);
}
public Dimension getMaximumSize(JComponent c)
{
return getPreferredSize(c);
}
public void paint(Graphics g, JComponent c)
{
if (tabPane.getTabCount() == 0)
return;
if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
paintContentBorder(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
}
protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex)
{
Rectangle ir = new Rectangle();
Rectangle tr = new Rectangle();
boolean isScroll = tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT;
int tabCount = tabPane.getTabCount();
int currRun = 1;
if (tabCount < 1)
return;
if (runCount > 1)
currRun = 0;
for (int i = 0; i < runCount; i++)
{
int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1;
if (isScroll)
first = currentScrollLocation;
else if (first == tabCount)
first = 0;
int last = lastTabInRun(tabCount, currRun);
if (isScroll)
{
for (int k = first; k < tabCount; k++)
{
if (rects[k].x + rects[k].width - rects[first].x > viewport
.getWidth())
{
last = k;
break;
}
}
}
for (int j = first; j <= last; j++)
{
if (j != selectedIndex || isScroll)
paintTab(g, tabPlacement, rects, j, ir, tr);
}
currRun = getPreviousTabRun(currRun);
}
if (! isScroll)
paintTab(g, tabPlacement, rects, selectedIndex, ir, tr);
}
protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects,
int tabIndex, Rectangle iconRect, Rectangle textRect)
{
FontMetrics fm = getFontMetrics();
Icon icon = getIconForTab(tabIndex);
String title = tabPane.getTitleAt(tabIndex);
boolean isSelected = tabIndex == tabPane.getSelectedIndex();
calcRect = getTabBounds(tabPane, tabIndex);
int x = calcRect.x;
int y = calcRect.y;
int w = calcRect.width;
int h = calcRect.height;
if (getRunForTab(tabPane.getTabCount(), tabIndex) == 1)
{
Insets insets = getTabAreaInsets(tabPlacement);
switch (tabPlacement)
{
case TOP:
h += insets.bottom;
break;
case LEFT:
w += insets.right;
break;
case BOTTOM:
y -= insets.top;
h += insets.top;
break;
case RIGHT:
x -= insets.left;
w += insets.left;
break;
}
}
layoutLabel(tabPlacement, fm, tabIndex, title, icon, calcRect, iconRect,
textRect, isSelected);
paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected);
paintTabBorder(g, tabPlacement, tabIndex, x, y, w, h, isSelected);
if (icon != null)
paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected);
if (title != null && ! title.equals(""))
paintText(g, tabPlacement, tabPane.getFont(), fm, tabIndex, title,
textRect, isSelected);
}
protected void layoutLabel(int tabPlacement, FontMetrics metrics,
int tabIndex, String title, Icon icon,
Rectangle tabRect, Rectangle iconRect,
Rectangle textRect, boolean isSelected)
{
SwingUtilities.layoutCompoundLabel(metrics, title, icon,
SwingConstants.CENTER,
SwingConstants.CENTER,
SwingConstants.CENTER,
SwingConstants.CENTER, tabRect,
iconRect, textRect, textIconGap);
int shiftX = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
int shiftY = getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
iconRect.x += shiftX;
iconRect.y += shiftY;
textRect.x += shiftX;
textRect.y += shiftY;
}
protected void paintIcon(Graphics g, int tabPlacement, int tabIndex,
Icon icon, Rectangle iconRect, boolean isSelected)
{
icon.paintIcon(tabPane, g, iconRect.x, iconRect.y);
}
protected void paintText(Graphics g, int tabPlacement, Font font,
FontMetrics metrics, int tabIndex, String title,
Rectangle textRect, boolean isSelected)
{
View textView = getTextViewForTab(tabIndex);
if (textView != null)
{
textView.paint(g, textRect);
return;
}
Color fg = tabPane.getForegroundAt(tabIndex);
if (fg == null)
fg = tabPane.getForeground();
Color bg = tabPane.getBackgroundAt(tabIndex);
if (bg == null)
bg = tabPane.getBackground();
Color saved_color = g.getColor();
Font f = g.getFont();
g.setFont(font);
if (tabPane.isEnabledAt(tabIndex))
{
g.setColor(fg);
int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
if (mnemIndex != -1)
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
textRect.x,
textRect.y
+ metrics.getAscent());
else
g.drawString(title, textRect.x, textRect.y + metrics.getAscent());
}
else
{
g.setColor(bg.brighter());
int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
if (mnemIndex != -1)
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
textRect.x, textRect.y);
else
g.drawString(title, textRect.x, textRect.y);
g.setColor(bg.darker());
if (mnemIndex != -1)
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex,
textRect.x + 1,
textRect.y + 1);
else
g.drawString(title, textRect.x + 1, textRect.y + 1);
}
g.setColor(saved_color);
g.setFont(f);
}
protected int getTabLabelShiftX(int tabPlacement, int tabIndex,
boolean isSelected)
{
return 0;
}
protected int getTabLabelShiftY(int tabPlacement, int tabIndex,
boolean isSelected)
{
return 0;
}
protected void paintFocusIndicator(Graphics g, int tabPlacement,
Rectangle[] rects, int tabIndex,
Rectangle iconRect, Rectangle textRect,
boolean isSelected)
{
Color saved = g.getColor();
calcRect = iconRect.union(textRect);
g.setColor(focus);
g.drawRect(calcRect.x, calcRect.y, calcRect.width, calcRect.height);
g.setColor(saved);
}
protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
int x, int y, int w, int h, boolean isSelected)
{
Color saved = g.getColor();
if (! isSelected || tabPlacement != SwingConstants.TOP)
{
g.setColor(shadow);
g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
g.setColor(darkShadow);
g.drawLine(x, y + h, x + w, y + h);
}
if (! isSelected || tabPlacement != SwingConstants.LEFT)
{
g.setColor(darkShadow);
g.drawLine(x + w, y, x + w, y + h);
g.setColor(shadow);
g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
}
if (! isSelected || tabPlacement != SwingConstants.RIGHT)
{
g.setColor(lightHighlight);
g.drawLine(x, y, x, y + h);
}
if (! isSelected || tabPlacement != SwingConstants.BOTTOM)
{
g.setColor(lightHighlight);
g.drawLine(x, y, x + w, y);
}
g.setColor(saved);
}
protected void paintTabBackground(Graphics g, int tabPlacement,
int tabIndex, int x, int y, int w, int h,
boolean isSelected)
{
Color saved = g.getColor();
if (isSelected)
g.setColor(Color.LIGHT_GRAY);
else
{
Color bg = tabPane.getBackgroundAt(tabIndex);
if (bg == null)
bg = Color.GRAY;
g.setColor(bg);
}
g.fillRect(x, y, w, h);
g.setColor(saved);
}
protected void paintContentBorder(Graphics g, int tabPlacement,
int selectedIndex)
{
Insets insets = getContentBorderInsets(tabPlacement);
int x = contentRect.x;
int y = contentRect.y;
int w = contentRect.width;
int h = contentRect.height;
paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h);
paintContentBorderLeftEdge(g, tabPlacement, selectedIndex, x, y, w, h);
paintContentBorderBottomEdge(g, tabPlacement, selectedIndex, x, y, w, h);
paintContentBorderRightEdge(g, tabPlacement, selectedIndex, x, y, w, h);
}
protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
int selectedIndex, int x, int y,
int w, int h)
{
Color saved = g.getColor();
g.setColor(lightHighlight);
int startgap = rects[selectedIndex].x;
int endgap = rects[selectedIndex].x + rects[selectedIndex].width;
int diff = 0;
if (tabPlacement == SwingConstants.TOP)
{
if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
{
Point p = findPointForIndex(currentScrollLocation);
diff = p.x;
}
g.drawLine(x, y, startgap - diff, y);
g.drawLine(endgap - diff, y, x + w, y);
}
else
g.drawLine(x, y, x + w, y);
g.setColor(saved);
}
protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement,
int selectedIndex, int x, int y,
int w, int h)
{
Color saved = g.getColor();
g.setColor(lightHighlight);
int startgap = rects[selectedIndex].y;
int endgap = rects[selectedIndex].y + rects[selectedIndex].height;
int diff = 0;
if (tabPlacement == SwingConstants.LEFT)
{
if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
{
Point p = findPointForIndex(currentScrollLocation);
diff = p.y;
}
g.drawLine(x, y, x, startgap - diff);
g.drawLine(x, endgap - diff, x, y + h);
}
else
g.drawLine(x, y, x, y + h);
g.setColor(saved);
}
protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement,
int selectedIndex, int x, int y,
int w, int h)
{
Color saved = g.getColor();
int startgap = rects[selectedIndex].x;
int endgap = rects[selectedIndex].x + rects[selectedIndex].width;
int diff = 0;
if (tabPlacement == SwingConstants.BOTTOM)
{
if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
{
Point p = findPointForIndex(currentScrollLocation);
diff = p.x;
}
g.setColor(shadow);
g.drawLine(x + 1, y + h - 1, startgap - diff, y + h - 1);
g.drawLine(endgap - diff, y + h - 1, x + w - 1, y + h - 1);
g.setColor(darkShadow);
g.drawLine(x, y + h, startgap - diff, y + h);
g.drawLine(endgap - diff, y + h, x + w, y + h);
}
else
{
g.setColor(shadow);
g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
g.setColor(darkShadow);
g.drawLine(x, y + h, x + w, y + h);
}
g.setColor(saved);
}
protected void paintContentBorderRightEdge(Graphics g, int tabPlacement,
int selectedIndex, int x, int y,
int w, int h)
{
Color saved = g.getColor();
int startgap = rects[selectedIndex].y;
int endgap = rects[selectedIndex].y + rects[selectedIndex].height;
int diff = 0;
if (tabPlacement == SwingConstants.RIGHT)
{
if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
{
Point p = findPointForIndex(currentScrollLocation);
diff = p.y;
}
g.setColor(shadow);
g.drawLine(x + w - 1, y + 1, x + w - 1, startgap - diff);
g.drawLine(x + w - 1, endgap - diff, x + w - 1, y + h - 1);
g.setColor(darkShadow);
g.drawLine(x + w, y, x + w, startgap - diff);
g.drawLine(x + w, endgap - diff, x + w, y + h);
}
else
{
g.setColor(shadow);
g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
g.setColor(darkShadow);
g.drawLine(x + w, y, x + w, y + h);
}
g.setColor(saved);
}
public Rectangle getTabBounds(JTabbedPane pane, int i)
{
return rects[i];
}
public int getTabRunCount(JTabbedPane pane)
{
return runCount;
}
public int tabForCoordinate(JTabbedPane pane, int x, int y)
{
Point p = new Point(x, y);
int tabCount = tabPane.getTabCount();
int currRun = 1;
for (int i = 0; i < runCount; i++)
{
int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1;
if (first == tabCount)
first = 0;
int last = lastTabInRun(tabCount, currRun);
for (int j = first; j <= last; j++)
{
if (getTabBounds(pane, j).contains(p))
return j;
}
currRun = getNextTabRun(currRun);
}
return -1;
}
protected Rectangle getTabBounds(int tabIndex, Rectangle dest)
{
dest.setBounds(getTabBounds(tabPane, tabIndex));
return dest;
}
protected Component getVisibleComponent()
{
return tabPane.getComponentAt(tabPane.getSelectedIndex());
}
protected void setVisibleComponent(Component component)
{
component.setVisible(true);
tabPane.setSelectedComponent(component);
}
protected void assureRectsCreated(int tabCount)
{
if (rects == null)
rects = new Rectangle[tabCount];
if (tabCount == rects.length)
return;
else
{
int numToCopy = Math.min(tabCount, rects.length);
Rectangle[] tmp = new Rectangle[tabCount];
System.arraycopy(rects, 0, tmp, 0, numToCopy);
rects = tmp;
}
}
protected void expandTabRunsArray()
{
if (tabRuns == null)
tabRuns = new int[10];
else
{
int[] newRuns = new int[tabRuns.length + 10];
System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length);
tabRuns = newRuns;
}
}
protected int getRunForTab(int tabCount, int tabIndex)
{
if (runCount == 1 && tabIndex < tabCount && tabIndex >= 0)
return 1;
for (int i = 0; i < runCount; i++)
{
int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
if (first == tabCount)
first = 0;
int last = lastTabInRun(tabCount, i);
if (last >= tabIndex && first <= tabIndex)
return i;
}
return -1;
}
protected int lastTabInRun(int tabCount, int run)
{
if (tabRuns[run] == 0)
return tabCount - 1;
else
return tabRuns[run] - 1;
}
protected int getTabRunOverlay(int tabPlacement)
{
return tabRunOverlay;
}
protected int getTabRunIndent(int tabPlacement, int run)
{
return 0;
}
protected boolean shouldPadTabRun(int tabPlacement, int run)
{
return true;
}
protected boolean shouldRotateTabRuns(int tabPlacement)
{
return true;
}
protected Icon getIconForTab(int tabIndex)
{
if (tabPane.isEnabledAt(tabIndex))
return tabPane.getIconAt(tabIndex);
else
return tabPane.getDisabledIconAt(tabIndex);
}
protected View getTextViewForTab(int tabIndex)
{
return null;
}
protected int calculateTabHeight(int tabPlacement, int tabIndex,
int fontHeight)
{
Icon icon = getIconForTab(tabIndex);
Insets insets = getTabInsets(tabPlacement, tabIndex);
if (icon != null)
{
Rectangle vr = new Rectangle();
Rectangle ir = new Rectangle();
Rectangle tr = new Rectangle();
layoutLabel(tabPlacement, getFontMetrics(), tabIndex,
tabPane.getTitleAt(tabIndex), icon, vr, ir, tr,
tabIndex == tabPane.getSelectedIndex());
calcRect = tr.union(ir);
}
else
calcRect.height = fontHeight;
calcRect.height += insets.top + insets.bottom;
return calcRect.height;
}
protected int calculateMaxTabHeight(int tabPlacement)
{
maxTabHeight = 0;
FontMetrics fm = getFontMetrics();
int fontHeight = fm.getHeight();
for (int i = 0; i < tabPane.getTabCount(); i++)
maxTabHeight = Math.max(calculateTabHeight(tabPlacement, i, fontHeight),
maxTabHeight);
return maxTabHeight;
}
protected int calculateTabWidth(int tabPlacement, int tabIndex,
FontMetrics metrics)
{
Icon icon = getIconForTab(tabIndex);
Insets insets = getTabInsets(tabPlacement, tabIndex);
if (icon != null)
{
Rectangle vr = new Rectangle();
Rectangle ir = new Rectangle();
Rectangle tr = new Rectangle();
layoutLabel(tabPlacement, getFontMetrics(), tabIndex,
tabPane.getTitleAt(tabIndex), icon, vr, ir, tr,
tabIndex == tabPane.getSelectedIndex());
calcRect = tr.union(ir);
}
else
calcRect.width = metrics.stringWidth(tabPane.getTitleAt(tabIndex));
calcRect.width += insets.left + insets.right;
return calcRect.width;
}
protected int calculateMaxTabWidth(int tabPlacement)
{
maxTabWidth = 0;
FontMetrics fm = getFontMetrics();
for (int i = 0; i < tabPane.getTabCount(); i++)
maxTabWidth = Math.max(calculateTabWidth(tabPlacement, i, fm),
maxTabWidth);
return maxTabWidth;
}
protected int calculateTabAreaHeight(int tabPlacement, int horizRunCount,
int maxTabHeight)
{
Insets insets = getTabAreaInsets(tabPlacement);
int tabAreaHeight = horizRunCount * maxTabHeight
- (horizRunCount - 1) * tabRunOverlay;
tabAreaHeight += insets.top + insets.bottom;
return tabAreaHeight;
}
protected int calculateTabAreaWidth(int tabPlacement, int vertRunCount,
int maxTabWidth)
{
Insets insets = getTabAreaInsets(tabPlacement);
int tabAreaWidth = vertRunCount * maxTabWidth
- (vertRunCount - 1) * tabRunOverlay;
tabAreaWidth += insets.left + insets.right;
return tabAreaWidth;
}
protected Insets getTabInsets(int tabPlacement, int tabIndex)
{
Insets target = new Insets(0, 0, 0, 0);
rotateInsets(tabInsets, target, tabPlacement);
return target;
}
protected Insets getSelectedTabPadInsets(int tabPlacement)
{
Insets target = new Insets(0, 0, 0, 0);
rotateInsets(selectedTabPadInsets, target, tabPlacement);
return target;
}
protected Insets getTabAreaInsets(int tabPlacement)
{
Insets target = new Insets(0, 0, 0, 0);
rotateInsets(tabAreaInsets, target, tabPlacement);
return target;
}
protected Insets getContentBorderInsets(int tabPlacement)
{
Insets target = new Insets(0, 0, 0, 0);
rotateInsets(contentBorderInsets, target, tabPlacement);
return target;
}
protected FontMetrics getFontMetrics()
{
FontMetrics fm = tabPane.getToolkit().getFontMetrics(tabPane.getFont());
return fm;
}
protected void navigateSelectedTab(int direction)
{
int tabPlacement = tabPane.getTabPlacement();
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
if (direction == SwingConstants.WEST)
selectPreviousTabInRun(tabPane.getSelectedIndex());
else if (direction == SwingConstants.EAST)
selectNextTabInRun(tabPane.getSelectedIndex());
else
{
int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
tabPane.getSelectedIndex(),
(tabPlacement == SwingConstants.RIGHT)
? true : false);
selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
offset);
}
}
if (tabPlacement == SwingConstants.LEFT
|| tabPlacement == SwingConstants.RIGHT)
{
if (direction == SwingConstants.NORTH)
selectPreviousTabInRun(tabPane.getSelectedIndex());
else if (direction == SwingConstants.SOUTH)
selectNextTabInRun(tabPane.getSelectedIndex());
else
{
int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
tabPane.getSelectedIndex(),
(tabPlacement == SwingConstants.RIGHT)
? true : false);
selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
offset);
}
}
}
protected void selectNextTabInRun(int current)
{
tabPane.setSelectedIndex(getNextTabIndexInRun(tabPane.getTabCount(),
current));
}
protected void selectPreviousTabInRun(int current)
{
tabPane.setSelectedIndex(getPreviousTabIndexInRun(tabPane.getTabCount(),
current));
}
protected void selectNextTab(int current)
{
tabPane.setSelectedIndex(getNextTabIndex(current));
}
protected void selectPreviousTab(int current)
{
tabPane.setSelectedIndex(getPreviousTabIndex(current));
}
protected void selectAdjacentRunTab(int tabPlacement, int tabIndex,
int offset)
{
int x = rects[tabIndex].x + rects[tabIndex].width / 2;
int y = rects[tabIndex].y + rects[tabIndex].height / 2;
switch (tabPlacement)
{
case SwingConstants.TOP:
case SwingConstants.BOTTOM:
y += offset;
break;
case SwingConstants.RIGHT:
case SwingConstants.LEFT:
x += offset;
break;
}
int index = tabForCoordinate(tabPane, x, y);
if (index != -1)
tabPane.setSelectedIndex(index);
}
protected int getTabRunOffset(int tabPlacement, int tabCount, int tabIndex,
boolean forward)
{
int currRun = getRunForTab(tabCount, tabIndex);
int offset;
int nextRun = (forward) ? getNextTabRun(currRun) : getPreviousTabRun(currRun);
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
offset = rects[lastTabInRun(tabCount, nextRun)].y
- rects[lastTabInRun(tabCount, currRun)].y;
else
offset = rects[lastTabInRun(tabCount, nextRun)].x
- rects[lastTabInRun(tabCount, currRun)].x;
return offset;
}
protected int getPreviousTabIndex(int base)
{
base--;
if (base < 0)
return tabPane.getTabCount() - 1;
return base;
}
protected int getNextTabIndex(int base)
{
base++;
if (base == tabPane.getTabCount())
return 0;
return base;
}
protected int getNextTabIndexInRun(int tabCount, int base)
{
int index = getNextTabIndex(base);
int run = getRunForTab(tabCount, base);
if (index == lastTabInRun(tabCount, run) + 1)
index = lastTabInRun(tabCount, getPreviousTabRun(run)) + 1;
return getNextTabIndex(base);
}
protected int getPreviousTabIndexInRun(int tabCount, int base)
{
int index = getPreviousTabIndex(base);
int run = getRunForTab(tabCount, base);
if (index == lastTabInRun(tabCount, getPreviousTabRun(run)))
index = lastTabInRun(tabCount, run);
return getPreviousTabIndex(base);
}
protected int getPreviousTabRun(int baseRun)
{
if (getTabRunCount(tabPane) == 1)
return 1;
int prevRun = --baseRun;
if (prevRun < 0)
prevRun = getTabRunCount(tabPane) - 1;
return prevRun;
}
protected int getNextTabRun(int baseRun)
{
if (getTabRunCount(tabPane) == 1)
return 1;
int nextRun = ++baseRun;
if (nextRun == getTabRunCount(tabPane))
nextRun = 0;
return nextRun;
}
protected static void rotateInsets(Insets topInsets, Insets targetInsets,
int targetPlacement)
{
switch (targetPlacement)
{
case SwingConstants.TOP:
targetInsets.top = topInsets.top;
targetInsets.left = topInsets.left;
targetInsets.right = topInsets.right;
targetInsets.bottom = topInsets.bottom;
break;
case SwingConstants.LEFT:
targetInsets.left = topInsets.top;
targetInsets.top = topInsets.left;
targetInsets.right = topInsets.bottom;
targetInsets.bottom = topInsets.right;
break;
case SwingConstants.BOTTOM:
targetInsets.top = topInsets.bottom;
targetInsets.bottom = topInsets.top;
targetInsets.left = topInsets.left;
targetInsets.right = topInsets.right;
break;
case SwingConstants.RIGHT:
targetInsets.top = topInsets.left;
targetInsets.left = topInsets.bottom;
targetInsets.bottom = topInsets.right;
targetInsets.right = topInsets.top;
break;
}
}
}