Imported GNU Classpath 0.20
[official-gcc.git] / libjava / classpath / java / awt / GridBagLayout.java
blob714e080d7b29925a10f88aa4686a68be47030f09
1 /* GridBagLayout - Layout manager for components according to GridBagConstraints
2 Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package java.awt;
41 import java.io.Serializable;
42 import java.util.ArrayList;
43 import java.util.HashMap;
44 import java.util.Hashtable;
46 /**
47 * @author Michael Koch (konqueror@gmx.de)
48 * @author Jeroen Frijters (jeroen@frijters.net)
50 public class GridBagLayout
51 implements Serializable, LayoutManager2
53 private static final long serialVersionUID = 8838754796412211005L;
55 protected static final int MINSIZE = 1;
56 protected static final int PREFERREDSIZE = 2;
57 protected static final int MAXGRIDSIZE = 512;
59 // comptable remembers the original contraints given to us.
60 // internalcomptable is used to keep track of modified constraint values
61 // that we calculate, particularly when we are given RELATIVE and
62 // REMAINDER constraints.
63 // Constraints kept in comptable are never modified, and constraints
64 // kept in internalcomptable can be modified internally only.
65 protected Hashtable comptable;
66 private Hashtable internalcomptable;
67 protected GridBagLayoutInfo layoutInfo;
68 protected GridBagConstraints defaultConstraints;
70 public double[] columnWeights;
71 public int[] columnWidths;
72 public double[] rowWeights;
73 public int[] rowHeights;
75 public GridBagLayout ()
77 this.comptable = new Hashtable();
78 this.internalcomptable = new Hashtable();
79 this.defaultConstraints= new GridBagConstraints();
82 /**
83 * Helper method to calc the sum of a range of elements in an int array.
85 private int sumIntArray (int[] array, int upto)
87 int result = 0;
89 for (int i = 0; i < upto; i++)
90 result += array [i];
92 return result;
95 /**
96 * Helper method to calc the sum of all elements in an int array.
98 private int sumIntArray (int[] array)
100 return sumIntArray(array, array.length);
104 * Helper method to calc the sum of all elements in an double array.
106 private double sumDoubleArray (double[] array)
108 double result = 0;
110 for (int i = 0; i < array.length; i++)
111 result += array [i];
113 return result;
116 public void addLayoutComponent (String name, Component component)
118 // do nothing here.
121 public void removeLayoutComponent (Component component)
123 // do nothing here
126 public void addLayoutComponent (Component component, Object constraints)
128 if (constraints == null)
129 return;
131 if (!(constraints instanceof GridBagConstraints))
132 throw new IllegalArgumentException("constraints "
133 + constraints
134 + " are not an instance of GridBagConstraints");
136 setConstraints (component, (GridBagConstraints) constraints);
139 public Dimension preferredLayoutSize (Container parent)
141 if (parent == null)
142 return new Dimension (0, 0);
144 GridBagLayoutInfo li = getLayoutInfo (parent, PREFERREDSIZE);
145 return getMinSize (parent, li);
148 public Dimension minimumLayoutSize (Container parent)
150 if (parent == null)
151 return new Dimension (0, 0);
153 GridBagLayoutInfo li = getLayoutInfo (parent, MINSIZE);
154 return getMinSize (parent, li);
157 public Dimension maximumLayoutSize (Container target)
159 return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE);
162 public void layoutContainer (Container parent)
164 arrangeGrid (parent);
167 public float getLayoutAlignmentX (Container target)
169 return Component.CENTER_ALIGNMENT;
172 public float getLayoutAlignmentY (Container target)
174 return Component.CENTER_ALIGNMENT;
177 public void invalidateLayout (Container target)
179 this.layoutInfo = null;
182 public void setConstraints (Component component,
183 GridBagConstraints constraints)
185 GridBagConstraints clone = (GridBagConstraints) constraints.clone();
187 if (clone.gridx < 0)
188 clone.gridx = GridBagConstraints.RELATIVE;
190 if (clone.gridy < 0)
191 clone.gridy = GridBagConstraints.RELATIVE;
193 if (clone.gridwidth == 0)
194 clone.gridwidth = GridBagConstraints.REMAINDER;
195 else if (clone.gridwidth < 0)
196 clone.gridwidth = 1;
198 if (clone.gridheight == 0)
199 clone.gridheight = GridBagConstraints.REMAINDER;
200 else if (clone.gridheight < 0)
201 clone.gridheight = 1;
203 comptable.put (component, clone);
206 public GridBagConstraints getConstraints (Component component)
208 return (GridBagConstraints) (lookupConstraints (component).clone());
211 protected GridBagConstraints lookupConstraints (Component component)
213 GridBagConstraints result = (GridBagConstraints) comptable.get (component);
215 if (result == null)
217 setConstraints (component, defaultConstraints);
218 result = (GridBagConstraints) comptable.get (component);
221 return result;
224 private GridBagConstraints lookupInternalConstraints (Component component)
226 GridBagConstraints result =
227 (GridBagConstraints) internalcomptable.get (component);
229 if (result == null)
231 result = (GridBagConstraints) lookupConstraints(component).clone();
232 internalcomptable.put (component, result);
235 return result;
239 * @since 1.1
241 public Point getLayoutOrigin ()
243 if (layoutInfo == null)
244 return new Point (0, 0);
246 return new Point (layoutInfo.pos_x, layoutInfo.pos_y);
250 * @since 1.1
252 public int[][] getLayoutDimensions ()
254 int[][] result = new int [2][];
255 if (layoutInfo == null)
257 result[0] = new int[0];
258 result[1] = new int[0];
260 return result;
263 result [0] = new int [layoutInfo.cols];
264 System.arraycopy (layoutInfo.colWidths, 0, result [0], 0, layoutInfo.cols);
265 result [1] = new int [layoutInfo.rows];
266 System.arraycopy (layoutInfo.rowHeights, 0, result [1], 0, layoutInfo.rows);
267 return result;
270 public double[][] getLayoutWeights ()
272 double[][] result = new double [2][];
273 if (layoutInfo == null)
275 result[0] = new double[0];
276 result[1] = new double[0];
278 return result;
281 result [0] = new double [layoutInfo.cols];
282 System.arraycopy (layoutInfo.colWeights, 0, result [0], 0, layoutInfo.cols);
283 result [1] = new double [layoutInfo.rows];
284 System.arraycopy (layoutInfo.rowWeights, 0, result [1], 0, layoutInfo.rows);
285 return result;
289 * @since 1.1
291 public Point location (int x, int y)
293 if (layoutInfo == null)
294 return new Point (0, 0);
296 int col;
297 int row;
298 int pixel_x = layoutInfo.pos_x;
299 int pixel_y = layoutInfo.pos_y;
301 for (col = 0; col < layoutInfo.cols; col++)
303 int w = layoutInfo.colWidths [col];
304 if (x < pixel_x + w)
305 break;
307 pixel_x += w;
310 for (row = 0; row < layoutInfo.rows; row++)
312 int h = layoutInfo.rowHeights [row];
313 if (y < pixel_y + h)
314 break;
316 pixel_y += h;
319 return new Point (col, row);
323 * Obsolete.
325 protected void AdjustForGravity (GridBagConstraints gbc, Rectangle rect)
327 // FIXME
328 throw new Error ("Not implemented");
332 * Obsolete.
334 protected void ArrangeGrid (Container parent)
336 Component[] components = parent.getComponents();
338 if (components.length == 0)
339 return;
341 GridBagLayoutInfo info = getLayoutInfo (parent, PREFERREDSIZE);
342 if (info.cols == 0 && info.rows == 0)
343 return;
345 // DEBUG
346 //dumpLayoutInfo (info);
348 // Calling setBounds on these components causes this layout to
349 // be invalidated, clearing the layout information cache,
350 // layoutInfo. So we wait until after this for loop to set
351 // layoutInfo.
352 for(int i = 0; i < components.length; i++)
354 Component component = components [i];
356 // If component is not visible we dont have to care about it.
357 if (!component.isVisible())
358 continue;
360 GridBagConstraints constraints =
361 lookupInternalConstraints(component);
363 int cellx = sumIntArray(info.colWidths, constraints.gridx);
364 int celly = sumIntArray(info.rowHeights, constraints.gridy);
365 int cellw = sumIntArray(info.colWidths,
366 constraints.gridx + constraints.gridwidth) - cellx;
367 int cellh = sumIntArray(info.rowHeights,
368 constraints.gridy + constraints.gridheight) - celly;
370 Insets insets = constraints.insets;
371 if (insets != null)
373 cellx += insets.left;
374 celly += insets.top;
375 cellw -= insets.left + insets.right;
376 cellh -= insets.top + insets.bottom;
379 Dimension dim = component.getPreferredSize();
381 // Note: Documentation says that padding is added on both sides, but
382 // visual inspection shows that the Sun implementation only adds it
383 // once, so we do the same.
384 dim.width += constraints.ipadx;
385 dim.height += constraints.ipady;
387 switch(constraints.fill)
389 case GridBagConstraints.HORIZONTAL:
390 dim.width = cellw;
391 break;
392 case GridBagConstraints.VERTICAL:
393 dim.height = cellh;
394 break;
395 case GridBagConstraints.BOTH:
396 dim.width = cellw;
397 dim.height = cellh;
398 break;
401 int x;
402 int y;
404 switch(constraints.anchor)
406 case GridBagConstraints.NORTH:
407 x = cellx + (cellw - dim.width) / 2;
408 y = celly;
409 break;
410 case GridBagConstraints.SOUTH:
411 x = cellx + (cellw - dim.width) / 2;
412 y = celly + cellh - dim.height;
413 break;
414 case GridBagConstraints.WEST:
415 x = cellx;
416 y = celly + (cellh - dim.height) / 2;
417 break;
418 case GridBagConstraints.EAST:
419 x = cellx + cellw - dim.width;
420 y = celly + (cellh - dim.height) / 2;
421 break;
422 case GridBagConstraints.NORTHEAST:
423 x = cellx + cellw - dim.width;
424 y = celly;
425 break;
426 case GridBagConstraints.NORTHWEST:
427 x = cellx;
428 y = celly;
429 break;
430 case GridBagConstraints.SOUTHEAST:
431 x = cellx + cellw - dim.width;
432 y = celly + cellh - dim.height;
433 break;
434 case GridBagConstraints.SOUTHWEST:
435 x = cellx;
436 y = celly + cellh - dim.height;
437 break;
438 default:
439 x = cellx + (cellw - dim.width) / 2;
440 y = celly + (cellh - dim.height) / 2;
441 break;
444 component.setBounds(info.pos_x + x, info.pos_y + y, dim.width, dim.height);
447 // DEBUG
448 //dumpLayoutInfo (info);
450 // Cache layout information.
451 layoutInfo = getLayoutInfo (parent, PREFERREDSIZE);
455 * Obsolete.
457 protected GridBagLayoutInfo GetLayoutInfo (Container parent, int sizeflag)
459 if (sizeflag != MINSIZE && sizeflag != PREFERREDSIZE)
460 throw new IllegalArgumentException();
462 Dimension parentDim = parent.getSize ();
463 Insets parentInsets = parent.getInsets ();
464 parentDim.width -= parentInsets.left + parentInsets.right;
465 parentDim.height -= parentInsets.top + parentInsets.bottom;
467 int current_y = 0;
468 int max_x = 0;
469 int max_y = 0;
471 // Guaranteed to contain the last component added to the given row
472 // or column, whose gridwidth/height is not REMAINDER.
473 HashMap lastInRow = new HashMap();
474 HashMap lastInCol = new HashMap();
476 Component[] components = parent.getComponents();
478 // Components sorted by gridwidths/heights,
479 // smallest to largest, with REMAINDER and RELATIVE at the end.
480 // These are useful when determining sizes and weights.
481 ArrayList sortedByWidth = new ArrayList(components.length);
482 ArrayList sortedByHeight = new ArrayList(components.length);
484 // STEP 1: first we figure out how many rows/columns
485 for (int i = 0; i < components.length; i++)
487 Component component = components [i];
489 // If component is not visible we dont have to care about it.
490 if (!component.isVisible())
491 continue;
493 // When looking up the constraint for the first time, check the
494 // original unmodified constraint. After the first time, always
495 // refer to the internal modified constraint.
496 GridBagConstraints originalConstraints = lookupConstraints (component);
497 GridBagConstraints constraints = (GridBagConstraints) originalConstraints.clone();
498 internalcomptable.put(component, constraints);
500 // Cases:
502 // 1. gridy == RELATIVE, gridx == RELATIVE
504 // use y as the row number; check for the next
505 // available slot at row y
507 // 2. only gridx == RELATIVE
509 // check for the next available slot at row gridy
511 // 3. only gridy == RELATIVE
513 // check for the next available slot at column gridx
515 // 4. neither gridx or gridy == RELATIVE
517 // nothing to check; just add it
520 // cases 1 and 2
521 if(constraints.gridx == GridBagConstraints.RELATIVE)
523 if (constraints.gridy == GridBagConstraints.RELATIVE)
524 constraints.gridy = current_y;
526 int x;
528 // Check the component that occupies the right-most spot in this
529 // row. We want to add this component after it.
530 // If this row is empty, add to the 0 position.
531 if (!lastInRow.containsKey(new Integer(constraints.gridy)))
532 x = 0;
533 else
535 Component lastComponent = (Component) lastInRow.get(new Integer(constraints.gridy));
536 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
537 x = lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth);
540 // Determine if this component will fit in the slot vertically.
541 // If not, bump it over to where it does fit.
542 for (int y = constraints.gridy + 1; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
544 if (lastInRow.containsKey(new Integer(y)))
546 Component lastComponent = (Component) lastInRow.get(new Integer(y));
547 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
548 x = Math.max (x,
549 lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth));
553 constraints.gridx = x;
555 // case 3
556 else if(constraints.gridy == GridBagConstraints.RELATIVE)
558 int y;
559 // Check the component that occupies the bottom-most spot in
560 // this column. We want to add this component below it.
561 // If this column is empty, add to the 0 position.
562 if (!lastInCol.containsKey(new Integer(constraints.gridx)))
563 y = 0;
564 else
566 Component lastComponent = (Component)lastInCol.get(new Integer(constraints.gridx));
567 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
568 y = lastConstraints.gridy + Math.max(1, lastConstraints.gridheight);
571 // Determine if this component will fit in the slot horizontally.
572 // If not, bump it down to where it does fit.
573 for (int x = constraints.gridx + 1; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
575 if (lastInCol.containsKey(new Integer(x)))
577 Component lastComponent = (Component) lastInCol.get(new Integer(x));
578 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
579 y = Math.max (y,
580 lastConstraints.gridy + Math.max(1, lastConstraints.gridheight));
584 constraints.gridy = y;
586 // case 4: do nothing
588 max_x = Math.max(max_x,
589 constraints.gridx + Math.max(1, constraints.gridwidth));
590 max_y = Math.max(max_y,
591 constraints.gridy + Math.max(1, constraints.gridheight));
593 sortBySpan(component, constraints.gridwidth, sortedByWidth, true);
594 sortBySpan(component, constraints.gridheight, sortedByHeight, false);
596 // Update our reference points for RELATIVE gridx and gridy.
597 if(constraints.gridwidth == GridBagConstraints.REMAINDER)
599 current_y = constraints.gridy + Math.max(1, constraints.gridheight);
601 else if (constraints.gridwidth != GridBagConstraints.REMAINDER)
603 for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
605 if(lastInRow.containsKey(new Integer(y)))
607 Component lastComponent = (Component) lastInRow.get(new Integer(y));
608 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
609 if (constraints.gridx > lastConstraints.gridx)
611 lastInRow.put(new Integer(y), component);
614 else
616 lastInRow.put(new Integer(y), component);
620 for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
622 if(lastInCol.containsKey(new Integer(x)))
624 Component lastComponent = (Component) lastInCol.get(new Integer(x));
625 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
626 if (constraints.gridy > lastConstraints.gridy)
628 lastInCol.put(new Integer(x), component);
631 else
633 lastInCol.put(new Integer(x), component);
637 } // end of STEP 1
639 GridBagLayoutInfo info = new GridBagLayoutInfo(max_x, max_y);
641 // Check if column widths and row heights are overridden.
643 for (int x = 0; x < max_x; x++)
645 if(columnWidths != null && columnWidths.length > x)
646 info.colWidths[x] = columnWidths[x];
647 if(columnWeights != null && columnWeights.length > x)
648 info.colWeights[x] = columnWeights[x];
651 for (int y = 0; y < max_y; y++)
653 if(rowHeights != null && rowHeights.length > y)
654 info.rowHeights[y] = rowHeights[y];
655 if(rowWeights != null && rowWeights.length > y)
656 info.rowWeights[y] = rowWeights[y];
659 // STEP 2: Fix up any cells with width/height as REMAINDER/RELATIVE.
660 for (int i = 0; i < components.length; i++)
662 Component component = components [i];
664 // If component is not visible we dont have to care about it.
665 if (!component.isVisible())
666 continue;
668 GridBagConstraints constraints = lookupInternalConstraints (component);
670 if(constraints.gridwidth == GridBagConstraints.REMAINDER || constraints.gridwidth == GridBagConstraints.RELATIVE)
672 if(constraints.gridwidth == GridBagConstraints.REMAINDER)
674 for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
676 if (lastInRow.containsKey(new Integer(y)))
678 Component lastComponent = (Component) lastInRow.get(new Integer(y));
679 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
681 if (lastConstraints.gridwidth == GridBagConstraints.RELATIVE)
683 constraints.gridx = max_x - 1;
684 break;
686 else
688 constraints.gridx = Math.max (constraints.gridx,
689 lastConstraints.gridx + Math.max (1, lastConstraints.gridwidth));
693 constraints.gridwidth = max_x - constraints.gridx;
695 else if (constraints.gridwidth == GridBagConstraints.RELATIVE)
697 constraints.gridwidth = max_x - constraints.gridx - 1;
700 // Re-sort
701 sortedByWidth.remove(sortedByWidth.indexOf(component));
702 sortBySpan(component, constraints.gridwidth, sortedByWidth, true);
705 if(constraints.gridheight == GridBagConstraints.REMAINDER || constraints.gridheight == GridBagConstraints.RELATIVE)
707 if(constraints.gridheight == GridBagConstraints.REMAINDER)
709 for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
711 if (lastInCol.containsKey(new Integer(x)))
713 Component lastComponent = (Component) lastInRow.get(new Integer(x));
714 if (lastComponent != null)
716 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
718 if (lastConstraints.gridheight == GridBagConstraints.RELATIVE)
720 constraints.gridy = max_y - 1;
721 break;
723 else
725 constraints.gridy = Math.max (constraints.gridy,
726 lastConstraints.gridy + Math.max (1, lastConstraints.gridheight));
731 constraints.gridheight = max_y - constraints.gridy;
733 else if (constraints.gridheight == GridBagConstraints.RELATIVE)
735 constraints.gridheight = max_y - constraints.gridy - 1;
738 // Re-sort
739 sortedByHeight.remove(sortedByHeight.indexOf(component));
740 sortBySpan(component, constraints.gridheight, sortedByHeight, false);
742 } // end of STEP 2
744 // STEP 3: Determine sizes and weights for columns.
745 for (int i = 0; i < sortedByWidth.size(); i++)
747 Component component = (Component) sortedByWidth.get(i);
749 // If component is not visible we dont have to care about it.
750 if (!component.isVisible())
751 continue;
753 GridBagConstraints constraints = lookupInternalConstraints (component);
755 int width = (sizeflag == PREFERREDSIZE) ?
756 component.getPreferredSize().width :
757 component.getMinimumSize().width;
759 if(constraints.insets != null)
760 width += constraints.insets.left + constraints.insets.right;
762 width += constraints.ipadx;
764 distributeSizeAndWeight(width,
765 constraints.weightx,
766 constraints.gridx,
767 constraints.gridwidth,
768 info.colWidths,
769 info.colWeights);
770 } // end of STEP 3
772 // STEP 4: Determine sizes and weights for rows.
773 for (int i = 0; i < sortedByHeight.size(); i++)
775 Component component = (Component) sortedByHeight.get(i);
777 // If component is not visible we dont have to care about it.
778 if (!component.isVisible())
779 continue;
781 GridBagConstraints constraints = lookupInternalConstraints (component);
783 int height = (sizeflag == PREFERREDSIZE) ?
784 component.getPreferredSize().height :
785 component.getMinimumSize().height;
787 if(constraints.insets != null)
788 height += constraints.insets.top + constraints.insets.bottom;
790 height += constraints.ipady;
792 distributeSizeAndWeight(height,
793 constraints.weighty,
794 constraints.gridy,
795 constraints.gridheight,
796 info.rowHeights,
797 info.rowWeights);
798 } // end of STEP 4
800 // Adjust cell sizes iff parent size not zero.
801 if (parentDim.width > 0 && parentDim.height > 0)
803 calcCellSizes (info.colWidths, info.colWeights, parentDim.width);
804 calcCellSizes (info.rowHeights, info.rowWeights, parentDim.height);
807 int totalWidth = sumIntArray(info.colWidths);
808 int totalHeight = sumIntArray(info.rowHeights);
810 // Make sure pos_x and pos_y are never negative.
811 if (totalWidth >= parentDim.width)
812 info.pos_x = parentInsets.left;
813 else
814 info.pos_x = parentInsets.left + (parentDim.width - totalWidth) / 2;
816 if (totalHeight >= parentDim.height)
817 info.pos_y = parentInsets.top;
818 else
819 info.pos_y = parentInsets.top + (parentDim.height - totalHeight) / 2;
821 // DEBUG
822 //dumpLayoutInfo (info);
824 return info;
828 * Obsolete.
830 protected Dimension GetMinSize (Container parent, GridBagLayoutInfo info)
832 if (parent == null || info == null)
833 return new Dimension (0, 0);
835 Insets insets = parent.getInsets();
836 int width = sumIntArray (info.colWidths) + insets.left + insets.right;
837 int height = sumIntArray (info.rowHeights) + insets.top + insets.bottom;
838 return new Dimension (width, height);
842 * @since 1.4
844 protected Dimension getMinSize (Container parent, GridBagLayoutInfo info)
846 return GetMinSize (parent, info);
850 * Helper method used by GetLayoutInfo to keep components sorted, either
851 * by gridwidth or gridheight.
853 * @param component Component to add to the sorted list.
854 * @param span Either the component's gridwidth or gridheight.
855 * @param list <code>ArrayList</code> of components, sorted by
856 * their span.
857 * @param sortByWidth Flag indicating sorting index. If true, sort by
858 * width. Otherwise, sort by height.
859 * FIXME: Use a better sorting algorithm.
861 private void sortBySpan (Component component, int span, ArrayList list, boolean sortByWidth)
863 if (span == GridBagConstraints.REMAINDER
864 || span == GridBagConstraints.RELATIVE)
866 // Put all RELATIVE and REMAINDER components at the end.
867 list.add(component);
869 else
871 int i = 0;
872 if (list.size() > 0)
874 GridBagConstraints gbc = lookupInternalConstraints((Component) list.get(i));
875 int otherspan = sortByWidth ?
876 gbc.gridwidth :
877 gbc.gridheight;
878 while (otherspan != GridBagConstraints.REMAINDER
879 && otherspan != GridBagConstraints.RELATIVE
880 && span >= otherspan)
882 i++;
883 if (i < list.size())
885 gbc = lookupInternalConstraints((Component) list.get(i));
886 otherspan = sortByWidth ?
887 gbc.gridwidth :
888 gbc.gridheight;
890 else
891 break;
894 list.add(i, component);
899 * Helper method used by GetLayoutInfo to distribute a component's size
900 * and weight.
902 * @param size Preferred size of component, with inset and padding
903 * already added.
904 * @param weight Weight of component.
905 * @param start Starting position of component. Either
906 * constraints.gridx or gridy.
907 * @param span Span of component. either contraints.gridwidth or
908 * gridheight.
909 * @param sizes Sizes of rows or columns.
910 * @param weights Weights of rows or columns.
912 private void distributeSizeAndWeight (int size, double weight,
913 int start, int span,
914 int[] sizes, double[] weights)
916 if (span == 1)
918 sizes[start] = Math.max(sizes[start], size);
919 weights[start] = Math.max(weights[start], weight);
921 else if (span > 1)
923 int numOccupied = span;
924 int lastOccupied = -1;
926 for(int i = start; i < start + span; i++)
928 if (sizes[i] == 0.0)
929 numOccupied--;
930 else
932 size -= sizes[i];
933 lastOccupied = i;
937 // A component needs to occupy at least one row.
938 if(numOccupied == 0)
939 sizes[start + span - 1] = size;
940 else if (size > 0)
941 sizes[lastOccupied] += size;
943 calcCellWeights(weight, weights, start, span);
948 * Helper method used by GetLayoutInfo to calculate weight distribution.
949 * @param weight Weight of component.
950 * @param weights Weights of rows/columns.
951 * @param start Starting position of component in grid (gridx/gridy).
952 * @param span Span of component (gridwidth/gridheight).
954 private void calcCellWeights (double weight, double[] weights, int start, int span)
956 double totalWeight = 0.0;
957 for(int k = start; k < start + span; k++)
958 totalWeight += weights[k];
960 if(weight > totalWeight)
962 if (totalWeight == 0.0)
964 weights[start + span - 1] += weight;
966 else
968 double diff = weight - totalWeight ;
969 double remaining = diff;
971 for(int k = start; k < start + span; k++)
973 double extraWeight = diff * weights[k] / totalWeight;
974 weights[k] += extraWeight;
975 remaining -= extraWeight;
978 if (remaining > 0.0 && weights[start + span - 1] != 0.0)
980 weights[start + span - 1] += remaining;
987 * Helper method used by GetLayoutInfo to distribute extra space
988 * based on weight distribution.
990 * @param sizes Sizes of rows/columns.
991 * @param weights Weights of rows/columns.
992 * @param range Dimension of container.
994 private void calcCellSizes (int[] sizes, double[] weights, int range)
996 int totalSize = sumIntArray (sizes);
997 double totalWeight = sumDoubleArray (weights);
999 int diff = range - totalSize;
1001 if (diff == 0)
1002 return;
1004 for (int i = 0; i < sizes.length; i++)
1006 int newsize = (int) (sizes[i] + (((double) diff) * weights [i] / totalWeight ));
1008 if (newsize > 0)
1009 sizes[i] = newsize;
1013 private void dumpLayoutInfo (GridBagLayoutInfo info)
1015 System.out.println ("GridBagLayoutInfo:");
1016 System.out.println ("cols: " + info.cols + ", rows: " + info.rows);
1017 System.out.print ("colWidths: ");
1018 dumpArray(info.colWidths);
1019 System.out.print ("rowHeights: ");
1020 dumpArray(info.rowHeights);
1021 System.out.print ("colWeights: ");
1022 dumpArray(info.colWeights);
1023 System.out.print ("rowWeights: ");
1024 dumpArray(info.rowWeights);
1027 private void dumpArray(int[] array)
1029 String sep = "";
1030 for(int i = 0; i < array.length; i++)
1032 System.out.print(sep);
1033 System.out.print(array[i]);
1034 sep = ", ";
1036 System.out.println();
1039 private void dumpArray(double[] array)
1041 String sep = "";
1042 for(int i = 0; i < array.length; i++)
1044 System.out.print(sep);
1045 System.out.print(array[i]);
1046 sep = ", ";
1048 System.out.println();
1052 * @since 1.4
1054 protected void arrangeGrid (Container parent)
1056 ArrangeGrid (parent);
1060 * @since 1.4
1062 protected GridBagLayoutInfo getLayoutInfo (Container parent, int sizeflag)
1064 return GetLayoutInfo (parent, sizeflag);
1068 * @since 1.4
1070 protected void adjustForGravity (GridBagConstraints gbc, Rectangle rect)
1072 AdjustForGravity (gbc, rect);