1
2 import java.awt.AWTException;
3 import java.awt.Component;
4 import java.awt.Container;
5 import java.awt.GridBagConstraints;
6 import java.awt.GridBagLayout;
7 import java.awt.Insets;
8 import java.awt.LayoutManager;
9
10 /**
11 * <table><tr><td>Author:<td>Shiraz Kanga
12 * <tr><td>Copyright:<td>Shiraz Kanga, July 9, 2000
13 * </table>
14 *
15 * <p>Copyright © 2000 Shiraz Kanga
16 *
17 * <p>This code is made available under the BSD license.
18 *
19 * <p>This is a layout manager that gives you most of the power GridBagLayout
20 * (in fact it is an instance of GridBagLayout) without any of the complexity
21 * associated with the GridBagLayout. Indeed - it is about as easy to use as
22 * the GridLayout.
23 * <p>
24 * The user merely keeps adding components (gridwidth and gridheight may be
25 * specified or not. The values of gridx and gridy are automatically computed
26 * and the component will be placed into the next available cell.
27 * <p>
28 * You can also manually skip cells and create empty cells.
29 * <p>
30 * It also does <em>not</em> backtrack; once it skips past an empty cell,
31 * that cell will not be used.
32 *
33 * <br>Any bugs, changes or suggestions should be sent to
34 * <a href="mailto:skanga@bigfoot.com">Shiraz Kanga</a>.
35 *
36 * @version 1.0
37 * @author Shiraz Kanga
38 */
39
40 public class FlexGridLayout extends GridBagLayout
41 {
42 private int curRow = 0, curCol = 0;
43 private int flexRow = 0, flexCol = 0;
44 private int numCols;
45
46 // give all components a 2 pixel inset by default
47 private Insets defaultInsets = new Insets (2, 2, 2, 2);
48
49 // anchor all components NORTHWEST by default
50 private int defaultAnchor = GridBagConstraints.NORTHWEST;
51
52 // do not resize the component by default
53 private int defaultFill = GridBagConstraints.BOTH;
54
55 /**
56 * The constructor takes one argument - the number of columns in the grid.
57 *
58 * @param columns the number of columns in the grid (zero based)
59 */
60 public FlexGridLayout (int columns)
61 {
62 super ();
63 numCols = columns;
64 }
65
66 /**
67 * This forces the layout engine to wrap to the next row.
68 */
69 public void nextRow ()
70 {
71 curRow ++ ;
72 curCol = 0;
73 }
74
75 /**
76 * This forces the layout engine to go to the next column.
77 */
78 public void nextCol ()
79 {
80 curCol++;
81 if (curCol >= numCols)
82 {
83 curCol = 0;
84 curRow ++;
85 }
86 }
87
88 /**
89 * Set the flexible row
90 *
91 * @param flex the index (zero based) of the flexible row
92 */
93 public void setFlexRow (int flex)
94 {
95 flexRow = flex;
96 }
97
98 /**
99 * Set the flexible row
100 *
101 * @param flex the index (zero based) of the flexible column
102 */
103 public void setFlexCol (int flex)
104 {
105 flexCol = flex;
106 }
107
108 /**
109 * Set the Insets used by default in this layout
110 */
111 public void setDefaultInsets (Insets in)
112 {
113 defaultInsets = in;
114 }
115
116 /**
117 * Set the anchor used by default in this layout.
118 */
119 public void setDefaultAnchor (int anchor)
120 {
121 defaultAnchor = anchor;
122 }
123
124 /**
125 * Set the fill used by default in this layout.
126 */
127 public void setDefaultFill (int fill)
128 {
129 defaultFill = fill;
130 }
131
132 /**
133 * Add a component to the theContainer which occupies the given number of rows and columns in the grid
134 */
135 public void addComponent (Container theContainer, Component component, int gridwidth, int gridheight)
136 throws AWTException
137 {
138 LayoutManager lm = theContainer.getLayout ();
139 if (! (lm instanceof GridBagLayout))
140 {
141 throw new AWTException ("Container " + theContainer + " has an invalid LayoutManager: " + lm);
142 }
143
144 GridBagConstraints gbc = new GridBagConstraints ();
145
146 gbc.insets = defaultInsets;
147 gbc.anchor = defaultAnchor;
148 gbc.fill = defaultFill;
149
150 gbc.gridwidth = gridwidth;
151 gbc.gridheight = gridheight;
152
153 gbc.gridx = curCol;
154 gbc.gridy = curRow;
155
156 if (curCol == flexCol)
157 gbc.weightx = 1.0;
158 else
159 gbc.weightx = 0.0;
160
161 if (curRow == flexRow)
162 gbc.weighty = 1.0;
163 else
164 gbc.weighty = 0.0;
165
166 if ((curCol == flexCol) && (curRow == flexRow))
167 {
168 gbc.weightx = 1.0;
169 gbc.weighty = 1.0;
170 }
171
172 theContainer.add (component, gbc);
173
174 curCol += gridwidth;
175 if (curCol >= numCols)
176 {
177 curCol = 0;
178 curRow ++;
179 }
180 }
181
182 /**
183 * Add a component to the theContainer which occupies 1 row and 1 column in the grid
184 */
185 public void addComponent (Container theContainer, Component component)
186 throws AWTException
187 {
188 addComponent (theContainer, component, 1, 1);
189 }
190
191
192 // FOR TESTING
193 public static void main (String [] args)
194 {
195 test1 ();
196 test2 ();
197 }
198
199 // FOR TESTING
200 public static void test1 ()
201 {
202 javax.swing.JFrame theFrame = new javax.swing.JFrame ("Test");
203
204 // make sure that any way they cancel the window does the right thing
205 theFrame.addWindowListener (new java.awt.event.WindowAdapter ()
206 {
207 public void windowClosing (java.awt.event.WindowEvent e)
208 {
209 java.awt.Window w = e.getWindow ();
210 w.setVisible (false);
211 w.dispose ();
212 }
213 });
214
215 javax.swing.JTextField firstField = new javax.swing.JTextField (10);
216 javax.swing.JTextField middleField = new javax.swing.JTextField (10);
217 javax.swing.JTextField lastField = new javax.swing.JTextField (10);
218 javax.swing.JTextArea addressArea = new javax.swing.JTextArea (5, 10);
219 javax.swing.JScrollPane addressPane = new javax.swing.JScrollPane (addressArea);
220 javax.swing.JTextField dobField = new javax.swing.JTextField (10);
221
222 javax.swing.JLabel firstName = createLabel ("First Name", firstField, 'F');
223 javax.swing.JLabel middleName = createLabel ("Middle Name", middleField, 'M');
224 javax.swing.JLabel lastName = createLabel ("Last Name", lastField, 'L');
225 javax.swing.JLabel addressName = createLabel ("Address", addressArea, 'A');
226 javax.swing.JLabel dobName = createLabel ("Date of Birth", dobField, 'D');
227
228 // Create a two column grid
229 FlexGridLayout gl = new FlexGridLayout (2);
230
231 // Make Column 1 flexible
232 gl.setFlexCol (1);
233
234 // Make Row 3 flexible
235 gl.setFlexRow (3);
236
237 Container theContainer = theFrame.getContentPane ();
238 theContainer.setLayout (gl);
239
240 try
241 {
242 // Now simply add your components to the container
243 gl.addComponent (theContainer, firstName);
244 gl.addComponent (theContainer, firstField);
245 gl.addComponent (theContainer, middleName);
246 gl.addComponent (theContainer, middleField);
247 gl.addComponent (theContainer, lastName);
248 gl.addComponent (theContainer, lastField);
249 gl.addComponent (theContainer, addressName);
250 gl.addComponent (theContainer, addressPane);
251 gl.addComponent (theContainer, dobName);
252 gl.addComponent (theContainer, dobField);
253 }
254 catch (Exception e)
255 {
256 e.printStackTrace ();
257 }
258
259 theFrame.pack ();
260 theFrame.setVisible (true);
261 }
262
263 // FOR TESTING
264 private static javax.swing.JLabel createLabel (String theName, Component theField, char theMnemonic)
265 {
266 javax.swing.JLabel theLabel = new javax.swing.JLabel (theName);
267 theLabel.setDisplayedMnemonic (theMnemonic);
268 theLabel.setLabelFor (theField);
269 return theLabel;
270 }
271
272 // FOR TESTING
273 public static void test2 ()
274 {
275 javax.swing.JFrame theFrame = new javax.swing.JFrame ("Test");
276
277 // make sure that any way they cancel the window does the right thing
278 theFrame.addWindowListener (new java.awt.event.WindowAdapter ()
279 {
280 public void windowClosing (java.awt.event.WindowEvent e)
281 {
282 java.awt.Window w = e.getWindow ();
283 w.setVisible (false);
284 w.dispose ();
285 }
286 });
287
288 // Create a two column grid
289 FlexGridLayout gl = new FlexGridLayout (5);
290
291 // Make Column 3 flexible
292 gl.setFlexCol (3);
293
294 // Make Row 2 flexible
295 gl.setFlexRow (2);
296
297 Container theContainer = theFrame.getContentPane ();
298 theContainer.setLayout (gl);
299 javax.swing.JButton b;
300
301 try
302 {
303 b = new javax.swing.JButton ("One");
304 gl.addComponent (theContainer, b,1,2);
305 b = new javax.swing.JButton ("Two");
306 gl.addComponent (theContainer, b);
307 b = new javax.swing.JButton ("Three");
308 gl.addComponent (theContainer, b);
309 b = new javax.swing.JButton ("Four");
310 gl.addComponent (theContainer, b);
311 b = new javax.swing.JButton ("Five");
312 gl.addComponent (theContainer, b);
313
314 // Overlapping cells can be created
315 b = new javax.swing.JButton ("Deliberate Overlap!");
316 gl.addComponent (theContainer, b, 2, 1);
317 gl.addComponent (theContainer, new javax.swing.JButton ("six"), 2, 1);
318 gl.addComponent (theContainer, new javax.swing.JButton ("seven"), 1, 2);
319 gl.addComponent (theContainer, new javax.swing.JLabel ("Enter"));
320 gl.addComponent (theContainer, new javax.swing.JTextField ("Some Text!"), 2, 1);
321 gl.nextRow ();
322 gl.addComponent (theContainer, new javax.swing.JButton ("tall"), 1, 2);
323
324 // Empty cells can be created
325 gl.nextCol ();
326 gl.addComponent (theContainer, new javax.swing.JButton ("eight"));
327 gl.addComponent (theContainer, new javax.swing.JButton ("nine"));
328 gl.addComponent (theContainer, new javax.swing.JButton ("ten"));
329 gl.nextCol ();
330 gl.addComponent (theContainer, new javax.swing.JButton ("eleven"));
331 gl.addComponent (theContainer, new javax.swing.JButton ("twelve"));
332 gl.addComponent (theContainer, new javax.swing.JButton ("thirteen"));
333 gl.addComponent (theContainer, new javax.swing.JButton ("fourteen"));
334 gl.addComponent (theContainer, new javax.swing.JButton ("fifteen"));
335 gl.addComponent (theContainer, new javax.swing.JButton ("sixteen"));
336 gl.addComponent (theContainer, new javax.swing.JButton ("seventeen"), 4, 1);
337 }
338 catch (Exception e)
339 {
340 e.printStackTrace ();
341 }
342
343 theFrame.pack ();
344 theFrame.setVisible (true);
345 }
346 }
347