2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / java / awt / GridBagLayout.java
blob7572c1d1d565e114bb9003fcf2c16b5e55f9df70
1 /* GridBagLayout - Layout manager for components according to GridBagConstraints
2 Copyright (C) 2002, 2003 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.Hashtable;
44 /**
45 * @author Michael Koch <konqueror@gmx.de>
46 * @author Jeroen Frijters <jeroen@frijters.net>
48 public class GridBagLayout
49 implements Serializable, LayoutManager2
51 private static final long serialVersionUID = 8838754796412211005L;
53 protected static final int MINSIZE = 1;
54 protected static final int PREFERREDSIZE = 2;
55 protected static final int MAXGRIDSIZE = 512;
57 protected Hashtable comptable;
58 protected GridBagLayoutInfo layoutInfo;
59 protected GridBagConstraints defaultConstraints;
61 public double[] columnWeights;
62 public int[] columnWidths;
63 public double[] rowWeights;
64 public int[] rowHeights;
66 public GridBagLayout ()
68 this.comptable = new Hashtable();
69 this.defaultConstraints= new GridBagConstraints();
72 /**
73 * Helper method to calc the sum of a range of elements in an int array.
75 private int sumIntArray (int[] array, int upto)
77 int result = 0;
79 for (int i = 0; i < upto; i++)
80 result += array [i];
82 return result;
85 /**
86 * Helper method to calc the sum of all elements in an int array.
88 private int sumIntArray (int[] array)
90 return sumIntArray(array, array.length);
93 /**
94 * Helper method to calc the sum of all elements in an double array.
96 private double sumDoubleArray (double[] array)
98 double result = 0;
100 for (int i = 0; i < array.length; i++)
101 result += array [i];
103 return result;
106 public void addLayoutComponent (String name, Component component)
108 // do nothing here.
111 public void removeLayoutComponent (Component component)
113 // do nothing here
116 public void addLayoutComponent (Component component, Object constraints)
118 if (constraints == null)
119 return;
121 if (!(constraints instanceof GridBagConstraints))
122 throw new IllegalArgumentException();
124 setConstraints (component, (GridBagConstraints) constraints);
127 public Dimension preferredLayoutSize (Container parent)
129 if (parent == null)
130 return new Dimension (0, 0);
132 GridBagLayoutInfo li = getLayoutInfo (parent, PREFERREDSIZE);
133 return getMinSize (parent, li);
136 public Dimension minimumLayoutSize (Container parent)
138 if (parent == null)
139 return new Dimension (0, 0);
141 GridBagLayoutInfo li = getLayoutInfo (parent, MINSIZE);
142 return getMinSize (parent, li);
145 public Dimension maximumLayoutSize (Container target)
147 return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE);
150 public void layoutContainer (Container parent)
152 arrangeGrid (parent);
155 public float getLayoutAlignmentX (Container target)
157 return Component.CENTER_ALIGNMENT;
160 public float getLayoutAlignmentY (Container target)
162 return Component.CENTER_ALIGNMENT;
165 public void invalidateLayout (Container target)
167 this.layoutInfo = null;
170 public void setConstraints (Component component,
171 GridBagConstraints constraints)
173 GridBagConstraints clone = (GridBagConstraints) constraints.clone();
175 if (clone.gridx < 0)
176 clone.gridx = GridBagConstraints.RELATIVE;
178 if (clone.gridy < 0)
179 clone.gridy = GridBagConstraints.RELATIVE;
181 if (clone.gridwidth == 0)
182 clone.gridwidth = GridBagConstraints.REMAINDER;
183 else if (clone.gridwidth < 0
184 && clone.gridwidth != GridBagConstraints.REMAINDER
185 && clone.gridwidth != GridBagConstraints.RELATIVE)
186 clone.gridwidth = 1;
188 if (clone.gridheight == 0)
189 clone.gridheight = GridBagConstraints.REMAINDER;
190 else if (clone.gridheight < 0
191 && clone.gridheight != GridBagConstraints.REMAINDER
192 && clone.gridheight != GridBagConstraints.RELATIVE)
193 clone.gridheight = 1;
195 comptable.put (component, clone);
198 public GridBagConstraints getConstraints (Component component)
200 return (GridBagConstraints) (lookupConstraints (component).clone());
203 protected GridBagConstraints lookupConstraints (Component component)
205 GridBagConstraints result = (GridBagConstraints) comptable.get (component);
207 if (result == null)
209 setConstraints (component, defaultConstraints);
210 result = (GridBagConstraints) comptable.get (component);
213 return result;
217 * @since 1.1
219 public Point getLayoutOrigin ()
221 if (layoutInfo == null)
222 return new Point (0, 0);
224 return new Point (layoutInfo.pos_x, layoutInfo.pos_y);
228 * @since 1.1
230 public int[][] getLayoutDimensions ()
232 int[][] result = new int [2][];
233 if (layoutInfo == null)
235 result[0] = new int[0];
236 result[1] = new int[0];
238 return result;
241 result [0] = new int [layoutInfo.cols];
242 System.arraycopy (layoutInfo.colWidths, 0, result [0], 0, layoutInfo.cols);
243 result [1] = new int [layoutInfo.rows];
244 System.arraycopy (layoutInfo.rowHeights, 0, result [1], 0, layoutInfo.rows);
245 return result;
248 public double[][] getLayoutWeights ()
250 double[][] result = new double [2][];
251 if (layoutInfo == null)
253 result[0] = new double[0];
254 result[1] = new double[0];
256 return result;
259 result [0] = new double [layoutInfo.cols];
260 System.arraycopy (layoutInfo.colWeights, 0, result [0], 0, layoutInfo.cols);
261 result [1] = new double [layoutInfo.rows];
262 System.arraycopy (layoutInfo.rowWeights, 0, result [1], 0, layoutInfo.rows);
263 return result;
267 * @since 1.1
269 public Point location (int x, int y)
271 if (layoutInfo == null)
272 return new Point (0, 0);
274 int col;
275 int row;
276 int pixel_x = layoutInfo.pos_x;
277 int pixel_y = layoutInfo.pos_y;
279 for (col = 0; col < layoutInfo.cols; col++)
281 int w = layoutInfo.colWidths [col];
282 if (x < pixel_x + w)
283 break;
285 pixel_x += w;
288 for (row = 0; row < layoutInfo.rows; row++)
290 int h = layoutInfo.rowHeights [row];
291 if (y < pixel_y + h)
292 break;
294 pixel_y += h;
297 return new Point (col, row);
301 * Obsolete.
303 protected void AdjustForGravity (GridBagConstraints gbc, Rectangle rect)
305 adjustForGravity (gbc, rect);
309 * Obsolete.
311 protected void ArrangeGrid (Container parent)
313 arrangeGrid (parent);
317 * Obsolete.
319 protected GridBagLayoutInfo GetLayoutInfo (Container parent, int sizeflag)
321 return getLayoutInfo (parent, sizeflag);
325 * Obsolete.
327 protected Dimension GetMinSize (Container parent, GridBagLayoutInfo info)
329 return getMinSize (parent, info);
333 * @since 1.4
335 protected Dimension getMinSize (Container parent, GridBagLayoutInfo info)
337 if (parent == null || info == null)
338 return new Dimension (0, 0);
340 Insets insets = parent.getInsets();
341 int width = sumIntArray (info.colWidths) + insets.left + insets.right;
342 int height = sumIntArray (info.rowHeights) + insets.top + insets.bottom;
343 return new Dimension (width, height);
346 private void calcCellSizes (int[] sizes, double[] weights, int range)
348 int diff = range - sumIntArray (sizes);
350 if (diff == 0)
351 return;
353 double weight = sumDoubleArray (weights);
355 for (int i = 0; i < sizes.length; i++)
357 sizes [i] += (int) (((double) diff) * weights [i] / weight );
359 if (sizes [i] < 0)
360 sizes [i] = 0;
364 private void dumpLayoutInfo (GridBagLayoutInfo info)
366 System.out.println ("GridBagLayoutInfo:");
367 System.out.println ("cols: " + info.cols + ", rows: " + info.rows);
368 System.out.print ("colWidths: ");
369 dumpArray(info.colWidths);
370 System.out.print ("rowHeights: ");
371 dumpArray(info.rowHeights);
372 System.out.print ("colWeights: ");
373 dumpArray(info.colWeights);
374 System.out.print ("rowWeights: ");
375 dumpArray(info.rowWeights);
378 private void dumpArray(int[] array)
380 String sep = "";
381 for(int i = 0; i < array.length; i++)
383 System.out.print(sep);
384 System.out.print(array[i]);
385 sep = ", ";
387 System.out.println();
390 private void dumpArray(double[] array)
392 String sep = "";
393 for(int i = 0; i < array.length; i++)
395 System.out.print(sep);
396 System.out.print(array[i]);
397 sep = ", ";
399 System.out.println();
403 * @since 1.4
405 protected void arrangeGrid (Container parent)
407 Component[] components = parent.getComponents();
409 if (components.length == 0)
410 return;
412 GridBagLayoutInfo info = getLayoutInfo (parent, PREFERREDSIZE);
413 if (info.cols == 0 && info.rows == 0)
414 return;
415 layoutInfo = info;
417 // DEBUG
418 //dumpLayoutInfo (layoutInfo);
420 for(int i = 0; i < components.length; i++)
422 Component component = components [i];
424 // If component is not visible we dont have to care about it.
425 if (!component.isVisible())
426 continue;
428 GridBagConstraints constraints = lookupConstraints (component);
430 int cellx = sumIntArray(layoutInfo.colWidths, constraints.gridx);
431 int celly = sumIntArray(layoutInfo.rowHeights, constraints.gridy);
432 int cellw = sumIntArray(layoutInfo.colWidths,
433 constraints.gridx + constraints.gridwidth) - cellx;
434 int cellh = sumIntArray(layoutInfo.rowHeights,
435 constraints.gridy + constraints.gridheight) - celly;
437 Insets insets = constraints.insets;
438 if (insets != null)
440 cellx += insets.left;
441 celly += insets.top;
442 cellw -= insets.left + insets.right;
443 cellh -= insets.top + insets.bottom;
446 Dimension dim = component.preferredSize();
448 // Note: Documentation says that padding is added on both sides, but
449 // visual inspection shows that the Sun implementation only adds it
450 // once, so we do the same.
451 dim.width += constraints.ipadx;
452 dim.height += constraints.ipady;
454 switch(constraints.fill)
456 case GridBagConstraints.HORIZONTAL:
457 dim.width = cellw;
458 break;
459 case GridBagConstraints.VERTICAL:
460 dim.height = cellh;
461 break;
462 case GridBagConstraints.BOTH:
463 dim.width = cellw;
464 dim.height = cellh;
465 break;
468 int x;
469 int y;
471 switch(constraints.anchor)
473 case GridBagConstraints.NORTH:
474 x = cellx + (cellw - dim.width) / 2;
475 y = celly;
476 break;
477 case GridBagConstraints.SOUTH:
478 x = cellx + (cellw - dim.width) / 2;
479 y = celly + cellh - dim.height;
480 break;
481 case GridBagConstraints.WEST:
482 x = cellx;
483 y = celly + (cellh - dim.height) / 2;
484 break;
485 case GridBagConstraints.EAST:
486 x = cellx + cellw - dim.width;
487 y = celly + (cellh - dim.height) / 2;
488 break;
489 case GridBagConstraints.NORTHEAST:
490 x = cellx + cellw - dim.width;
491 y = celly;
492 break;
493 case GridBagConstraints.NORTHWEST:
494 x = cellx;
495 y = celly;
496 break;
497 case GridBagConstraints.SOUTHEAST:
498 x = cellx + cellw - dim.width;
499 y = celly + cellh - dim.height;
500 break;
501 case GridBagConstraints.SOUTHWEST:
502 x = cellx;
503 y = celly + cellh - dim.height;
504 break;
505 default:
506 x = cellx + (cellw - dim.width) / 2;
507 y = celly + (cellh - dim.height) / 2;
508 break;
511 component.setBounds(layoutInfo.pos_x + x, layoutInfo.pos_y + y, dim.width, dim.height);
514 // DEBUG
515 //dumpLayoutInfo (layoutInfo);
520 * @since 1.4
522 protected GridBagLayoutInfo getLayoutInfo (Container parent, int sizeflag)
524 if (sizeflag != MINSIZE && sizeflag != PREFERREDSIZE)
525 throw new IllegalArgumentException();
527 Dimension parentDim = parent.size();
528 Insets parentInsets = parent.insets();
529 parentDim.width -= parentInsets.left + parentInsets.right;
530 parentDim.height -= parentInsets.top + parentInsets.bottom;
532 int x = 0;
533 int y = 0;
534 int max_x = 0;
535 int max_y = 0;
537 // first we figure out how many rows/columns
538 Component[] components = parent.getComponents();
539 for (int i = 0; i < components.length; i++)
541 Component component = components [i];
543 // If component is not visible we dont have to care about it.
544 if (!component.isVisible())
545 continue;
547 GridBagConstraints constraints = lookupConstraints (component);
549 if(constraints.gridx == GridBagConstraints.RELATIVE)
550 constraints.gridx = x;
552 if(constraints.gridy == GridBagConstraints.RELATIVE)
553 constraints.gridy = y;
555 max_x = Math.max(max_x,
556 constraints.gridx + Math.max(1, constraints.gridwidth));
557 max_y = Math.max(max_y,
558 constraints.gridy + Math.max(1, constraints.gridheight));
560 if(constraints.gridwidth == GridBagConstraints.REMAINDER)
562 x = 0;
563 y++;
565 else
567 x = constraints.gridx + Math.max(1, constraints.gridwidth);
568 y = constraints.gridy;
572 GridBagLayoutInfo info = new GridBagLayoutInfo(max_x, max_y);
574 for (x = 0; x <= max_x; x++)
576 if(columnWidths != null && columnWidths.length > x)
578 info.colWidths[x] = columnWidths[x];
580 if(columnWeights != null && columnWeights.length > x)
582 info.colWeights[x] = columnWeights[x];
584 for (int i = 0; i < components.length; i++)
586 Component component = components [i];
588 // If component is not visible we dont have to care about it.
589 if (!component.isVisible())
590 continue;
592 GridBagConstraints constraints = lookupConstraints (component);
594 // first we fix up any REMAINDER cells
595 if(constraints.gridwidth == GridBagConstraints.REMAINDER)
597 constraints.gridwidth = max_x - constraints.gridx;
599 if(constraints.gridheight == GridBagConstraints.REMAINDER)
601 constraints.gridheight = max_y - constraints.gridy;
604 if(constraints.gridx + constraints.gridwidth - 1 == x)
606 int width = (sizeflag == PREFERREDSIZE) ?
607 component.preferredSize().width :
608 component.minimumSize().width;
609 if(constraints.insets != null)
611 width += constraints.insets.left + constraints.insets.right;
613 width += constraints.ipadx;
614 for(int w = 1; w < constraints.gridwidth; w++)
616 width -= info.colWidths[x - w];
618 info.colWidths[x] = Math.max(info.colWidths[x], width);
619 info.colWeights[x] =
620 Math.max(info.colWeights[x], constraints.weightx);
625 for (y = 0; y <= max_y; y++)
627 if(rowHeights != null && rowHeights.length > y)
629 info.rowHeights[y] = rowHeights[y];
631 if(rowWeights != null && rowWeights.length > y)
633 info.rowWeights[y] = rowWeights[y];
635 for (int i = 0; i < components.length; i++)
637 Component component = components [i];
639 // If component is not visible we dont have to care about it.
640 if (!component.isVisible())
641 continue;
643 GridBagConstraints constraints = lookupConstraints (component);
645 if(constraints.gridy + constraints.gridheight - 1 == y)
647 int height = (sizeflag == PREFERREDSIZE) ?
648 component.preferredSize().height :
649 component.minimumSize().height;
650 if(constraints.insets != null)
652 height += constraints.insets.top + constraints.insets.bottom;
654 height += constraints.ipady;
655 for(int h = 1; h < constraints.gridheight; h++)
657 height -= info.rowHeights[y - h];
659 info.rowHeights[y] = Math.max(info.rowHeights[y], height);
660 info.rowWeights[y] =
661 Math.max(info.rowWeights[y], constraints.weighty);
666 calcCellSizes (info.colWidths, info.colWeights, parentDim.width);
667 calcCellSizes (info.rowHeights, info.rowWeights, parentDim.height);
669 int totalWidth = sumIntArray(info.colWidths);
670 int totalHeight = sumIntArray(info.rowHeights);
671 info.pos_x = parentInsets.left + (parentDim.width - totalWidth) / 2;
672 info.pos_y = parentInsets.top + (parentDim.height - totalHeight) / 2;
674 // DEBUG
675 //dumpLayoutInfo (info);
677 return info;
681 * @since 1.4
683 protected void adjustForGravity (GridBagConstraints gbc, Rectangle rect)
685 // FIXME
686 throw new Error ("Not implemented");