Merge from the pain train
[official-gcc.git] / libjava / java / awt / GridBagLayout.java
blob0ee996ce71574f4428f84df1b0b6b8112e203774
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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();
134 setConstraints (component, (GridBagConstraints) constraints);
137 public Dimension preferredLayoutSize (Container parent)
139 if (parent == null)
140 return new Dimension (0, 0);
142 GridBagLayoutInfo li = getLayoutInfo (parent, PREFERREDSIZE);
143 return getMinSize (parent, li);
146 public Dimension minimumLayoutSize (Container parent)
148 if (parent == null)
149 return new Dimension (0, 0);
151 GridBagLayoutInfo li = getLayoutInfo (parent, MINSIZE);
152 return getMinSize (parent, li);
155 public Dimension maximumLayoutSize (Container target)
157 return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE);
160 public void layoutContainer (Container parent)
162 arrangeGrid (parent);
165 public float getLayoutAlignmentX (Container target)
167 return Component.CENTER_ALIGNMENT;
170 public float getLayoutAlignmentY (Container target)
172 return Component.CENTER_ALIGNMENT;
175 public void invalidateLayout (Container target)
177 this.layoutInfo = null;
180 public void setConstraints (Component component,
181 GridBagConstraints constraints)
183 GridBagConstraints clone = (GridBagConstraints) constraints.clone();
185 if (clone.gridx < 0)
186 clone.gridx = GridBagConstraints.RELATIVE;
188 if (clone.gridy < 0)
189 clone.gridy = GridBagConstraints.RELATIVE;
191 if (clone.gridwidth == 0)
192 clone.gridwidth = GridBagConstraints.REMAINDER;
193 else if (clone.gridwidth < 0
194 && clone.gridwidth != GridBagConstraints.REMAINDER
195 && clone.gridwidth != GridBagConstraints.RELATIVE)
196 clone.gridwidth = 1;
198 if (clone.gridheight == 0)
199 clone.gridheight = GridBagConstraints.REMAINDER;
200 else if (clone.gridheight < 0
201 && clone.gridheight != GridBagConstraints.REMAINDER
202 && clone.gridheight != GridBagConstraints.RELATIVE)
203 clone.gridheight = 1;
205 comptable.put (component, clone);
208 public GridBagConstraints getConstraints (Component component)
210 return (GridBagConstraints) (lookupConstraints (component).clone());
213 protected GridBagConstraints lookupConstraints (Component component)
215 GridBagConstraints result = (GridBagConstraints) comptable.get (component);
217 if (result == null)
219 setConstraints (component, defaultConstraints);
220 result = (GridBagConstraints) comptable.get (component);
223 return result;
226 private GridBagConstraints lookupInternalConstraints (Component component)
228 GridBagConstraints result =
229 (GridBagConstraints) internalcomptable.get (component);
231 if (result == null)
233 result = (GridBagConstraints) lookupConstraints(component).clone();
234 internalcomptable.put (component, result);
237 return result;
241 * @since 1.1
243 public Point getLayoutOrigin ()
245 if (layoutInfo == null)
246 return new Point (0, 0);
248 return new Point (layoutInfo.pos_x, layoutInfo.pos_y);
252 * @since 1.1
254 public int[][] getLayoutDimensions ()
256 int[][] result = new int [2][];
257 if (layoutInfo == null)
259 result[0] = new int[0];
260 result[1] = new int[0];
262 return result;
265 result [0] = new int [layoutInfo.cols];
266 System.arraycopy (layoutInfo.colWidths, 0, result [0], 0, layoutInfo.cols);
267 result [1] = new int [layoutInfo.rows];
268 System.arraycopy (layoutInfo.rowHeights, 0, result [1], 0, layoutInfo.rows);
269 return result;
272 public double[][] getLayoutWeights ()
274 double[][] result = new double [2][];
275 if (layoutInfo == null)
277 result[0] = new double[0];
278 result[1] = new double[0];
280 return result;
283 result [0] = new double [layoutInfo.cols];
284 System.arraycopy (layoutInfo.colWeights, 0, result [0], 0, layoutInfo.cols);
285 result [1] = new double [layoutInfo.rows];
286 System.arraycopy (layoutInfo.rowWeights, 0, result [1], 0, layoutInfo.rows);
287 return result;
291 * @since 1.1
293 public Point location (int x, int y)
295 if (layoutInfo == null)
296 return new Point (0, 0);
298 int col;
299 int row;
300 int pixel_x = layoutInfo.pos_x;
301 int pixel_y = layoutInfo.pos_y;
303 for (col = 0; col < layoutInfo.cols; col++)
305 int w = layoutInfo.colWidths [col];
306 if (x < pixel_x + w)
307 break;
309 pixel_x += w;
312 for (row = 0; row < layoutInfo.rows; row++)
314 int h = layoutInfo.rowHeights [row];
315 if (y < pixel_y + h)
316 break;
318 pixel_y += h;
321 return new Point (col, row);
325 * Obsolete.
327 protected void AdjustForGravity (GridBagConstraints gbc, Rectangle rect)
329 // FIXME
330 throw new Error ("Not implemented");
334 * Obsolete.
336 protected void ArrangeGrid (Container parent)
338 Component[] components = parent.getComponents();
340 if (components.length == 0)
341 return;
343 GridBagLayoutInfo info = getLayoutInfo (parent, PREFERREDSIZE);
344 if (info.cols == 0 && info.rows == 0)
345 return;
346 layoutInfo = info;
348 // DEBUG
349 //dumpLayoutInfo (layoutInfo);
351 for(int i = 0; i < components.length; i++)
353 Component component = components [i];
355 // If component is not visible we dont have to care about it.
356 if (!component.isVisible())
357 continue;
359 GridBagConstraints constraints =
360 lookupInternalConstraints(component);
362 int cellx = sumIntArray(layoutInfo.colWidths, constraints.gridx);
363 int celly = sumIntArray(layoutInfo.rowHeights, constraints.gridy);
364 int cellw = sumIntArray(layoutInfo.colWidths,
365 constraints.gridx + constraints.gridwidth) - cellx;
366 int cellh = sumIntArray(layoutInfo.rowHeights,
367 constraints.gridy + constraints.gridheight) - celly;
369 Insets insets = constraints.insets;
370 if (insets != null)
372 cellx += insets.left;
373 celly += insets.top;
374 cellw -= insets.left + insets.right;
375 cellh -= insets.top + insets.bottom;
378 Dimension dim = component.getPreferredSize();
380 // Note: Documentation says that padding is added on both sides, but
381 // visual inspection shows that the Sun implementation only adds it
382 // once, so we do the same.
383 dim.width += constraints.ipadx;
384 dim.height += constraints.ipady;
386 switch(constraints.fill)
388 case GridBagConstraints.HORIZONTAL:
389 dim.width = cellw;
390 break;
391 case GridBagConstraints.VERTICAL:
392 dim.height = cellh;
393 break;
394 case GridBagConstraints.BOTH:
395 dim.width = cellw;
396 dim.height = cellh;
397 break;
400 int x;
401 int y;
403 switch(constraints.anchor)
405 case GridBagConstraints.NORTH:
406 x = cellx + (cellw - dim.width) / 2;
407 y = celly;
408 break;
409 case GridBagConstraints.SOUTH:
410 x = cellx + (cellw - dim.width) / 2;
411 y = celly + cellh - dim.height;
412 break;
413 case GridBagConstraints.WEST:
414 x = cellx;
415 y = celly + (cellh - dim.height) / 2;
416 break;
417 case GridBagConstraints.EAST:
418 x = cellx + cellw - dim.width;
419 y = celly + (cellh - dim.height) / 2;
420 break;
421 case GridBagConstraints.NORTHEAST:
422 x = cellx + cellw - dim.width;
423 y = celly;
424 break;
425 case GridBagConstraints.NORTHWEST:
426 x = cellx;
427 y = celly;
428 break;
429 case GridBagConstraints.SOUTHEAST:
430 x = cellx + cellw - dim.width;
431 y = celly + cellh - dim.height;
432 break;
433 case GridBagConstraints.SOUTHWEST:
434 x = cellx;
435 y = celly + cellh - dim.height;
436 break;
437 default:
438 x = cellx + (cellw - dim.width) / 2;
439 y = celly + (cellh - dim.height) / 2;
440 break;
443 component.setBounds(layoutInfo.pos_x + x, layoutInfo.pos_y + y, dim.width, dim.height);
446 // DEBUG
447 //dumpLayoutInfo (layoutInfo);
451 * Obsolete.
453 protected GridBagLayoutInfo GetLayoutInfo (Container parent, int sizeflag)
455 if (sizeflag != MINSIZE && sizeflag != PREFERREDSIZE)
456 throw new IllegalArgumentException();
458 Dimension parentDim = parent.getSize ();
459 Insets parentInsets = parent.getInsets ();
460 parentDim.width -= parentInsets.left + parentInsets.right;
461 parentDim.height -= parentInsets.top + parentInsets.bottom;
463 int current_y = 0;
464 int max_x = 0;
465 int max_y = 0;
467 // Guaranteed to contain the last component added to the given row
468 // or column, whose gridwidth/height is not REMAINDER.
469 HashMap lastInRow = new HashMap();
470 HashMap lastInCol = new HashMap();
472 Component[] components = parent.getComponents();
474 // Components sorted by gridwidths/heights,
475 // smallest to largest, with REMAINDER and RELATIVE at the end.
476 // These are useful when determining sizes and weights.
477 ArrayList sortedByWidth = new ArrayList(components.length);
478 ArrayList sortedByHeight = new ArrayList(components.length);
480 // STEP 1: first we figure out how many rows/columns
481 for (int i = 0; i < components.length; i++)
483 Component component = components [i];
485 // If component is not visible we dont have to care about it.
486 if (!component.isVisible())
487 continue;
489 // When looking up the constraint for the first time, check the
490 // original unmodified constraint. After the first time, always
491 // refer to the internal modified constraint.
492 GridBagConstraints originalConstraints = lookupConstraints (component);
493 GridBagConstraints constraints = (GridBagConstraints) originalConstraints.clone();
494 internalcomptable.put(component, constraints);
496 // Cases:
498 // 1. gridy == RELATIVE, gridx == RELATIVE
500 // use y as the row number; check for the next
501 // available slot at row y
503 // 2. only gridx == RELATIVE
505 // check for the next available slot at row gridy
507 // 3. only gridy == RELATIVE
509 // check for the next available slot at column gridx
511 // 4. neither gridx or gridy == RELATIVE
513 // nothing to check; just add it
516 // cases 1 and 2
517 if(constraints.gridx == GridBagConstraints.RELATIVE)
519 if (constraints.gridy == GridBagConstraints.RELATIVE)
520 constraints.gridy = current_y;
522 int x;
524 // Check the component that occupies the right-most spot in this
525 // row. We want to add this component after it.
526 // If this row is empty, add to the 0 position.
527 if (!lastInRow.containsKey(new Integer(constraints.gridy)))
528 x = 0;
529 else
531 Component lastComponent = (Component) lastInRow.get(new Integer(constraints.gridy));
532 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
533 x = lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth);
536 // Determine if this component will fit in the slot vertically.
537 // If not, bump it over to where it does fit.
538 for (int y = constraints.gridy + 1; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
540 if (lastInRow.containsKey(new Integer(y)))
542 Component lastComponent = (Component) lastInRow.get(new Integer(y));
543 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
544 x = Math.max (x,
545 lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth));
549 constraints.gridx = x;
551 // case 3
552 else if(constraints.gridy == GridBagConstraints.RELATIVE)
554 int y;
555 // Check the component that occupies the bottom-most spot in
556 // this column. We want to add this component below it.
557 // If this column is empty, add to the 0 position.
558 if (!lastInCol.containsKey(new Integer(constraints.gridx)))
559 y = 0;
560 else
562 Component lastComponent = (Component)lastInCol.get(new Integer(constraints.gridx));
563 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
564 y = lastConstraints.gridy + Math.max(1, lastConstraints.gridheight);
567 // Determine if this component will fit in the slot horizontally.
568 // If not, bump it down to where it does fit.
569 for (int x = constraints.gridx + 1; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
571 if (lastInCol.containsKey(new Integer(x)))
573 Component lastComponent = (Component) lastInCol.get(new Integer(x));
574 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
575 y = Math.max (y,
576 lastConstraints.gridy + Math.max(1, lastConstraints.gridheight));
580 constraints.gridy = y;
582 // case 4: do nothing
584 max_x = Math.max(max_x,
585 constraints.gridx + Math.max(1, constraints.gridwidth));
586 max_y = Math.max(max_y,
587 constraints.gridy + Math.max(1, constraints.gridheight));
589 sortBySpan(component, constraints.gridwidth, sortedByWidth, true);
590 sortBySpan(component, constraints.gridheight, sortedByHeight, false);
592 // Update our reference points for RELATIVE gridx and gridy.
593 if(constraints.gridwidth == GridBagConstraints.REMAINDER)
595 current_y = constraints.gridy + Math.max(1, constraints.gridheight);
597 else if (constraints.gridwidth != GridBagConstraints.REMAINDER)
599 for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
601 if(lastInRow.containsKey(new Integer(y)))
603 Component lastComponent = (Component) lastInRow.get(new Integer(y));
604 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
605 if (constraints.gridx > lastConstraints.gridx)
607 lastInRow.put(new Integer(y), component);
610 else
612 lastInRow.put(new Integer(y), component);
616 for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
618 if(lastInCol.containsKey(new Integer(x)))
620 Component lastComponent = (Component) lastInCol.get(new Integer(x));
621 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
622 if (constraints.gridy > lastConstraints.gridy)
624 lastInCol.put(new Integer(x), component);
627 else
629 lastInCol.put(new Integer(x), component);
633 } // end of STEP 1
635 GridBagLayoutInfo info = new GridBagLayoutInfo(max_x, max_y);
637 // Check if column widths and row heights are overridden.
639 for (int x = 0; x < max_x; x++)
641 if(columnWidths != null && columnWidths.length > x)
642 info.colWidths[x] = columnWidths[x];
643 if(columnWeights != null && columnWeights.length > x)
644 info.colWeights[x] = columnWeights[x];
647 for (int y = 0; y < max_y; y++)
649 if(rowHeights != null && rowHeights.length > y)
650 info.rowHeights[y] = rowHeights[y];
651 if(rowWeights != null && rowWeights.length > y)
652 info.rowWeights[y] = rowWeights[y];
655 // STEP 2: Fix up any cells with width/height as REMAINDER/RELATIVE.
656 for (int i = 0; i < components.length; i++)
658 Component component = components [i];
660 // If component is not visible we dont have to care about it.
661 if (!component.isVisible())
662 continue;
664 GridBagConstraints constraints = lookupInternalConstraints (component);
666 if(constraints.gridwidth == GridBagConstraints.REMAINDER || constraints.gridwidth == GridBagConstraints.RELATIVE)
668 if(constraints.gridwidth == GridBagConstraints.REMAINDER)
670 for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
672 if (lastInRow.containsKey(new Integer(y)))
674 Component lastComponent = (Component) lastInRow.get(new Integer(y));
675 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
677 if (lastConstraints.gridwidth == GridBagConstraints.RELATIVE)
679 constraints.gridx = max_x - 1;
680 break;
682 else
684 constraints.gridx = Math.max (constraints.gridx,
685 lastConstraints.gridx + Math.max (1, lastConstraints.gridwidth));
689 constraints.gridwidth = max_x - constraints.gridx;
691 else if (constraints.gridwidth == GridBagConstraints.RELATIVE)
693 constraints.gridwidth = max_x - constraints.gridx - 1;
696 // Re-sort
697 sortedByWidth.remove(sortedByWidth.indexOf(component));
698 sortBySpan(component, constraints.gridwidth, sortedByWidth, true);
701 if(constraints.gridheight == GridBagConstraints.REMAINDER || constraints.gridheight == GridBagConstraints.RELATIVE)
703 if(constraints.gridheight == GridBagConstraints.REMAINDER)
705 for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
707 if (lastInCol.containsKey(new Integer(x)))
709 Component lastComponent = (Component) lastInRow.get(new Integer(x));
710 GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
712 if (lastConstraints.gridheight == GridBagConstraints.RELATIVE)
714 constraints.gridy = max_y - 1;
715 break;
717 else
719 constraints.gridy = Math.max (constraints.gridy,
720 lastConstraints.gridy + Math.max (1, lastConstraints.gridheight));
724 constraints.gridheight = max_y - constraints.gridy;
726 else if (constraints.gridheight == GridBagConstraints.RELATIVE)
728 constraints.gridheight = max_y - constraints.gridy - 1;
731 // Re-sort
732 sortedByHeight.remove(sortedByHeight.indexOf(component));
733 sortBySpan(component, constraints.gridheight, sortedByHeight, false);
735 } // end of STEP 2
737 // STEP 3: Determine sizes and weights for columns.
738 for (int i = 0; i < sortedByWidth.size(); i++)
740 Component component = (Component) sortedByWidth.get(i);
742 // If component is not visible we dont have to care about it.
743 if (!component.isVisible())
744 continue;
746 GridBagConstraints constraints = lookupInternalConstraints (component);
748 int width = (sizeflag == PREFERREDSIZE) ?
749 component.getPreferredSize().width :
750 component.getMinimumSize().width;
752 if(constraints.insets != null)
753 width += constraints.insets.left + constraints.insets.right;
755 width += constraints.ipadx;
757 distributeSizeAndWeight(width,
758 constraints.weightx,
759 constraints.gridx,
760 constraints.gridwidth,
761 info.colWidths,
762 info.colWeights);
763 } // end of STEP 3
765 // STEP 4: Determine sizes and weights for rows.
766 for (int i = 0; i < sortedByHeight.size(); i++)
768 Component component = (Component) sortedByHeight.get(i);
770 // If component is not visible we dont have to care about it.
771 if (!component.isVisible())
772 continue;
774 GridBagConstraints constraints = lookupInternalConstraints (component);
776 int height = (sizeflag == PREFERREDSIZE) ?
777 component.getPreferredSize().height :
778 component.getMinimumSize().height;
780 if(constraints.insets != null)
781 height += constraints.insets.top + constraints.insets.bottom;
783 height += constraints.ipady;
785 distributeSizeAndWeight(height,
786 constraints.weighty,
787 constraints.gridy,
788 constraints.gridheight,
789 info.rowHeights,
790 info.rowWeights);
791 } // end of STEP 4
793 // Adjust cell sizes iff parent size not zero.
794 if (parentDim.width > 0 && parentDim.height > 0)
796 calcCellSizes (info.colWidths, info.colWeights, parentDim.width);
797 calcCellSizes (info.rowHeights, info.rowWeights, parentDim.height);
800 int totalWidth = sumIntArray(info.colWidths);
801 int totalHeight = sumIntArray(info.rowHeights);
803 // Make sure pos_x and pos_y are never negative.
804 if (totalWidth >= parentDim.width)
805 info.pos_x = parentInsets.left;
806 else
807 info.pos_x = parentInsets.left + (parentDim.width - totalWidth) / 2;
809 if (totalHeight >= parentDim.height)
810 info.pos_y = parentInsets.top;
811 else
812 info.pos_y = parentInsets.top + (parentDim.height - totalHeight) / 2;
814 // DEBUG
815 //dumpLayoutInfo (info);
817 return info;
821 * Obsolete.
823 protected Dimension GetMinSize (Container parent, GridBagLayoutInfo info)
825 if (parent == null || info == null)
826 return new Dimension (0, 0);
828 Insets insets = parent.getInsets();
829 int width = sumIntArray (info.colWidths) + insets.left + insets.right;
830 int height = sumIntArray (info.rowHeights) + insets.top + insets.bottom;
831 return new Dimension (width, height);
835 * @since 1.4
837 protected Dimension getMinSize (Container parent, GridBagLayoutInfo info)
839 return GetMinSize (parent, info);
843 * Helper method used by GetLayoutInfo to keep components sorted, either
844 * by gridwidth or gridheight.
846 * @param component Component to add to the sorted list.
847 * @param span Either the component's gridwidth or gridheight.
848 * @param list <code>ArrayList</code> of components, sorted by
849 * their span.
850 * @param sortByWidth Flag indicating sorting index. If true, sort by
851 * width. Otherwise, sort by height.
852 * FIXME: Use a better sorting algorithm.
854 private void sortBySpan (Component component, int span, ArrayList list, boolean sortByWidth)
856 if (span == GridBagConstraints.REMAINDER
857 || span == GridBagConstraints.RELATIVE)
859 // Put all RELATIVE and REMAINDER components at the end.
860 list.add(component);
862 else
864 int i = 0;
865 if (list.size() > 0)
867 GridBagConstraints gbc = lookupInternalConstraints((Component) list.get(i));
868 int otherspan = sortByWidth ?
869 gbc.gridwidth :
870 gbc.gridheight;
871 while (otherspan != GridBagConstraints.REMAINDER
872 && otherspan != GridBagConstraints.RELATIVE
873 && span >= otherspan)
875 i++;
876 if (i < list.size())
878 gbc = lookupInternalConstraints((Component) list.get(i));
879 otherspan = sortByWidth ?
880 gbc.gridwidth :
881 gbc.gridheight;
883 else
884 break;
887 list.add(i, component);
892 * Helper method used by GetLayoutInfo to distribute a component's size
893 * and weight.
895 * @param size Preferred size of component, with inset and padding
896 * already added.
897 * @param weight Weight of component.
898 * @param start Starting position of component. Either
899 * constraints.gridx or gridy.
900 * @param span Span of component. either contraints.gridwidth or
901 * gridheight.
902 * @param sizes Sizes of rows or columns.
903 * @param weights Weights of rows or columns.
905 private void distributeSizeAndWeight (int size, double weight,
906 int start, int span,
907 int[] sizes, double[] weights)
909 if (span == 1)
911 sizes[start] = Math.max(sizes[start], size);
912 weights[start] = Math.max(weights[start], weight);
914 else
916 int numOccupied = span;
917 int lastOccupied = -1;
919 for(int i = start; i < start + span; i++)
921 if (sizes[i] == 0.0)
922 numOccupied--;
923 else
925 size -= sizes[i];
926 lastOccupied = i;
930 // A component needs to occupy at least one row.
931 if(numOccupied == 0)
932 sizes[start + span - 1] = size;
933 else if (size > 0)
934 sizes[lastOccupied] += size;
936 calcCellWeights(weight, weights, start, span);
941 * Helper method used by GetLayoutInfo to calculate weight distribution.
942 * @param weight Weight of component.
943 * @param weights Weights of rows/columns.
944 * @param start Starting position of component in grid (gridx/gridy).
945 * @param span Span of component (gridwidth/gridheight).
947 private void calcCellWeights (double weight, double[] weights, int start, int span)
949 double totalWeight = 0.0;
950 for(int k = start; k < start + span; k++)
951 totalWeight += weights[k];
953 if(weight > totalWeight)
955 if (totalWeight == 0.0)
957 weights[start + span - 1] += weight;
959 else
961 double diff = weight - totalWeight ;
962 double remaining = diff;
964 for(int k = start; k < start + span; k++)
966 double extraWeight = diff * weights[k] / totalWeight;
967 weights[k] += extraWeight;
968 remaining -= extraWeight;
971 if (remaining > 0.0 && weights[start + span - 1] != 0.0)
973 weights[start + span - 1] += remaining;
980 * Helper method used by GetLayoutInfo to distribute extra space
981 * based on weight distribution.
983 * @param sizes Sizes of rows/columns.
984 * @param weights Weights of rows/columns.
985 * @param range Dimension of container.
987 private void calcCellSizes (int[] sizes, double[] weights, int range)
989 int totalSize = sumIntArray (sizes);
990 double totalWeight = sumDoubleArray (weights);
992 int diff = range - totalSize;
994 if (diff == 0)
995 return;
997 for (int i = 0; i < sizes.length; i++)
999 int newsize = (int) (sizes[i] + (((double) diff) * weights [i] / totalWeight ));
1001 if (newsize > 0)
1002 sizes[i] = newsize;
1006 private void dumpLayoutInfo (GridBagLayoutInfo info)
1008 System.out.println ("GridBagLayoutInfo:");
1009 System.out.println ("cols: " + info.cols + ", rows: " + info.rows);
1010 System.out.print ("colWidths: ");
1011 dumpArray(info.colWidths);
1012 System.out.print ("rowHeights: ");
1013 dumpArray(info.rowHeights);
1014 System.out.print ("colWeights: ");
1015 dumpArray(info.colWeights);
1016 System.out.print ("rowWeights: ");
1017 dumpArray(info.rowWeights);
1020 private void dumpArray(int[] array)
1022 String sep = "";
1023 for(int i = 0; i < array.length; i++)
1025 System.out.print(sep);
1026 System.out.print(array[i]);
1027 sep = ", ";
1029 System.out.println();
1032 private void dumpArray(double[] array)
1034 String sep = "";
1035 for(int i = 0; i < array.length; i++)
1037 System.out.print(sep);
1038 System.out.print(array[i]);
1039 sep = ", ";
1041 System.out.println();
1045 * @since 1.4
1047 protected void arrangeGrid (Container parent)
1049 ArrangeGrid (parent);
1053 * @since 1.4
1055 protected GridBagLayoutInfo getLayoutInfo (Container parent, int sizeflag)
1057 return GetLayoutInfo (parent, sizeflag);
1061 * @since 1.4
1063 protected void adjustForGravity (GridBagConstraints gbc, Rectangle rect)
1065 AdjustForGravity (gbc, rect);