Source for javax.swing.BoxLayout

   1: /* BoxLayout.java -- A layout for swing components.
   2:    Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package javax.swing;
  39: 
  40: import java.awt.AWTError;
  41: import java.awt.Component;
  42: import java.awt.ComponentOrientation;
  43: import java.awt.Container;
  44: import java.awt.Dimension;
  45: import java.awt.Insets;
  46: import java.awt.LayoutManager2;
  47: import java.io.Serializable;
  48: import java.util.Collection;
  49: import java.util.Iterator;
  50: import java.util.List;
  51: import java.util.Vector;
  52: 
  53: import gnu.java.awt.AWTUtilities;
  54: 
  55: /**
  56:  * A layout that stacks the children of a container in a Box, either
  57:  * horizontally or vertically.
  58:  *
  59:  * @author Ronald Veldema (rveldema@cs.vu.nl)
  60:  * @author Roman Kennke (roman@kennke.org)
  61:  */
  62: public class BoxLayout implements LayoutManager2, Serializable
  63: {
  64: 
  65:   /**
  66:    * This is an abstraction that allows the BoxLayout algorithm to
  67:    * be applied to both direction (X and Y) without duplicating the
  68:    * algorithm. It defines several methods that access properties of
  69:    * a component for a specific direction.
  70:    */
  71:   static interface Direction
  72:   {
  73:     /**
  74:      * Returns the correct part of <code>d</code> for this direction. This will
  75:      * be <code>d.width</code> for horizontal and <code>d.height</code> for
  76:      * vertical direction.
  77:      *
  78:      * @param d the size as Dimension object
  79:      *
  80:      * @return the correct part of <code>d</code> for this direction
  81:      */
  82:     int size(Dimension d);
  83: 
  84:     /**
  85:      * Returns the lower bounds of the {@link Insets} object according to this
  86:      * direction. This will be <code>insets.top</code> for vertical direction
  87:      * and <code>insets.left</code> for horizontal direction.
  88:      *
  89:      * @param the {@link Insets} object from which to return the lower bounds
  90:      *
  91:      * @return the lower bounds of the {@link Insets} object according to this
  92:      *     direction
  93:      */
  94:     int lower(Insets insets);
  95: 
  96:     /**
  97:      * Returns the alignment property according to this direction.
  98:      *
  99:      * @param comp the Component for which to return the alignment property
 100:      *
 101:      * @return the alignment property according to this direction
 102:      */
 103:     float alignment(Component comp);
 104: 
 105:     /**
 106:      * Sets the location for Component <code>c</code>. <code>coord1</code>
 107:      * specifies the coordinate of the location in this direction,
 108:      * <code>coord2</code> the coordinate of the location in the opposite
 109:      * direction.
 110:      *
 111:      * @param c the Component for which to set the location
 112:      * @param coord1 the coordinate in this direction
 113:      * @param coord2 the coordinate in the opposite direction
 114:      */
 115:     void setLocation(Component c, int coord1, int coord2);
 116: 
 117:     /**
 118:      * Sets the size for Component <code>c</code>. <code>coord1</code>
 119:      * specifies the size in this direction,
 120:      * <code>coord2</code> the size in the opposite
 121:      * direction.
 122:      *
 123:      * @param c the Component for which to set the size
 124:      * @param size1 the size in this direction
 125:      * @param size2 the size in the opposite direction
 126:      */
 127:     void setSize(Component c, int size1, int size2);
 128:   }
 129: 
 130:   /**
 131:    * The horizontal direction.
 132:    */
 133:   static class Horizontal implements Direction
 134:   {
 135:     /**
 136:      * Returns the correct part of <code>d</code> for this direction. This will
 137:      * be <code>d.width</code> for horizontal and <code>d.height</code> for
 138:      * vertical direction.
 139:      *
 140:      * @param d the size as Dimension object
 141:      *
 142:      * @return the correct part of <code>d</code> for this direction
 143:      */
 144:     public int size(Dimension d)
 145:     {
 146:       return d.width;
 147:     }
 148: 
 149:     /**
 150:      * Returns the lower bounds of the {@link Insets} object according to this
 151:      * direction. This will be <code>insets.top</code> for vertical direction
 152:      * and <code>insets.left</code> for horizontal direction.
 153:      *
 154:      * @param insets the {@link Insets} object from which to return the lower 
 155:      *               bounds
 156:      *
 157:      * @return the lower bounds of the {@link Insets} object according to this
 158:      *     direction
 159:      */
 160:     public int lower(Insets insets)
 161:     {
 162:       return insets.left;
 163:     }
 164: 
 165:     /**
 166:      * Returns the alignment property according to this direction.
 167:      *
 168:      * @param comp the Component for which to return the alignment property
 169:      *
 170:      * @return the alignment property according to this direction
 171:      */
 172:     public float alignment(Component comp)
 173:     {
 174:       return comp.getAlignmentX();
 175:     }
 176: 
 177:     /**
 178:      * Sets the location for Component <code>c</code>. <code>coord1</code>
 179:      * specifies the coordinate of the location in this direction,
 180:      * <code>coord2</code> the coordinate of the location in the opposite
 181:      * direction.
 182:      *
 183:      * @param c the Component for which to set the location
 184:      * @param coord1 the coordinate in this direction
 185:      * @param coord2 the coordinate in the opposite direction
 186:      */
 187:     public void setLocation(Component c, int coord1, int coord2)
 188:     {
 189:       c.setLocation(coord1, coord2);
 190:     }
 191: 
 192:     /**
 193:      * Sets the size for Component <code>c</code>. <code>coord1</code>
 194:      * specifies the size in this direction,
 195:      * <code>coord2</code> the size in the opposite
 196:      * direction.
 197:      *
 198:      * @param c the Component for which to set the size
 199:      * @param size1 the size in this direction
 200:      * @param size2 the size in the opposite direction
 201:      */
 202:     public void setSize(Component c, int size1, int size2)
 203:     {
 204:       c.setSize(size1, size2);
 205:     }
 206:   }
 207:   /**
 208:    * The vertical direction.
 209:    */
 210:   static class Vertical implements Direction
 211:   {
 212:     /**
 213:      * Returns the correct part of <code>d</code> for this direction. This will
 214:      * be <code>d.width</code> for horizontal and <code>d.height</code> for
 215:      * vertical direction.
 216:      *
 217:      * @param d the size as Dimension object
 218:      *
 219:      * @return the correct part of <code>d</code> for this direction
 220:      */
 221:     public int size(Dimension d)
 222:     {
 223:       return d.height;
 224:     }
 225: 
 226:     /**
 227:      * Returns the lower bounds of the {@link Insets} object according to this
 228:      * direction. This will be <code>insets.top</code> for vertical direction
 229:      * and <code>insets.left</code> for horizontal direction.
 230:      *
 231:      * @param insets the {@link Insets} object from which to return the lower 
 232:      *        bounds
 233:      *
 234:      * @return the lower bounds of the {@link Insets} object according to this
 235:      *     direction
 236:      */
 237:     public int lower(Insets insets)
 238:     {
 239:       return insets.top;
 240:     }
 241: 
 242:     /**
 243:      * Returns the alignment property according to this direction.
 244:      *
 245:      * @param comp the Component for which to return the alignment property
 246:      *
 247:      * @return the alignment property according to this direction
 248:      */
 249:     public float alignment(Component comp)
 250:     {
 251:       return comp.getAlignmentY();
 252:     }
 253: 
 254:     /**
 255:      * Sets the location for Component <code>c</code>. <code>coord1</code>
 256:      * specifies the coordinate of the location in this direction,
 257:      * <code>coord2</code> the coordinate of the location in the opposite
 258:      * direction.
 259:      *
 260:      * @param c the Component for which to set the location
 261:      * @param coord1 the coordinate in this direction
 262:      * @param coord2 the coordinate in the opposite direction
 263:      */
 264:     public void setLocation(Component c, int coord1, int coord2)
 265:     {
 266:       c.setLocation(coord2, coord1);
 267:     }
 268: 
 269:     /**
 270:      * Sets the size for Component <code>c</code>. <code>coord1</code>
 271:      * specifies the size in this direction,
 272:      * <code>coord2</code> the size in the opposite
 273:      * direction.
 274:      *
 275:      * @param c the Component for which to set the size
 276:      * @param size1 the size in this direction
 277:      * @param size2 the size in the opposite direction
 278:      */
 279:     public void setSize(Component c, int size1, int size2)
 280:     {
 281:       c.setSize(size2, size1);
 282:     }
 283:   }
 284: 
 285:   /**
 286:    * A helper class that temporarily stores the size specs of a component.
 287:    */
 288:   static class SizeReq
 289:   {
 290:     int size;
 291:     int min;
 292:     int pref;
 293:     int max;
 294:     float align;
 295:     Component comp;
 296:     SizeReq(Component comp, Direction dir)
 297:     {
 298:       this.min = dir.size(comp.getMinimumSize());
 299:       this.pref = dir.size(comp.getPreferredSize());
 300:       this.max = dir.size(comp.getMaximumSize());
 301:       this.size = dir.size(comp.getSize());
 302:       this.align = dir.alignment(comp);
 303:       this.comp = comp;
 304:     }
 305:   }
 306: 
 307:   /**
 308:    * Specifies that components are laid out left to right.
 309:    */
 310:   public static final int X_AXIS = 0;
 311: 
 312:   /**
 313:    * Specifies that components are laid out top to bottom.
 314:    */
 315:   public static final int Y_AXIS = 1;
 316: 
 317:   /**
 318:    * Specifies that components are laid out in the direction of a line of text.
 319:    */
 320:   public static final int LINE_AXIS = 2;
 321: 
 322:   /**
 323:    * Sepcifies that components are laid out in the direction of the line flow.
 324:    */
 325:   public static final int PAGE_AXIS = 3;
 326: 
 327:   /*
 328:    * Needed for serialization.
 329:    */
 330:   private static final long serialVersionUID = -2474455742719112368L;
 331: 
 332:   /*
 333:    * The container given to the constructor.
 334:    */
 335:   private Container container;
 336:   
 337:   /*
 338:    * Current type of component layouting. Defaults to X_AXIS.
 339:    */
 340:   private int way = X_AXIS;
 341: 
 342:   /** Constant for the horizontal direction. */
 343:   private static final Direction HORIZONTAL = new Horizontal();
 344: 
 345:   /** Constant for the vertical direction. */
 346:   private static final Direction VERTICAL = new Vertical();
 347: 
 348:   /**
 349:    * Constructs a <code>BoxLayout</code> object.
 350:    *
 351:    * @param container The container that needs to be laid out.
 352:    * @param way The orientation of the components.
 353:    *
 354:    * @exception AWTError If way has an invalid value.
 355:    */
 356:   public BoxLayout(Container container, int way)
 357:   {
 358:     int width = 0;
 359:     int height = 0;
 360:     this.container = container;
 361:     this.way = way;
 362:   }
 363: 
 364:   /**
 365:    * Adds a component to the layout. Not used in BoxLayout.
 366:    *
 367:    * @param name The name of the component to add.
 368:    * @param component the component to add to the layout.
 369:    */
 370:   public void addLayoutComponent(String name, Component component)
 371:   {
 372:   }
 373: 
 374:   /**
 375:    * Removes a component from the layout. Not used in BoxLayout.
 376:    *
 377:    * @param component The component to remove from the layout.
 378:    */
 379:   public void removeLayoutComponent(Component component)
 380:   {
 381:   }
 382: 
 383:   private boolean isHorizontalIn(Container parent)
 384:   {
 385:     ComponentOrientation orientation = parent.getComponentOrientation();
 386:     return this.way == X_AXIS 
 387:       || (this.way == LINE_AXIS 
 388:           && orientation.isHorizontal())
 389:       || (this.way == PAGE_AXIS
 390:           && (!orientation.isHorizontal()));
 391:   }
 392: 
 393:   
 394: 
 395:   /**
 396:    * Returns the preferred size of the layout.
 397:    *
 398:    * @param parent The container that needs to be laid out.
 399:    *
 400:    * @return The dimension of the layout.
 401:    */
 402:   public Dimension preferredLayoutSize(Container parent)
 403:   {
 404:     if (parent != container)
 405:       throw new AWTError("invalid parent");
 406: 
 407:     Insets insets = parent.getInsets();
 408:     int x = 0;
 409:     int y = 0;
 410: 
 411:     List children = AWTUtilities.getVisibleChildren(parent);
 412: 
 413:     if (isHorizontalIn(parent))
 414:       {        
 415:         x = insets.left + insets.right;
 416:         // sum up preferred widths of components, find maximum of preferred
 417:         // heights
 418:         for (Iterator i = children.iterator(); i.hasNext();)
 419:           {
 420:             Component comp = (Component) i.next();
 421:             Dimension sz = comp.getPreferredSize();
 422:             x += sz.width;
 423:             y = Math.max(y, sz.height);
 424:           }
 425:         y += insets.bottom + insets.top;
 426:       } 
 427:     else 
 428:       {        
 429:         y = insets.top + insets.bottom;
 430:         // sum up preferred heights of components, find maximum of
 431:         //  preferred widths
 432:         for (Iterator i = children.iterator(); i.hasNext();)
 433:           {
 434:             Component comp = (Component) i.next();
 435:             Dimension sz = comp.getPreferredSize();
 436:             y += sz.height;
 437:             x = Math.max(x, sz.width);
 438:           }
 439:         x += insets.left + insets.right;
 440:       }
 441: 
 442:     return new Dimension(x, y);
 443:   }
 444: 
 445:   /**
 446:    * Returns the minimum size of the layout.
 447:    *
 448:    * @param parent The container that needs to be laid out.
 449:    *
 450:    * @return The dimension of the layout.
 451:    */
 452:   public Dimension minimumLayoutSize(Container parent)
 453:   {
 454:     if (parent != container)
 455:       throw new AWTError("invalid parent");
 456: 
 457:     Insets insets = parent.getInsets();
 458:     int x = insets.left + insets.right;
 459:     int y = insets.bottom + insets.top;
 460: 
 461:     List children = AWTUtilities.getVisibleChildren(parent);
 462: 
 463:     if (isHorizontalIn(parent))
 464:       {
 465:         // sum up preferred widths of components, find maximum of preferred
 466:         // heights
 467:         for (Iterator i = children.iterator(); i.hasNext();)
 468:           {
 469:         Component comp = (Component) i.next();
 470:             Dimension sz = comp.getMinimumSize();
 471:             x += sz.width;
 472:             y = Math.max(y, sz.height);
 473:           }
 474:       }
 475:     else
 476:       {
 477:         // sum up preferred heights of components, find maximum of
 478:         //  preferred widths
 479:         for (Iterator i = children.iterator(); i.hasNext();)
 480:           {
 481:         Component comp = (Component) i.next();
 482:             Dimension sz = comp.getMinimumSize();
 483:             y += sz.height;
 484:             x = Math.max(x, sz.width);
 485:           }
 486:       }
 487:     
 488:     return new Dimension(x, y);
 489:   }
 490: 
 491:   /**
 492:    * Lays out the specified container using this layout.
 493:    *
 494:    * @param parent The container that needs to be laid out.
 495:    */
 496:   public void layoutContainer(Container parent)
 497:   {
 498:     if (isHorizontalIn(parent))
 499:       layoutAlgorithm(parent, HORIZONTAL, VERTICAL);
 500:     else
 501:       layoutAlgorithm(parent, VERTICAL, HORIZONTAL);
 502:   }
 503:   
 504:   /**
 505:    * Adds a component to the layout. Not used in BoxLayout
 506:    *
 507:    * @param child The component to add to the layout.
 508:    * @param constraints The constraints for the component in the layout.
 509:    */
 510:   public void addLayoutComponent(Component child, Object constraints)
 511:   {
 512:   }
 513: 
 514:   /**
 515:    * Returns the alignment along the X axis for the container.
 516:    *
 517:    * @param parent The container that needs to be laid out.
 518:    *
 519:    * @return The alignment.
 520:    */
 521:   public float getLayoutAlignmentX(Container parent)
 522:   {
 523:     if (parent != container)
 524:       throw new AWTError("invalid parent");
 525:     
 526:     return 0;
 527:   }
 528: 
 529:   /**
 530:    * Returns the alignment along the Y axis for the container.
 531:    *
 532:    * @param parent The container that needs to be laid out.
 533:    *
 534:    * @return The alignment.
 535:    */
 536:   public float getLayoutAlignmentY(Container parent)
 537:   {
 538:     if (parent != container)
 539:       throw new AWTError("invalid parent");
 540:     
 541:     return 0;
 542:   }
 543: 
 544:   /**
 545:    * Invalidates the layout.
 546:    *
 547:    * @param parent The container that needs to be laid out.
 548:    */
 549:   public void invalidateLayout(Container parent)
 550:   {
 551:     if (parent != container)
 552:       throw new AWTError("invalid parent");
 553:   }
 554: 
 555:   /**
 556:    * Returns the maximum size of the layout gived the components
 557:    * in the given container.
 558:    *
 559:    * @param parent The container that needs to be laid out.
 560:    *
 561:    * @return The dimension of the layout.
 562:    */
 563:   public Dimension maximumLayoutSize(Container parent)
 564:   {
 565:     if (parent != container)
 566:       throw new AWTError("invalid parent");
 567: 
 568:     Insets insets = parent.getInsets();
 569:     int x = insets.left + insets.right;
 570:     int y = insets.top + insets.bottom;
 571: 
 572:     List children = AWTUtilities.getVisibleChildren(parent);
 573: 
 574:     if (isHorizontalIn(parent))
 575:       {
 576:         
 577:         // sum up preferred widths of components, find maximum of preferred
 578:         // heights
 579:         for (Iterator i = children.iterator(); i.hasNext();)
 580:           {
 581:             Component comp = (Component) i.next();
 582:             Dimension sz = comp.getMaximumSize();
 583:             x += sz.width;
 584:             // Check for overflow.
 585:             if (x < 0)
 586:               x = Integer.MAX_VALUE;
 587:             y = Math.max(y, sz.height);
 588:           }
 589:       }
 590:     else
 591:       {
 592:         // sum up preferred heights of components, find maximum of
 593:         //  preferred widths
 594:         for (Iterator i = children.iterator(); i.hasNext();)
 595:           {
 596:             Component comp = (Component) i.next();
 597:             Dimension sz = comp.getMaximumSize();
 598:             y += sz.height;
 599:             // Check for overflow
 600:             if (y < 0)
 601:               y = Integer.MAX_VALUE;
 602:             x = Math.max(x, sz.width);
 603:           }
 604:       } 
 605:     return new Dimension(x, y);
 606:   }
 607: 
 608:   /**
 609:    * Lays out the Container <code>c</code> in the layout direction
 610:    * <code>layoutDir</code>. The direction that is crossing the layout
 611:    * direction is specified in <code>crossDir</code>.
 612:    *
 613:    * @param parent
 614:    * @param layoutDir
 615:    * @param crossDir
 616:    */
 617:   void layoutAlgorithm(Container parent, Direction layoutDir, Direction crossDir)
 618:   {
 619:     if (parent != container)
 620:       throw new AWTError("invalid parent");
 621: 
 622:     Dimension parentSize = parent.getSize();
 623:     Insets insets = parent.getInsets();
 624:     Dimension innerSize = new Dimension(parentSize.width - insets.left
 625:                                         - insets.right, parentSize.height
 626:                                         - insets.bottom - insets.top);
 627: 
 628:     // Set all components to their preferredSizes and sum up the allocated
 629:     // space. Create SizeReqs for each component and store them in
 630:     // sizeReqs. Find the maximum size in the crossing direction.
 631:     List children = AWTUtilities.getVisibleChildren(parent);
 632:     Vector sizeReqs = new Vector();
 633:     int allocated = 0;
 634:     for (Iterator i = children.iterator(); i.hasNext();)
 635:       {
 636:     Component c = (Component) i.next();
 637:     SizeReq sizeReq = new SizeReq(c, layoutDir);
 638:     int preferred = layoutDir.size(c.getPreferredSize());
 639:     sizeReq.size = preferred;
 640:     allocated += preferred;
 641:     sizeReqs.add(sizeReq);
 642:       }
 643: 
 644:     // Distribute remaining space (may be positive or negative) over components
 645:     int remainder = layoutDir.size(innerSize) - allocated;
 646:     distributeSpace(sizeReqs, remainder, layoutDir);
 647: 
 648:     // Resize and relocate components. If the component can be sized to
 649:     // take the full space in the crossing direction, then do so, otherwise
 650:     // align according to its alingnmentX or alignmentY property.
 651:     int loc = 0;
 652:     int offset1 = layoutDir.lower(insets);
 653:     int offset2 = crossDir.lower(insets);
 654:     for (Iterator i = sizeReqs.iterator(); i.hasNext();)
 655:       {
 656:     SizeReq sizeReq = (SizeReq) i.next();
 657:     Component c = sizeReq.comp;
 658:     int availCrossSize = crossDir.size(innerSize);
 659:     int maxCross = crossDir.size(c.getMaximumSize());
 660:     int crossSize = Math.min(availCrossSize, maxCross);
 661:     int crossRemainder = availCrossSize - crossSize;
 662:     int crossLoc = (int) (crossDir.alignment(c) * crossRemainder);
 663:     layoutDir.setSize(c, sizeReq.size, crossSize);
 664:     layoutDir.setLocation(c, offset1 + loc, offset2 + crossLoc);
 665:     loc += sizeReq.size;
 666:       }
 667:   }
 668: 
 669:   /**
 670:    * Distributes some space over a set of components. This implementation
 671:    * tries to set the components as close as possible to their
 672:    * <code>preferredSize</code>s, and respects the components
 673:    * <code>minimumSize</code> and <code>maximumSize</code>.
 674:    *
 675:    * The algorithm is implemented as follows:
 676:    *
 677:    * <ul>
 678:    * <li>The <code>remainder</code> is divided by the number of components
 679:    * in <code>freeComponents</code>.</li>
 680:    * <li>The result is added to (or substracted from) the size of each
 681:    * component.</li>
 682:    * <li>If the <code>minimumSize</code> or <code>maximumSize</code> of a
 683:    * component is exceeded, then this component is set to its
 684:    * <code>minimumSize</code> or <code>maximumSize</code>, it is removed from
 685:    * <code>freeComponents</code> and the difference is added to a new
 686:    * remainder.</li>
 687:    * <li>Finally, if there is a new remainer != 0 and the
 688:    * <code>freeComponents.size() != 0</code>, then this method is called
 689:    * recursivly to distribute the newly allocated remaining space.</li>
 690:    * </ul>
 691:    *
 692:    * @param freeComponents a SizeReq collection for components that have space
 693:    *     left so that they can be moved freely
 694:    * @param remainder the space that should be distributed between the
 695:    *     components
 696:    * @param dir the direction in which we operate
 697:    */
 698:   void distributeSpace(Collection freeComponents, int remainder, Direction dir)
 699:   {
 700:     // Sum up total available space in components. If the remainder is negative
 701:     // then we sum up the difference between minSize and size. If remainder
 702:     // is positive we sum up the difference between maxSize and size.
 703:     double totalAvailable = 0;
 704:     for (Iterator i = freeComponents.iterator(); i.hasNext();)
 705:       {
 706:         SizeReq sizeReq = (SizeReq) i.next();
 707:         if (remainder >= 0)
 708:           totalAvailable += sizeReq.max - sizeReq.size;
 709:         else
 710:           totalAvailable += sizeReq.min - sizeReq.size;
 711:       }
 712:     if (totalAvailable == 0)
 713:       if (remainder >= 0)
 714:         totalAvailable = 1;
 715:       else
 716:         totalAvailable = -1;
 717: 
 718:     int newRemainder = 0;
 719:     Vector stillFree = new Vector();
 720:     for (Iterator i = freeComponents.iterator(); i.hasNext();)
 721:       {
 722:     // Add/substract share to component.
 723:     SizeReq sizeReq = (SizeReq) i.next();
 724:         double available = 0;
 725:         if (remainder >= 0)
 726:           available = sizeReq.max - sizeReq.size;
 727:         else
 728:           available = sizeReq.min - sizeReq.size;
 729:         int share = (int) ((available / totalAvailable) * remainder);
 730:     sizeReq.size += share;
 731:     // check for min/maximumSize
 732:     if (sizeReq.size < sizeReq.min)
 733:       {
 734:         newRemainder += sizeReq.size - sizeReq.min;
 735:         sizeReq.size = sizeReq.min;
 736:       }
 737:     else if (sizeReq.size > sizeReq.max)
 738:       {
 739:         newRemainder += sizeReq.size - sizeReq.max;
 740:         sizeReq.size = sizeReq.max;
 741:       }
 742:     else
 743:       stillFree.add(sizeReq);
 744:       }
 745:     // recursivly call this method if necessary
 746:     if (newRemainder != 0 && stillFree.size() > 0)
 747:       distributeSpace(stillFree, newRemainder, dir);
 748:   }
 749: }