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)
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
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
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. */
41 import java
.io
.Serializable
;
42 import java
.util
.Hashtable
;
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();
73 * Helper method to calc the sum of a range of elements in an int array.
75 private int sumIntArray (int[] array
, int upto
)
79 for (int i
= 0; i
< upto
; i
++)
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
);
94 * Helper method to calc the sum of all elements in an double array.
96 private double sumDoubleArray (double[] array
)
100 for (int i
= 0; i
< array
.length
; i
++)
106 public void addLayoutComponent (String name
, Component component
)
111 public void removeLayoutComponent (Component component
)
116 public void addLayoutComponent (Component component
, Object constraints
)
118 if (constraints
== null)
121 if (!(constraints
instanceof GridBagConstraints
))
122 throw new IllegalArgumentException();
124 setConstraints (component
, (GridBagConstraints
) constraints
);
127 public Dimension
preferredLayoutSize (Container parent
)
130 return new Dimension (0, 0);
132 GridBagLayoutInfo li
= getLayoutInfo (parent
, PREFERREDSIZE
);
133 return getMinSize (parent
, li
);
136 public Dimension
minimumLayoutSize (Container parent
)
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();
176 clone
.gridx
= GridBagConstraints
.RELATIVE
;
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
)
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
);
209 setConstraints (component
, defaultConstraints
);
210 result
= (GridBagConstraints
) comptable
.get (component
);
219 public Point
getLayoutOrigin ()
221 if (layoutInfo
== null)
222 return new Point (0, 0);
224 return new Point (layoutInfo
.pos_x
, layoutInfo
.pos_y
);
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];
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
);
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];
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
);
269 public Point
location (int x
, int y
)
271 if (layoutInfo
== null)
272 return new Point (0, 0);
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
];
288 for (row
= 0; row
< layoutInfo
.rows
; row
++)
290 int h
= layoutInfo
.rowHeights
[row
];
297 return new Point (col
, row
);
303 protected void AdjustForGravity (GridBagConstraints gbc
, Rectangle rect
)
305 adjustForGravity (gbc
, rect
);
311 protected void ArrangeGrid (Container parent
)
313 arrangeGrid (parent
);
319 protected GridBagLayoutInfo
GetLayoutInfo (Container parent
, int sizeflag
)
321 return getLayoutInfo (parent
, sizeflag
);
327 protected Dimension
GetMinSize (Container parent
, GridBagLayoutInfo info
)
329 return getMinSize (parent
, info
);
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
);
353 double weight
= sumDoubleArray (weights
);
355 for (int i
= 0; i
< sizes
.length
; i
++)
357 sizes
[i
] += (int) (((double) diff
) * weights
[i
] / weight
);
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
)
381 for(int i
= 0; i
< array
.length
; i
++)
383 System
.out
.print(sep
);
384 System
.out
.print(array
[i
]);
387 System
.out
.println();
390 private void dumpArray(double[] array
)
393 for(int i
= 0; i
< array
.length
; i
++)
395 System
.out
.print(sep
);
396 System
.out
.print(array
[i
]);
399 System
.out
.println();
405 protected void arrangeGrid (Container parent
)
407 Component
[] components
= parent
.getComponents();
409 if (components
.length
== 0)
412 GridBagLayoutInfo info
= getLayoutInfo (parent
, PREFERREDSIZE
);
413 if (info
.cols
== 0 && info
.rows
== 0)
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())
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
;
440 cellx
+= insets
.left
;
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
:
459 case GridBagConstraints
.VERTICAL
:
462 case GridBagConstraints
.BOTH
:
471 switch(constraints
.anchor
)
473 case GridBagConstraints
.NORTH
:
474 x
= cellx
+ (cellw
- dim
.width
) / 2;
477 case GridBagConstraints
.SOUTH
:
478 x
= cellx
+ (cellw
- dim
.width
) / 2;
479 y
= celly
+ cellh
- dim
.height
;
481 case GridBagConstraints
.WEST
:
483 y
= celly
+ (cellh
- dim
.height
) / 2;
485 case GridBagConstraints
.EAST
:
486 x
= cellx
+ cellw
- dim
.width
;
487 y
= celly
+ (cellh
- dim
.height
) / 2;
489 case GridBagConstraints
.NORTHEAST
:
490 x
= cellx
+ cellw
- dim
.width
;
493 case GridBagConstraints
.NORTHWEST
:
497 case GridBagConstraints
.SOUTHEAST
:
498 x
= cellx
+ cellw
- dim
.width
;
499 y
= celly
+ cellh
- dim
.height
;
501 case GridBagConstraints
.SOUTHWEST
:
503 y
= celly
+ cellh
- dim
.height
;
506 x
= cellx
+ (cellw
- dim
.width
) / 2;
507 y
= celly
+ (cellh
- dim
.height
) / 2;
511 component
.setBounds(layoutInfo
.pos_x
+ x
, layoutInfo
.pos_y
+ y
, dim
.width
, dim
.height
);
515 //dumpLayoutInfo (layoutInfo);
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
;
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())
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
)
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())
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
);
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())
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
);
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;
675 //dumpLayoutInfo (info);
683 protected void adjustForGravity (GridBagConstraints gbc
, Rectangle rect
)
686 throw new Error ("Not implemented");