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;

Reply via email to