1 // GridLayout.java - Grid-based layout engine
3 /* Copyright (C) 2000 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
13 import java.io.Serializable;
15 /** This class implements a grid-based layout scheme. Components are
16 * all given the same size and are laid out from left to right and top
17 * to bottom. A GridLayout is configured with a number of rows and a
18 * number of columns. If either is zero then that dimension is
19 * computed based on the actual size of the container. An exception
20 * is thrown if an attempt is made to set both the number of rows and
21 * the number of columns to 0. This class also support horizontal and
22 * vertical gaps; these are used as spacing between cells.
24 public class GridLayout implements LayoutManager, Serializable
26 /** Add a new component to the layout. This particular implementation
29 public void addLayoutComponent (String name, Component comp)
34 /** Return the number of columns in this layout. */
35 public int getColumns ()
40 /** Return the horizontal gap. */
46 /** Return the number of rows in this layout. */
52 /** Return the vertical gap. */
58 /** Create a new GridLayout with one row and any number of columns.
59 * Both gaps are set to 0.
66 /** Create a new GridLayout with the specified number of rows and
67 * columns. Both gaps are set to 0.
68 * @param rows Number of rows
69 * @param cols Number of columns
70 * @exception IllegalArgumentException If rows and columns are both
71 * 0, or if either are negative
73 public GridLayout (int rows, int cols)
75 this (rows, cols, 0, 0);
78 /** Create a new GridLayout with the specified number of rows and
79 * columns and the specified gaps.
80 * @param rows Number of rows
81 * @param cols Number of columns
82 * @param hgap The horizontal gap
83 * @param vgap The vertical gap
84 * @exception IllegalArgumentException If rows and columns are both
85 * 0, if either are negative, or if either gap is negative
87 public GridLayout (int rows, int cols, int hgap, int vgap)
90 throw new IllegalArgumentException ("number of rows cannot be negative");
92 throw new IllegalArgumentException ("number of columns cannot be negative");
93 if (rows == 0 && cols == 0)
94 throw new IllegalArgumentException ("both rows and columns cannot be 0");
96 throw new IllegalArgumentException ("horizontal gap must be nonnegative");
98 throw new IllegalArgumentException ("vertical gap must be nonnegative");
105 /** Lay out the container's components based on current settings.
106 * @param parent The parent container
108 public void layoutContainer (Container parent)
110 int num = parent.getComponentCount ();
111 // This is more efficient than calling getComponents().
112 Component[] comps = parent.component;
114 int real_rows = rows;
115 int real_cols = cols;
117 real_rows = (num + real_cols - 1) / real_cols;
119 real_cols = (num + real_rows - 1) / real_rows;
121 Dimension d = parent.getSize ();
122 Insets ins = parent.getInsets ();
124 int tw = d.width - ins.left - ins.right;
125 int th = d.height - ins.top - ins.bottom;
127 int w = (tw - (real_rows - 1) * hgap) / real_rows;
128 int h = (th - (real_cols - 1) * vgap) / real_cols;
137 comps[i].setBounds (x, y, tw, th);
141 if (recount == real_cols)
152 /** Get the minimum layout size of the container.
153 * @param cont The parent container
155 public Dimension minimumLayoutSize (Container cont)
157 return getSize (cont, true);
160 /** Get the preferred layout size of the container.
161 * @param cont The parent container
163 public Dimension preferredLayoutSize (Container cont)
165 return getSize (cont, false);
168 /** Remove the indicated component from this layout manager.
169 * This particular implementation does nothing.
170 * @param comp The component to remove
172 public void removeLayoutComponent (Component comp)
177 /** Set the number of columns.
179 * @exception IllegalArgumentException If the number of columns is
180 * negative, or if the number of columns is zero and the number
181 * of rows is already 0.
183 public void setColumns (int newCols)
186 throw new IllegalArgumentException ("number of columns cannot be negative");
187 if (newCols == 0 && rows == 0)
188 throw new IllegalArgumentException ("number of rows is already 0");
192 /** Set the horizontal gap
193 * @param hgap The horizontal gap
195 public void setHgap (int hgap)
198 throw new IllegalArgumentException ("horizontal gap must be nonnegative");
202 /** Set the number of rows
204 * @exception IllegalArgumentException If the number of rows is
205 * negative, or if the number of rows is zero and the number
206 * of columns is already 0.
208 public void setRows (int newRows)
211 throw new IllegalArgumentException ("number of rows cannot be negative");
212 if (newRows == 0 && cols == 0)
213 throw new IllegalArgumentException ("number of columns is already 0");
217 /** Set the vertical gap.
218 * @param vgap The vertical gap
220 public void setVgap (int vgap)
223 throw new IllegalArgumentException ("vertical gap must be nonnegative");
227 // This method is used to compute the various sizes.
228 private Dimension getSize (Container parent, boolean is_min)
230 int w = 0, h = 0, num = parent.getComponentCount ();
231 // This is more efficient than calling getComponents().
232 Component[] comps = parent.component;
234 for (int i = 0; i < num; ++i)
236 // FIXME: can we just directly read the fields in Component?
237 // Or will that not work with subclassing?
241 d = comps[i].getMinimumSize ();
243 d = comps[i].getPreferredSize ();
245 w = Math.max (d.width, w);
246 h = Math.max (d.height, h);
249 int real_rows = rows;
250 int real_cols = cols;
252 real_rows = (num + real_cols - 1) / real_cols;
254 real_cols = (num + real_rows - 1) / real_rows;
256 // We subtract out an extra gap here because the gaps are only
258 return new Dimension (real_rows * (w + hgap) - hgap,
259 real_cols * (h + vgap) - vgap);
265 // Number of rows and columns.