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