📄 tabbedpaneui.java
字号:
}
private void ensureCurrentLayout()
{
if (!tabPane.isValid())
{
tabPane.validate();
}
/* If tabPane doesn't have a peer yet, the validate() call will
* silently fail. We handle that by forcing a layout if tabPane
* is still invalid. See bug 4237677.
*/
if (!tabPane.isValid())
{
TabbedPaneLayout layout= (TabbedPaneLayout) tabPane.getLayout();
layout.calculateLayoutInfo();
}
}
// TabbedPaneUI methods
/**
* Returns the bounds of the specified tab index. The bounds are
* with respect to the JTabbedPane's coordinate space.
*/
public Rectangle getTabBounds(JTabbedPane pane, int i)
{
ensureCurrentLayout();
Rectangle tabRect= new Rectangle();
return getTabBounds(i, tabRect);
}
public int getTabRunCount(JTabbedPane pane)
{
ensureCurrentLayout();
return runCount;
}
/** Returns the tab index which intersects the specified point
* in the JTabbedPane's coordinate space.
*/
public int tabForCoordinate(JTabbedPane pane, int x, int y)
{
ensureCurrentLayout();
Point p= new Point(x, y);
if (scrollableTabLayoutEnabled())
{
translatePointToTabPanel(x, y, p);
}
int tabCount= tabPane.getTabCount();
for (int i= 0; i < tabCount; i++)
{
if (rects[i].contains(p.x, p.y))
{
return i;
}
}
return -1;
}
/**
* Returns the bounds of the specified tab in the coordinate space
* of the JTabbedPane component. This is required because the tab rects
* are by default defined in the coordinate space of the component where
* they are rendered, which could be the JTabbedPane
* (for WRAP_TAB_LAYOUT) or a ScrollableTabPanel (SCROLL_TAB_LAYOUT).
* This method should be used whenever the tab rectangle must be relative
* to the JTabbedPane itself and the result should be placed in a
* designated Rectangle object (rather than instantiating and returning
* a new Rectangle each time). The tab index parameter must be a valid
* tabbed pane tab index (0 to tab count - 1, inclusive). The destination
* rectangle parameter must be a valid <code>Rectangle</code> instance.
* The handling of invalid parameters is unspecified.
*
* @param tabIndex the index of the tab
* @param dest the rectangle where the result should be placed
* @return the resulting rectangle
*
* @since 1.4
*/
protected Rectangle getTabBounds(int tabIndex, Rectangle dest)
{
dest.width= rects[tabIndex].width;
dest.height= rects[tabIndex].height;
if (scrollableTabLayoutEnabled())
{ // SCROLL_TAB_LAYOUT
// Need to translate coordinates based on viewport location &
// view position
Point vpp= tabScroller.viewport.getLocation();
Point viewp= tabScroller.viewport.getViewPosition();
dest.x= rects[tabIndex].x - vpp.x - viewp.x;
dest.y= rects[tabIndex].y - vpp.y - viewp.y;
}
else
{ // WRAP_TAB_LAYOUT
dest.x= rects[tabIndex].x;
dest.y= rects[tabIndex].y;
}
return dest;
}
/**
* Returns the tab index which intersects the specified point
* in the coordinate space of the component where the
* tabs are actually rendered, which could be the JTabbedPane
* (for WRAP_TAB_LAYOUT) or a ScrollableTabPanel (SCROLL_TAB_LAYOUT).
*/
private int getTabAtLocation(int x, int y)
{
ensureCurrentLayout();
int tabCount= tabPane.getTabCount();
for (int i= 0; i < tabCount; i++)
{
if (rects[i].contains(x, y))
{
return i;
}
}
return -1;
}
/**
* Returns the index of the tab closest to the passed in location, note
* that the returned tab may not contain the location x,y.
*/
private int getClosestTab(int x, int y)
{
int min= 0;
int tabCount= Math.min(rects.length, tabPane.getTabCount());
int max= tabCount;
int tabPlacement= tabPane.getTabPlacement();
boolean useX= (tabPlacement == TOP || tabPlacement == BOTTOM);
int want= (useX) ? x : y;
while (min != max)
{
int current= (max + min) / 2;
int minLoc;
int maxLoc;
if (useX)
{
minLoc= rects[current].x;
maxLoc= minLoc + rects[current].width;
}
else
{
minLoc= rects[current].y;
maxLoc= minLoc + rects[current].height;
}
if (want < minLoc)
{
max= current;
if (min == max)
{
return Math.max(0, current - 1);
}
}
else if (want >= maxLoc)
{
min= current;
if (max - min <= 1)
{
return Math.max(current + 1, tabCount - 1);
}
}
else
{
return current;
}
}
return min;
}
/**
* Returns a point which is translated from the specified point in the
* JTabbedPane's coordinate space to the coordinate space of the
* ScrollableTabPanel. This is used for SCROLL_TAB_LAYOUT ONLY.
*/
private Point translatePointToTabPanel(int srcx, int srcy, Point dest)
{
Point vpp= tabScroller.viewport.getLocation();
Point viewp= tabScroller.viewport.getViewPosition();
dest.x= srcx + vpp.x + viewp.x;
dest.y= srcy + vpp.y + viewp.y;
return dest;
}
// BasicTabbedPaneUI methods
protected Component getVisibleComponent()
{
return visibleComponent;
}
protected void setVisibleComponent(Component component)
{
if (visibleComponent == component)
{
return;
}
if (visibleComponent != null && visibleComponent.getParent() == tabPane)
{
visibleComponent.setVisible(false);
}
if (component != null)
{
component.setVisible(true);
}
visibleComponent= component;
}
protected void assureRectsCreated(int tabCount)
{
int rectArrayLen= rects.length;
if (tabCount != rectArrayLen)
{
Rectangle[] tempRectArray= new Rectangle[tabCount];
System.arraycopy(
rects,
0,
tempRectArray,
0,
Math.min(rectArrayLen, tabCount));
rects= tempRectArray;
for (int rectIndex= rectArrayLen; rectIndex < tabCount; rectIndex++)
{
rects[rectIndex]= new Rectangle();
}
}
}
protected void expandTabRunsArray()
{
int rectLen= tabRuns.length;
int[] newArray= new int[rectLen + 10];
System.arraycopy(tabRuns, 0, newArray, 0, runCount);
tabRuns= newArray;
}
protected int getRunForTab(int tabCount, int tabIndex)
{
for (int i= 0; i < runCount; i++)
{
int first= tabRuns[i];
int last= lastTabInRun(tabCount, i);
if (tabIndex >= first && tabIndex <= last)
{
return i;
}
}
return 0;
}
protected int lastTabInRun(int tabCount, int run)
{
if (runCount == 1)
{
return tabCount - 1;
}
int nextRun= (run == runCount - 1 ? 0 : run + 1);
if (tabRuns[nextRun] == 0)
{
return tabCount - 1;
}
return tabRuns[nextRun] - 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 runCount > 1;
}
protected boolean shouldRotateTabRuns(int tabPlacement)
{
return true;
}
protected Icon getIconForTab(int tabIndex)
{
return (!tabPane.isEnabled() || !tabPane.isEnabledAt(tabIndex))
? tabPane.getDisabledIconAt(tabIndex)
: tabPane.getIconAt(tabIndex);
}
/**
* Returns the text View object required to render stylized text (HTML) for
* the specified tab or null if no specialized text rendering is needed
* for this tab. This is provided to support html rendering inside tabs.
*
* @param tabIndex the index of the tab
* @return the text view to render the tab's text or null if no
* specialized rendering is required
*
* @since 1.4
*/
protected View getTextViewForTab(int tabIndex)
{
if (htmlViews != null)
{
return (View) htmlViews.elementAt(tabIndex);
}
return null;
}
protected int calculateTabHeight(
int tabPlacement,
int tabIndex,
int fontHeight)
{
int height= 0;
View v= getTextViewForTab(tabIndex);
if (v != null)
{
// html
height += (int) v.getPreferredSpan(View.Y_AXIS);
}
else
{
// plain text
height += fontHeight;
}
Icon icon= getIconForTab(tabIndex);
Insets tabInsets= getTabInsets(tabPlacement, tabIndex);
if (icon != null)
{
height= Math.max(height, icon.getIconHeight());
}
height += tabInsets.top + tabInsets.bottom + 2;
return height;
}
protected int calculateMaxTabHeight(int tabPlacement)
{
FontMetrics metrics= getFontMetrics();
int tabCount= tabPane.getTabCount();
int result= 0;
int fontHeight= metrics.getHeight();
for (int i= 0; i < tabCount; i++)
{
result=
Math.max(calculateTabHeight(tabPlacement, i, fontHeight), result);
}
return result;
}
protected int calculateTabWidth(
int tabPlacement,
int tabIndex,
FontMetrics metrics)
{
Icon icon= getIconForTab(tabIndex);
Insets tabInsets= getTabInsets(tabPlacement, tabIndex);
int width= tabInsets.left + tabInsets.right + 3;
if (icon != null)
{
width += icon.getIconWidth() + textIconGap;
}
View v= getTextViewForTab(tabIndex);
if (v != null)
{
// html
width += (int) v.getPreferredSpan(View.X_AXIS);
}
else
{
// plain text
String title= tabPane.getTitleAt(tabIndex);
width += SwingUtilities.computeStringWidth(metrics, title);
}
return width;
}
protected int calculateMaxTabWidth(int tabPlacement)
{
FontMetrics metrics= getFontMetrics();
int tabCount= tabPane.getTabCount();
int result= 0;
for (int i= 0; i < tabCount; i++)
{
result= Math.max(calculateTabWidth(tabPlacement, i, metrics), result);
}
return result;
}
protected int calculateTabAreaHeight(
int tabPlacement,
int horizRunCount,
int maxTabHeight)
{
Insets tabAreaInsets= getTabAreaInsets(tabPlacement);
int tabRunOverlay= getTabRunOverlay(tabPlacement);
return (
horizRunCount > 0
? horizRunCount * (maxTabHeight - tabRunOverlay)
+ tabRunOverlay
+ tabAreaInsets.top
+ tabAreaInsets.bottom
: 0);
}
protected int calculateTabAreaWidth(
int tabPlacement,
int vertRunCount,
int maxTabWidth)
{
Insets tabAreaInsets= getTabAreaInsets(tabPlacement);
int tabRunOverlay= getTabRunOverlay(tabPlacement);
return (
vertRunCount > 0
? vertRunCount * (maxTabWidth - tabRunOverlay)
+ tabRunOverlay
+ tabAreaInsets.left
+ tabAreaInsets.right
: 0);
}
protected Insets getTabInsets(int tabPlacement, int tabIndex)
{
return tabInsets;
}
protected Insets getSelectedTabPadInsets(int tabPlacement)
{
rotateInsets(selectedTabPadInsets, currentPadInsets, tabPlacement);
return currentPadInsets;
}
protected Insets getTabAreaInsets(int tabPlacement)
{
rotateInsets(tabAreaInsets, currentTabAreaInsets, tabPlacement);
return currentTabAreaInsets;
}
protected Insets getContentBorderInsets(int tabPlacement)
{
return contentBorderInsets;
}
protected FontMetrics getFontMetrics()
{
//Font font= tabPane.getFont();
Font font=UIManager.getFont("TabbedPane.selectedFont");
return Toolkit.getDefaultToolkit().getFontMetrics(font);
}
// Tab Navigation methods
protected void navigateSelectedTab(int direction)
{
int tabPlacement= tabPane.getTabPlacement();
int current= tabPane.getSelectedIndex();
int tabCount= tabPane.getTabCount();
int offset;
switch (tabPlacement)
{
case NEXT :
selectNextTab(current);
break;
case PREVIOUS :
selectPreviousTab(current);
break;
case LEFT :
case RIGHT :
switch (direction)
{
case NORTH :
selectPreviousTabInRun(current);
break;
case SOUTH :
selectNextTabInRun(current);
break;
case WEST :
offset=
getTabRunOffset(tabPlacement, tabCount, current, false);
selectAdjacentRunTab(tabPlacement, current, offset);
break;
case EAST :
offset=
getTabRunOffset(tabPlacement, tabCount, current, true);
selectAdjacentRunTab(tabPlacement, current, offset);
break;
default :
}
break;
case BOTTOM :
case TOP :
default :
switch (direction)
{
case NORTH :
offset=
getTabRunOffset(tabPlacement, tabCount, current, false);
selectAdjacentRunTab(tabPlacement, current, offset);
break;
case SOUTH :
offset=
getTabRunOffset(tabPlacement, tabCount, current, true);
selectAdjacentRunTab(tabPlacement, current, offset);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -