Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)
Frames | No Frames

Source for java.awt.GridBagLayout

 1:  /* GridBagLayout - Layout manager for components according to GridBagConstraints
 2:  Copyright (C) 2002, 2003, 2004, 2005, 2006 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: 
 39:  package java.awt;
 40: 
 41:  import java.io.Serializable;
 42:  import java.util.ArrayList;
 43:  import java.util.HashMap;
 44:  import java.util.Hashtable;
 45: 
 46:  /**
 47:  * @author Michael Koch (konqueror@gmx.de)
 48:  * @author Jeroen Frijters (jeroen@frijters.net)
 49:  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 50:  */
 51:  public class GridBagLayout
 52:  implements Serializable, LayoutManager2
 53: {
 54:  private static final long serialVersionUID = 8838754796412211005L;
 55: 
 56:  protected static final int MINSIZE = 1;
 57:  protected static final int PREFERREDSIZE = 2;
 58:  protected static final int MAXGRIDSIZE = 512;
 59: 
 60:  // comptable remembers the original contraints given to us.
 61:  // internalcomptable is used to keep track of modified constraint values
 62:  // that we calculate, particularly when we are given RELATIVE and
 63:  // REMAINDER constraints.
 64:  // Constraints kept in comptable are never modified, and constraints
 65:  // kept in internalcomptable can be modified internally only.
 66:  protected Hashtable<Component,GridBagConstraints> comptable;
 67:  private Hashtable<Component,GridBagConstraints> internalcomptable;
 68:  protected GridBagLayoutInfo layoutInfo;
 69:  protected GridBagConstraints defaultConstraints;
 70: 
 71:  public double[] columnWeights;
 72:  public int[] columnWidths;
 73:  public double[] rowWeights;
 74:  public int[] rowHeights;
 75: 
 76:  public GridBagLayout ()
 77:  {
 78:  this.comptable = new Hashtable<Component,GridBagConstraints>();
 79:  this.internalcomptable = new Hashtable<Component,GridBagConstraints>();
 80:  this.defaultConstraints= new GridBagConstraints();
 81:  }
 82: 
 83:  /**
 84:  * Helper method to calc the sum of a range of elements in an int array.
 85:  */
 86:  private int sumIntArray (int[] array, int upto)
 87:  {
 88:  int result = 0;
 89: 
 90:  for (int i = 0; i < upto; i++)
 91:  result += array [i];
 92: 
 93:  return result;
 94:  }
 95: 
 96:  /**
 97:  * Helper method to calc the sum of all elements in an int array.
 98:  */
 99:  private int sumIntArray (int[] array)
 100:  {
 101:  return sumIntArray(array, array.length);
 102:  }
 103: 
 104:  /**
 105:  * Helper method to calc the sum of all elements in an double array.
 106:  */
 107:  private double sumDoubleArray (double[] array)
 108:  {
 109:  double result = 0;
 110: 
 111:  for (int i = 0; i < array.length; i++)
 112:  result += array [i];
 113: 
 114:  return result;
 115:  }
 116: 
 117:  public void addLayoutComponent (String name, Component component)
 118:  {
 119:  // do nothing here.
 120:  }
 121: 
 122:  public void removeLayoutComponent (Component component)
 123:  {
 124:  // do nothing here
 125:  }
 126: 
 127:  public void addLayoutComponent (Component component, Object constraints)
 128:  {
 129:  if (constraints == null)
 130:  return;
 131: 
 132:  if (!(constraints instanceof GridBagConstraints))
 133:  throw new IllegalArgumentException("constraints " 
 134:  + constraints 
 135:  + " are not an instance of GridBagConstraints");
 136: 
 137:  setConstraints (component, (GridBagConstraints) constraints);
 138:  }
 139: 
 140:  public Dimension preferredLayoutSize (Container parent)
 141:  {
 142:  if (parent == null)
 143:  return new Dimension (0, 0);
 144:  
 145:  GridBagLayoutInfo li = getLayoutInfo (parent, PREFERREDSIZE);
 146:  return getMinSize (parent, li);
 147:  }
 148: 
 149:  public Dimension minimumLayoutSize (Container parent)
 150:  {
 151:  if (parent == null)
 152:  return new Dimension (0, 0);
 153:  
 154:  GridBagLayoutInfo li = getLayoutInfo (parent, MINSIZE);
 155:  return getMinSize (parent, li);
 156:  }
 157: 
 158:  public Dimension maximumLayoutSize (Container target)
 159:  {
 160:  return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE);
 161:  }
 162: 
 163:  public void layoutContainer (Container parent)
 164:  {
 165:  arrangeGrid (parent);
 166:  }
 167: 
 168:  public float getLayoutAlignmentX (Container target)
 169:  {
 170:  return Component.CENTER_ALIGNMENT;
 171:  }
 172: 
 173:  public float getLayoutAlignmentY (Container target)
 174:  {
 175:  return Component.CENTER_ALIGNMENT;
 176:  }
 177: 
 178:  public void invalidateLayout (Container target)
 179:  {
 180:  this.layoutInfo = null;
 181:  }
 182: 
 183:  public void setConstraints (Component component,
 184:  GridBagConstraints constraints)
 185:  {
 186:  GridBagConstraints clone = (GridBagConstraints) constraints.clone();
 187: 
 188:  if (clone.gridx < 0)
 189:  clone.gridx = GridBagConstraints.RELATIVE;
 190:  
 191:  if (clone.gridy < 0)
 192:  clone.gridy = GridBagConstraints.RELATIVE;
 193: 
 194:  if (clone.gridwidth == 0)
 195:  clone.gridwidth = GridBagConstraints.REMAINDER;
 196:  else if (clone.gridwidth < 0)
 197:  clone.gridwidth = 1;
 198:  
 199:  if (clone.gridheight == 0)
 200:  clone.gridheight = GridBagConstraints.REMAINDER;
 201:  else if (clone.gridheight < 0)
 202:  clone.gridheight = 1;
 203:  
 204:  comptable.put (component, clone);
 205:  }
 206: 
 207:  public GridBagConstraints getConstraints (Component component)
 208:  {
 209:  return (GridBagConstraints) (lookupConstraints (component).clone());
 210:  }
 211: 
 212:  protected GridBagConstraints lookupConstraints (Component component)
 213:  {
 214:  GridBagConstraints result = (GridBagConstraints) comptable.get (component);
 215: 
 216:  if (result == null)
 217:  {
 218:  setConstraints (component, defaultConstraints);
 219:  result = (GridBagConstraints) comptable.get (component);
 220:  }
 221:  
 222:  return result;
 223:  }
 224: 
 225:  private GridBagConstraints lookupInternalConstraints (Component component)
 226:  {
 227:  GridBagConstraints result =
 228:  (GridBagConstraints) internalcomptable.get (component);
 229: 
 230:  if (result == null)
 231:  {
 232:  result = (GridBagConstraints) lookupConstraints(component).clone();
 233:  internalcomptable.put (component, result);
 234:  }
 235:  
 236:  return result;
 237:  }
 238: 
 239:  /**
 240:  * @since 1.1
 241:  */
 242:  public Point getLayoutOrigin ()
 243:  {
 244:  if (layoutInfo == null)
 245:  return new Point (0, 0);
 246:  
 247:  return new Point (layoutInfo.pos_x, layoutInfo.pos_y);
 248:  }
 249: 
 250:  /**
 251:  * @since 1.1
 252:  */
 253:  public int[][] getLayoutDimensions ()
 254:  {
 255:  int[][] result = new int [2][];
 256:  if (layoutInfo == null)
 257:  {
 258:  result[0] = new int[0];
 259:  result[1] = new int[0];
 260: 
 261:  return result;
 262:  }
 263: 
 264:  result [0] = new int [layoutInfo.cols];
 265:  System.arraycopy (layoutInfo.colWidths, 0, result [0], 0, layoutInfo.cols);
 266:  result [1] = new int [layoutInfo.rows];
 267:  System.arraycopy (layoutInfo.rowHeights, 0, result [1], 0, layoutInfo.rows);
 268:  return result;
 269:  }
 270: 
 271:  public double[][] getLayoutWeights ()
 272:  {
 273:  double[][] result = new double [2][];
 274:  if (layoutInfo == null)
 275:  {
 276:  result[0] = new double[0];
 277:  result[1] = new double[0];
 278: 
 279:  return result;
 280:  }
 281: 
 282:  result [0] = new double [layoutInfo.cols];
 283:  System.arraycopy (layoutInfo.colWeights, 0, result [0], 0, layoutInfo.cols);
 284:  result [1] = new double [layoutInfo.rows];
 285:  System.arraycopy (layoutInfo.rowWeights, 0, result [1], 0, layoutInfo.rows);
 286:  return result;
 287:  }
 288: 
 289:  /**
 290:  * @since 1.1
 291:  */
 292:  public Point location (int x, int y)
 293:  {
 294:  if (layoutInfo == null)
 295:  return new Point (0, 0);
 296: 
 297:  int col;
 298:  int row;
 299:  int pixel_x = layoutInfo.pos_x;
 300:  int pixel_y = layoutInfo.pos_y;
 301: 
 302:  for (col = 0; col < layoutInfo.cols; col++)
 303:  {
 304:  int w = layoutInfo.colWidths [col];
 305:  if (x < pixel_x + w)
 306:  break;
 307: 
 308:  pixel_x += w;
 309:  }
 310: 
 311:  for (row = 0; row < layoutInfo.rows; row++)
 312:  {
 313:  int h = layoutInfo.rowHeights [row];
 314:  if (y < pixel_y + h)
 315:  break;
 316: 
 317:  pixel_y += h;
 318:  }
 319: 
 320:  return new Point (col, row);
 321:  }
 322: 
 323:  /**
 324:  * Return a string representation of this GridBagLayout.
 325:  *
 326:  * @return a string representation
 327:  */
 328:  public String toString()
 329:  {
 330:  return getClass().getName();
 331:  }
 332:  
 333:  /**
 334:  * Move and resize a rectangle according to a set of grid bag
 335:  * constraints. The x, y, width and height fields of the
 336:  * rectangle argument are adjusted to the new values.
 337:  *
 338:  * @param constraints position and size constraints
 339:  * @param r rectangle to be moved and resized
 340:  */
 341:  protected void AdjustForGravity (GridBagConstraints constraints,
 342:  Rectangle r)
 343:  {
 344:  Insets insets = constraints.insets;
 345:  if (insets != null)
 346:  {
 347:  r.x += insets.left;
 348:  r.y += insets.top;
 349:  r.width -= insets.left + insets.right;
 350:  r.height -= insets.top + insets.bottom;
 351:  }
 352:  }
 353: 
 354:  /**
 355:  * Obsolete.
 356:  */
 357:  protected void ArrangeGrid (Container parent)
 358:  {
 359:  Component[] components = parent.getComponents();
 360: 
 361:  if (components.length == 0)
 362:  return;
 363: 
 364:  GridBagLayoutInfo info = getLayoutInfo (parent, PREFERREDSIZE);
 365:  if (info.cols == 0 && info.rows == 0)
 366:  return;
 367: 
 368:  // DEBUG
 369:  //dumpLayoutInfo (info);
 370: 
 371:  // Calling setBounds on these components causes this layout to
 372:  // be invalidated, clearing the layout information cache,
 373:  // layoutInfo. So we wait until after this for loop to set
 374:  // layoutInfo.
 375:  Component lastComp = null;
 376: 
 377:  Rectangle cell = new Rectangle();
 378: 
 379:  for (int i = 0; i < components.length; i++)
 380:  {
 381:  Component component = components[i];
 382: 
 383:  // If component is not visible we dont have to care about it.
 384:  if (! component.isVisible())
 385:  continue;
 386: 
 387:  Dimension dim = component.getPreferredSize();
 388:  GridBagConstraints constraints = lookupInternalConstraints(component);
 389:  
 390:  if (lastComp != null
 391:  && constraints.gridheight == GridBagConstraints.REMAINDER)
 392:  cell.y += cell.height;
 393:  else
 394:  cell.y = sumIntArray(info.rowHeights, constraints.gridy);
 395:  
 396:  if (lastComp != null
 397:  && constraints.gridwidth == GridBagConstraints.REMAINDER)
 398:  cell.x += cell.width;
 399:  else
 400:  cell.x = sumIntArray(info.colWidths, constraints.gridx);
 401: 
 402:  cell.width = sumIntArray(info.colWidths, constraints.gridx
 403:  + constraints.gridwidth) - cell.x;
 404:  cell.height = sumIntArray(info.rowHeights, constraints.gridy
 405:  + constraints.gridheight) - cell.y;
 406:  
 407:  // Adjust for insets.
 408:  AdjustForGravity( constraints, cell );
 409: 
 410:  // Note: Documentation says that padding is added on both sides, but
 411:  // visual inspection shows that the Sun implementation only adds it
 412:  // once, so we do the same.
 413:  dim.width += constraints.ipadx;
 414:  dim.height += constraints.ipady;
 415: 
 416:  switch (constraints.fill)
 417:  {
 418:  case GridBagConstraints.HORIZONTAL:
 419:  dim.width = cell.width;
 420:  break;
 421:  case GridBagConstraints.VERTICAL:
 422:  dim.height = cell.height;
 423:  break;
 424:  case GridBagConstraints.BOTH:
 425:  dim.width = cell.width;
 426:  dim.height = cell.height;
 427:  break;
 428:  }
 429: 
 430:  int x = 0;
 431:  int y = 0;
 432: 
 433:  switch (constraints.anchor)
 434:  {
 435:  case GridBagConstraints.NORTH:
 436:  x = cell.x + (cell.width - dim.width) / 2;
 437:  y = cell.y;
 438:  break;
 439:  case GridBagConstraints.SOUTH:
 440:  x = cell.x + (cell.width - dim.width) / 2;
 441:  y = cell.y + cell.height - dim.height;
 442:  break;
 443:  case GridBagConstraints.WEST:
 444:  x = cell.x;
 445:  y = cell.y + (cell.height - dim.height) / 2;
 446:  break;
 447:  case GridBagConstraints.EAST:
 448:  x = cell.x + cell.width - dim.width;
 449:  y = cell.y + (cell.height - dim.height) / 2;
 450:  break;
 451:  case GridBagConstraints.NORTHEAST:
 452:  x = cell.x + cell.width - dim.width;
 453:  y = cell.y;
 454:  break;
 455:  case GridBagConstraints.NORTHWEST:
 456:  x = cell.x;
 457:  y = cell.y;
 458:  break;
 459:  case GridBagConstraints.SOUTHEAST:
 460:  x = cell.x + cell.width - dim.width;
 461:  y = cell.y + cell.height - dim.height;
 462:  break;
 463:  case GridBagConstraints.SOUTHWEST:
 464:  x = cell.x;
 465:  y = cell.y + cell.height - dim.height;
 466:  break;
 467:  default:
 468:  x = cell.x + (cell.width - dim.width) / 2;
 469:  y = cell.y + (cell.height - dim.height) / 2;
 470:  break;
 471:  }
 472:  component.setBounds(info.pos_x + x, info.pos_y + y, dim.width,
 473:  dim.height);
 474:  lastComp = component;
 475:  }
 476: 
 477:  // DEBUG
 478:  //dumpLayoutInfo(info);
 479: 
 480:  // Cache layout information.
 481:  layoutInfo = getLayoutInfo(parent, PREFERREDSIZE);
 482:  }
 483: 
 484:  /**
 485:  * Obsolete.
 486:  */
 487:  protected GridBagLayoutInfo GetLayoutInfo (Container parent, int sizeflag)
 488:  {
 489:  if (sizeflag != MINSIZE && sizeflag != PREFERREDSIZE)
 490:  throw new IllegalArgumentException();
 491: 
 492:  Dimension parentDim = parent.getSize ();
 493:  Insets parentInsets = parent.getInsets ();
 494:  parentDim.width -= parentInsets.left + parentInsets.right;
 495:  parentDim.height -= parentInsets.top + parentInsets.bottom;
 496:  
 497:  int current_y = 0;
 498:  int max_x = 0;
 499:  int max_y = 0;
 500: 
 501:  // Guaranteed to contain the last component added to the given row
 502:  // or column, whose gridwidth/height is not REMAINDER.
 503:  HashMap<Integer,Component> lastInRow = new HashMap<Integer,Component>();
 504:  HashMap<Integer,Component> lastInCol = new HashMap<Integer,Component>();
 505: 
 506:  Component[] components = parent.getComponents();
 507: 
 508:  // Components sorted by gridwidths/heights,
 509:  // smallest to largest, with REMAINDER and RELATIVE at the end.
 510:  // These are useful when determining sizes and weights.
 511:  ArrayList<Component> sortedByWidth =
 512:  new ArrayList<Component>(components.length);
 513:  ArrayList<Component> sortedByHeight =
 514:  new ArrayList<Component>(components.length);
 515: 
 516:  // STEP 1: first we figure out how many rows/columns
 517:  for (int i = 0; i < components.length; i++)
 518:  {
 519:  Component component = components [i];
 520:  // If component is not visible we dont have to care about it.
 521:  if (!component.isVisible())
 522:  continue;
 523: 
 524:  // When looking up the constraint for the first time, check the
 525:  // original unmodified constraint. After the first time, always
 526:  // refer to the internal modified constraint.
 527:  GridBagConstraints originalConstraints = lookupConstraints (component);
 528:  GridBagConstraints constraints = (GridBagConstraints) originalConstraints.clone();
 529:  internalcomptable.put(component, constraints);
 530: 
 531:  // Cases:
 532:  //
 533:  // 1. gridy == RELATIVE, gridx == RELATIVE
 534:  //
 535:  // use y as the row number; check for the next
 536:  // available slot at row y
 537:  //
 538:  // 2. only gridx == RELATIVE
 539:  //
 540:  // check for the next available slot at row gridy
 541:  //
 542:  // 3. only gridy == RELATIVE
 543:  //
 544:  // check for the next available slot at column gridx
 545:  //
 546:  // 4. neither gridx or gridy == RELATIVE
 547:  //
 548:  // nothing to check; just add it
 549: 
 550:  // cases 1 and 2
 551:  if(constraints.gridx == GridBagConstraints.RELATIVE)
 552:  {
 553:  if (constraints.gridy == GridBagConstraints.RELATIVE)
 554:  constraints.gridy = current_y;
 555: 
 556:  int x;
 557: 
 558:  // Check the component that occupies the right-most spot in this
 559:  // row. We want to add this component after it.
 560:  // If this row is empty, add to the 0 position.
 561:  if (!lastInRow.containsKey(new Integer(constraints.gridy))) 
 562:  x = 0;
 563:  else
 564:  {
 565:  Component lastComponent = (Component) lastInRow.get(new Integer(constraints.gridy));
 566:  GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
 567:  x = lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth);
 568:  }
 569: 
 570:  // Determine if this component will fit in the slot vertically.
 571:  // If not, bump it over to where it does fit.
 572:  for (int y = constraints.gridy + 1; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
 573:  {
 574:  if (lastInRow.containsKey(new Integer(y)))
 575:  {
 576:  Component lastComponent = (Component) lastInRow.get(new Integer(y));
 577:  GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
 578:  x = Math.max (x,
 579:  lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth));
 580:  }
 581:  }
 582: 
 583:  constraints.gridx = x;
 584:  }
 585:  // case 3
 586:  else if(constraints.gridy == GridBagConstraints.RELATIVE)
 587:  {
 588:  int y;
 589:  // Check the component that occupies the bottom-most spot in
 590:  // this column. We want to add this component below it.
 591:  // If this column is empty, add to the 0 position.
 592:  if (!lastInCol.containsKey(new Integer(constraints.gridx))) 
 593:  {
 594:  y = current_y;
 595:  }
 596:  else
 597:  {
 598:  Component lastComponent = (Component)lastInCol.get(new Integer(constraints.gridx));
 599:  GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
 600:  y = lastConstraints.gridy + Math.max(1, lastConstraints.gridheight);
 601:  }
 602: 
 603:  // Determine if this component will fit in the slot horizontally.
 604:  // If not, bump it down to where it does fit.
 605:  for (int x = constraints.gridx + 1; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
 606:  {
 607:  if (lastInCol.containsKey(new Integer(x)))
 608:  {
 609:  Component lastComponent = (Component) lastInCol.get(new Integer(x));
 610:  GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
 611:  y = Math.max (y,
 612:  lastConstraints.gridy + Math.max(1, lastConstraints.gridheight));
 613:  }
 614:  }
 615: 
 616:  constraints.gridy = y;
 617:  }
 618:  // case 4: do nothing
 619: 
 620:  max_x = Math.max(max_x, 
 621:  constraints.gridx + Math.max(1, constraints.gridwidth));
 622:  max_y = Math.max(max_y,
 623:  constraints.gridy + Math.max(1, constraints.gridheight));
 624: 
 625:  sortBySpan(component, constraints.gridwidth, sortedByWidth, true);
 626:  sortBySpan(component, constraints.gridheight, sortedByHeight, false);
 627: 
 628:  // Update our reference points for RELATIVE gridx and gridy.
 629:  if(constraints.gridwidth == GridBagConstraints.REMAINDER)
 630:  {
 631:  current_y = constraints.gridy + Math.max(1, constraints.gridheight);
 632:  }
 633:  else if (constraints.gridwidth != GridBagConstraints.REMAINDER)
 634:  {
 635:  for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
 636:  {
 637:  if(lastInRow.containsKey(new Integer(y)))
 638:  {
 639:  Component lastComponent = (Component) lastInRow.get(new Integer(y));
 640:  GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
 641:  if (constraints.gridx > lastConstraints.gridx)
 642:  {
 643:  lastInRow.put(new Integer(y), component);
 644:  }
 645:  }
 646:  else
 647:  {
 648:  lastInRow.put(new Integer(y), component);
 649:  }
 650:  }
 651: 
 652:  for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
 653:  {
 654:  if(lastInCol.containsKey(new Integer(x)))
 655:  {
 656:  Component lastComponent = (Component) lastInCol.get(new Integer(x));
 657:  GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
 658:  if (constraints.gridy > lastConstraints.gridy)
 659:  {
 660:  lastInCol.put(new Integer(x), component);
 661:  }
 662:  }
 663:  else
 664:  {
 665:  lastInCol.put(new Integer(x), component);
 666:  }
 667:  }
 668:  }
 669:  } // end of STEP 1
 670:  
 671:  GridBagLayoutInfo info = new GridBagLayoutInfo(max_x, max_y);
 672: 
 673:  // Check if column widths and row heights are overridden.
 674: 
 675:  for (int x = 0; x < max_x; x++)
 676:  {
 677:  if(columnWidths != null && columnWidths.length > x)
 678:  info.colWidths[x] = columnWidths[x];
 679:  if(columnWeights != null && columnWeights.length > x)
 680:  info.colWeights[x] = columnWeights[x];
 681:  }
 682: 
 683:  for (int y = 0; y < max_y; y++)
 684:  {
 685:  if(rowHeights != null && rowHeights.length > y)
 686:  info.rowHeights[y] = rowHeights[y];
 687:  if(rowWeights != null && rowWeights.length > y)
 688:  info.rowWeights[y] = rowWeights[y];
 689:  }
 690: 
 691:  // STEP 2: Fix up any cells with width/height as REMAINDER/RELATIVE.
 692:  for (int i = 0; i < components.length; i++)
 693:  {
 694:  Component component = components [i];
 695:  
 696:  // If component is not visible we dont have to care about it.
 697:  if (!component.isVisible())
 698:  continue;
 699:  
 700:  GridBagConstraints constraints = lookupInternalConstraints (component);
 701: 
 702:  if(constraints.gridwidth == GridBagConstraints.REMAINDER || constraints.gridwidth == GridBagConstraints.RELATIVE)
 703:  {
 704:  if(constraints.gridwidth == GridBagConstraints.REMAINDER)
 705:  {
 706:  for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
 707:  {
 708:  if (lastInRow.containsKey(new Integer(y)))
 709:  {
 710:  Component lastComponent = (Component) lastInRow.get(new Integer(y));
 711:  GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
 712: 
 713:  if (lastConstraints.gridwidth == GridBagConstraints.RELATIVE)
 714:  {
 715:  constraints.gridx = max_x - 1;
 716:  break;
 717:  }
 718:  else
 719:  {
 720:  constraints.gridx = Math.max (constraints.gridx,
 721:  lastConstraints.gridx + Math.max (1, lastConstraints.gridwidth));
 722:  }
 723:  }
 724:  }
 725:  constraints.gridwidth = max_x - constraints.gridx;
 726:  }
 727:  else if (constraints.gridwidth == GridBagConstraints.RELATIVE)
 728:  {
 729:  constraints.gridwidth = max_x - constraints.gridx - 1;
 730:  }
 731: 
 732:  // Re-sort
 733:  sortedByWidth.remove(sortedByWidth.indexOf(component));
 734:  sortBySpan(component, constraints.gridwidth, sortedByWidth, true);
 735:  }
 736: 
 737:  if(constraints.gridheight == GridBagConstraints.REMAINDER || constraints.gridheight == GridBagConstraints.RELATIVE)
 738:  {
 739:  if(constraints.gridheight == GridBagConstraints.REMAINDER)
 740:  {
 741:  for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
 742:  {
 743:  if (lastInCol.containsKey(new Integer(x)))
 744:  {
 745:  Component lastComponent = (Component) lastInRow.get(new Integer(x));
 746:  if (lastComponent != null)
 747:  {
 748:  GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
 749:  
 750:  if (lastConstraints.gridheight == GridBagConstraints.RELATIVE)
 751:  {
 752:  constraints.gridy = max_y - 1;
 753:  break;
 754:  }
 755:  else
 756:  {
 757:  constraints.gridy = Math.max (constraints.gridy,
 758:  lastConstraints.gridy + Math.max (1, lastConstraints.gridheight));
 759:  }
 760:  }
 761:  }
 762:  }
 763:  constraints.gridheight = max_y - constraints.gridy;
 764:  }
 765:  else if (constraints.gridheight == GridBagConstraints.RELATIVE)
 766:  {
 767:  constraints.gridheight = max_y - constraints.gridy - 1;
 768:  }
 769: 
 770:  // Re-sort
 771:  sortedByHeight.remove(sortedByHeight.indexOf(component));
 772:  sortBySpan(component, constraints.gridheight, sortedByHeight, false);
 773:  }
 774:  } // end of STEP 2
 775: 
 776:  // STEP 3: Determine sizes and weights for columns.
 777:  for (int i = 0; i < sortedByWidth.size(); i++)
 778:  {
 779:  Component component = sortedByWidth.get(i);
 780:  
 781:  // If component is not visible we dont have to care about it.
 782:  if (!component.isVisible())
 783:  continue;
 784: 
 785:  GridBagConstraints constraints = lookupInternalConstraints (component);
 786: 
 787:  int width = (sizeflag == PREFERREDSIZE) ?
 788:  component.getPreferredSize().width :
 789:  component.getMinimumSize().width;
 790: 
 791:  if(constraints.insets != null)
 792:  width += constraints.insets.left + constraints.insets.right;
 793: 
 794:  width += constraints.ipadx;
 795: 
 796:  distributeSizeAndWeight(width,
 797:  constraints.weightx, 
 798:  constraints.gridx,
 799:  constraints.gridwidth,
 800:  info.colWidths,
 801:  info.colWeights);
 802:  } // end of STEP 3
 803: 
 804:  // STEP 4: Determine sizes and weights for rows.
 805:  for (int i = 0; i < sortedByHeight.size(); i++)
 806:  {
 807:  Component component = (Component) sortedByHeight.get(i);
 808:  
 809:  // If component is not visible we dont have to care about it.
 810:  if (!component.isVisible())
 811:  continue;
 812: 
 813:  GridBagConstraints constraints = lookupInternalConstraints (component);
 814: 
 815:  int height = (sizeflag == PREFERREDSIZE) ?
 816:  component.getPreferredSize().height :
 817:  component.getMinimumSize().height;
 818: 
 819:  if(constraints.insets != null)
 820:  height += constraints.insets.top + constraints.insets.bottom;
 821: 
 822:  height += constraints.ipady;
 823:  
 824:  distributeSizeAndWeight(height,
 825:  constraints.weighty, 
 826:  constraints.gridy,
 827:  constraints.gridheight,
 828:  info.rowHeights,
 829:  info.rowWeights);
 830:  } // end of STEP 4
 831: 
 832:  // Adjust cell sizes iff parent size not zero.
 833:  if (parentDim.width > 0 && parentDim.height > 0)
 834:  {
 835:  calcCellSizes (info.colWidths, info.colWeights, parentDim.width);
 836:  calcCellSizes (info.rowHeights, info.rowWeights, parentDim.height);
 837:  }
 838: 
 839:  int totalWidth = sumIntArray(info.colWidths);
 840:  int totalHeight = sumIntArray(info.rowHeights);
 841: 
 842:  // Make sure pos_x and pos_y are never negative.
 843:  if (totalWidth >= parentDim.width)
 844:  info.pos_x = parentInsets.left;
 845:  else
 846:  info.pos_x = parentInsets.left + (parentDim.width - totalWidth) / 2;
 847: 
 848:  if (totalHeight >= parentDim.height)
 849:  info.pos_y = parentInsets.top;
 850:  else
 851:  info.pos_y = parentInsets.top + (parentDim.height - totalHeight) / 2;
 852: 
 853:  // DEBUG
 854:  //dumpLayoutInfo (info);
 855: 
 856:  return info;
 857:  }
 858: 
 859:  /**
 860:  * Obsolete.
 861:  */
 862:  protected Dimension GetMinSize (Container parent, GridBagLayoutInfo info)
 863:  {
 864:  if (parent == null || info == null)
 865:  return new Dimension (0, 0);
 866: 
 867:  Insets insets = parent.getInsets();
 868:  int width = sumIntArray (info.colWidths) + insets.left + insets.right;
 869:  int height = sumIntArray (info.rowHeights) + insets.top + insets.bottom;
 870:  return new Dimension (width, height);
 871:  }
 872: 
 873:  /**
 874:  * @since 1.4
 875:  */
 876:  protected Dimension getMinSize (Container parent, GridBagLayoutInfo info)
 877:  {
 878:  return GetMinSize (parent, info);
 879:  }
 880: 
 881:  /**
 882:  * Helper method used by GetLayoutInfo to keep components sorted, either
 883:  * by gridwidth or gridheight.
 884:  *
 885:  * @param component Component to add to the sorted list.
 886:  * @param span Either the component's gridwidth or gridheight.
 887:  * @param list <code>ArrayList</code> of components, sorted by
 888:  * their span.
 889:  * @param sortByWidth Flag indicating sorting index. If true, sort by
 890:  * width. Otherwise, sort by height.
 891:  * FIXME: Use a better sorting algorithm.
 892:  */
 893:  private void sortBySpan (Component component, int span,
 894:  ArrayList<Component> list, boolean sortByWidth)
 895:  {
 896:  if (span == GridBagConstraints.REMAINDER
 897:  || span == GridBagConstraints.RELATIVE)
 898:  {
 899:  // Put all RELATIVE and REMAINDER components at the end.
 900:  list.add(component);
 901:  }
 902:  else
 903:  {
 904:  int i = 0;
 905:  if (list.size() > 0)
 906:  {
 907:  GridBagConstraints gbc = lookupInternalConstraints((Component) list.get(i));
 908:  int otherspan = sortByWidth ?
 909:  gbc.gridwidth :
 910:  gbc.gridheight;
 911:  while (otherspan != GridBagConstraints.REMAINDER
 912:  && otherspan != GridBagConstraints.RELATIVE
 913:  && span >= otherspan)
 914:  {
 915:  i++;
 916:  if (i < list.size())
 917:  {
 918:  gbc = lookupInternalConstraints((Component) list.get(i));
 919:  otherspan = sortByWidth ?
 920:  gbc.gridwidth :
 921:  gbc.gridheight;
 922:  }
 923:  else
 924:  break;
 925:  }
 926:  }
 927:  list.add(i, component);
 928:  }
 929:  }
 930: 
 931:  /**
 932:  * Helper method used by GetLayoutInfo to distribute a component's size
 933:  * and weight.
 934:  *
 935:  * @param size Preferred size of component, with inset and padding
 936:  * already added.
 937:  * @param weight Weight of component.
 938:  * @param start Starting position of component. Either
 939:  * constraints.gridx or gridy.
 940:  * @param span Span of component. either contraints.gridwidth or
 941:  * gridheight.
 942:  * @param sizes Sizes of rows or columns.
 943:  * @param weights Weights of rows or columns.
 944:  */
 945:  private void distributeSizeAndWeight (int size, double weight,
 946:  int start, int span,
 947:  int[] sizes, double[] weights)
 948:  {
 949:  if (span == 1)
 950:  {
 951:  sizes[start] = Math.max(sizes[start], size);
 952:  weights[start] = Math.max(weights[start], weight);
 953:  }
 954:  else
 955:  {
 956:  int numOccupied = span;
 957:  int lastOccupied = -1;
 958: 
 959:  for(int i = start; i < start + span; i++)
 960:  {
 961:  if (sizes[i] == 0.0)
 962:  numOccupied--;
 963:  else
 964:  {
 965:  size -= sizes[i];
 966:  lastOccupied = i;
 967:  }
 968:  }
 969: 
 970:  // A component needs to occupy at least one row.
 971:  if(numOccupied == 0)
 972:  sizes[start + span - 1] = size;
 973:  else if (size > 0)
 974:  sizes[lastOccupied] += size;
 975: 
 976:  calcCellWeights(weight, weights, start, span);
 977:  }
 978:  }
 979: 
 980:  /**
 981:  * Helper method used by GetLayoutInfo to calculate weight distribution.
 982:  * @param weight Weight of component.
 983:  * @param weights Weights of rows/columns.
 984:  * @param start Starting position of component in grid (gridx/gridy).
 985:  * @param span Span of component (gridwidth/gridheight).
 986:  */
 987:  private void calcCellWeights (double weight, double[] weights, int start, int span)
 988:  {
 989:  double totalWeight = 0.0;
 990:  for(int k = start; k < start + span; k++)
 991:  totalWeight += weights[k];
 992: 
 993:  if(weight > totalWeight)
 994:  {
 995:  if (totalWeight == 0.0)
 996:  {
 997:  weights[start + span - 1] += weight;
 998:  }
 999:  else
1000:  {
1001:  double diff = weight - totalWeight ;
1002:  double remaining = diff;
1003: 
1004:  for(int k = start; k < start + span; k++)
1005:  {
1006:  double extraWeight = diff * weights[k] / totalWeight;
1007:  weights[k] += extraWeight;
1008:  remaining -= extraWeight;
1009:  } 
1010: 
1011:  if (remaining > 0.0 && weights[start + span - 1] != 0.0)
1012:  {
1013:  weights[start + span - 1] += remaining;
1014:  }
1015:  }
1016:  }
1017:  }
1018: 
1019:  /**
1020:  * Helper method used by GetLayoutInfo to distribute extra space
1021:  * based on weight distribution.
1022:  *
1023:  * @param sizes Sizes of rows/columns.
1024:  * @param weights Weights of rows/columns.
1025:  * @param range Dimension of container.
1026:  */
1027:  private void calcCellSizes (int[] sizes, double[] weights, int range)
1028:  {
1029:  int totalSize = sumIntArray (sizes);
1030:  double totalWeight = sumDoubleArray (weights);
1031: 
1032:  int diff = range - totalSize;
1033: 
1034:  if (diff == 0)
1035:  return;
1036: 
1037:  for (int i = 0; i < sizes.length; i++)
1038:  {
1039:  int newsize = (int) (sizes[i] + (((double) diff) * weights [i] / totalWeight ));
1040: 
1041:  if (newsize > 0)
1042:  sizes[i] = newsize;
1043:  }
1044:  }
1045: 
1046:  private void dumpLayoutInfo (GridBagLayoutInfo info)
1047:  {
1048:  System.out.println ("GridBagLayoutInfo:");
1049:  System.out.println ("cols: " + info.cols + ", rows: " + info.rows);
1050:  System.out.print ("colWidths: ");
1051:  dumpArray(info.colWidths);
1052:  System.out.print ("rowHeights: ");
1053:  dumpArray(info.rowHeights);
1054:  System.out.print ("colWeights: ");
1055:  dumpArray(info.colWeights);
1056:  System.out.print ("rowWeights: ");
1057:  dumpArray(info.rowWeights);
1058:  }
1059: 
1060:  private void dumpArray(int[] array)
1061:  {
1062:  String sep = "";
1063:  for(int i = 0; i < array.length; i++)
1064:  {
1065:  System.out.print(sep);
1066:  System.out.print(array[i]);
1067:  sep = ", ";
1068:  }
1069:  System.out.println();
1070:  }
1071: 
1072:  private void dumpArray(double[] array)
1073:  {
1074:  String sep = "";
1075:  for(int i = 0; i < array.length; i++)
1076:  {
1077:  System.out.print(sep);
1078:  System.out.print(array[i]);
1079:  sep = ", ";
1080:  }
1081:  System.out.println();
1082:  }
1083:  
1084:  /**
1085:  * @since 1.4
1086:  */
1087:  protected void arrangeGrid (Container parent)
1088:  {
1089:  ArrangeGrid (parent);
1090:  }
1091: 
1092:  /**
1093:  * @since 1.4
1094:  */
1095:  protected GridBagLayoutInfo getLayoutInfo (Container parent, int sizeflag)
1096:  {
1097:  return GetLayoutInfo (parent, sizeflag);
1098:  }
1099: 
1100:  /**
1101:  * Move and resize a rectangle according to a set of grid bag
1102:  * constraints. The x, y, width and height fields of the
1103:  * rectangle argument are adjusted to the new values.
1104:  *
1105:  * @param constraints position and size constraints
1106:  * @param r rectangle to be moved and resized
1107:  *
1108:  * @since 1.4
1109:  */
1110:  protected void adjustForGravity (GridBagConstraints constraints,
1111:  Rectangle r)
1112:  {
1113:  AdjustForGravity (constraints, r);
1114:  }
1115: }
Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)

AltStyle によって変換されたページ (->オリジナル) /