This fix should help avoid a division by zero error in
BasicTabbedPaneUI.
2006-10-12 Roman Kennke <[EMAIL PROTECTED]>
PR 2873
* javax/swing/plaf/basic/BasicTabbedPaneUI.java
(TabPaneLayout.normalizeTabRuns): Replaced algorithm with
one that avoids faulty state that could cause division by zero
error.
/Roman
Index: javax/swing/plaf/basic/BasicTabbedPaneUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java,v
retrieving revision 1.56
diff -u -1 -5 -r1.56 BasicTabbedPaneUI.java
--- javax/swing/plaf/basic/BasicTabbedPaneUI.java 1 Sep 2006 07:18:53 -0000 1.56
+++ javax/swing/plaf/basic/BasicTabbedPaneUI.java 12 Oct 2006 12:50:13 -0000
@@ -945,106 +945,75 @@
// max = the maximum position of where the tabs can go to
// (tabAreaInsets.left + the width of the tab area)
/**
* This method tries to "even out" the number of tabs in each run based on
* their widths.
*
* @param tabPlacement The JTabbedPane's tab placement.
* @param tabCount The number of tabs.
* @param start The x position where the tabs will begin.
* @param max The maximum x position where the tab can run to.
*/
protected void normalizeTabRuns(int tabPlacement, int tabCount, int start,
int max)
{
- if (tabPlacement == SwingUtilities.TOP
- || tabPlacement == SwingUtilities.BOTTOM)
+ boolean horizontal = tabPlacement == TOP || tabPlacement == BOTTOM;
+ int currentRun = runCount - 1;
+ double weight = 1.25;
+ for (boolean adjust = true; adjust == true;)
{
- // We should only do this for runCount - 1, cause we can
- // only shift that many times between runs.
- for (int i = 1; i < runCount; i++)
+ int last = lastTabInRun(tabCount, currentRun);
+ int prevLast = lastTabInRun(tabCount, currentRun - 1);
+ int end;
+ int prevLength;
+ if (horizontal)
{
- 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);
- }
-
- // Fixes the bounds of all tabs in the current
- // run.
- int first = tabRuns[i];
- int last = lastTabInRun(tabCount, i);
- int currX = start;
- for (int j = first; j <= last; j++)
- {
- rects[j].x = currX;
- currX += rects[j].width;
- }
+ end = rects[last].x + rects[last].width;
+ prevLength = (int) (maxTabWidth * weight);
}
- }
- else
- {
- for (int i = 1; i < runCount; i++)
+ else
{
- 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);
- }
-
- // Fixes the bounds of tabs in the current run.
- int first = tabRuns[i];
- int last = lastTabInRun(tabCount, i);
- int currY = start;
- for (int j = first; j <= last; j++)
+ end = rects[last].y + rects[last].height;
+ prevLength = (int) (maxTabWidth * weight * 2);
+ }
+ if (max - end > prevLength)
+ {
+ tabRuns[currentRun] = prevLast;
+ if (horizontal)
+ rects[prevLast].x = start;
+ else
+ rects[prevLast].y = start;
+ for (int i = prevLast + 1; i <= last; i++)
{
- rects[j].y = currY;
- currY += rects[j].height;
+ if (horizontal)
+ rects[i].x = rects[i - 1].x + rects[i - 1].width;
+ else
+ rects[i].y = rects[i - 1].y + rects[i - 1].height;
}
}
+ else if (currentRun == runCount - 1)
+ adjust = false;
+ if (currentRun - 1 > 0)
+ currentRun -= 1;
+ else
+ {
+ // Check again, but with higher ratio to avoid
+ // clogging up the last run.
+ currentRun = runCount - 1;
+ weight += 0.25;
+ }
}
}
/**
* This method pads the tab at the selected index by the selected tab pad
* insets (so that it looks larger).
*
* @param tabPlacement The placement of the tabs.
* @param selectedIndex The selected index.
*/
protected void padSelectedTab(int tabPlacement, int selectedIndex)
{
Insets insets = getSelectedTabPadInsets(tabPlacement);
rects[selectedIndex].x -= insets.left;
rects[selectedIndex].y -= insets.top;