blob: a9b3e4bd845bd7b423ec4672c61a77e231515c46 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1996 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package sun.awt;
26
27import java.awt.*;
28
29/**
30 * Extends the FlowLayout class to support both vertical and horizontal
31 * layout of components. Orientation can be changed dynamically after
32 * creation by calling either of the methods @method orientHorizontally or
33 * @method orientVertically. Separate values for alignment, vertical gap,
34 * and horizontal gap can be specified for horizontal and vertical
35 * orientation.
36 *
37 * @author Terry Cline
38 */
39public class OrientableFlowLayout extends FlowLayout {
40 /**
41 * The horizontal orientation constant.
42 */
43 public static final int HORIZONTAL = 0;
44
45 /**
46 * The vertical orientation constant.
47 */
48 public static final int VERTICAL = 1;
49
50 /**
51 * The top vertical alignment constant.
52 */
53 public static final int TOP = 0;
54
55 /**
56 * The bottom vertical alignment constant.
57 */
58 public static final int BOTTOM = 2; // CENTER == 1
59
60 int orientation;
61 int vAlign;
62 int vHGap;
63 int vVGap;
64
65 /**
66 * Constructs a new flow layout with a horizontal orientation and
67 * centered alignment.
68 */
69 public OrientableFlowLayout() {
70 this(HORIZONTAL, CENTER, CENTER, 5, 5, 5, 5);
71 }
72
73 /**
74 * Constructs a new flow layout with the specified orientation and
75 * a centered alignment.
76 *
77 * @param orientation the orientation, one of HORIZONTAL or VERTICAL.
78 */
79 public OrientableFlowLayout(int orientation) {
80 this(orientation, CENTER, CENTER, 5, 5, 5, 5);
81 }
82
83 /**
84 * Constructs a new flow layout with the specified orientation and
85 * alignment.
86 *
87 * @param orientation the orientation, one of HORIZONTAL or VERTICAL.
88 * @param hAlign the horizontal alignment, one of LEFT, CENTER, or RIGHT.
89 * @param vAlign the vertical alignment, one of TOP, CENTER, or BOTTOM.
90 */
91 public OrientableFlowLayout(int orientation, int hAlign, int vAlign) {
92 this(orientation, hAlign, vAlign, 5, 5, 5, 5);
93 }
94
95 /**
96 * Constructs a new flow layout with the specified orientation,
97 * alignment, and gap values.
98 *
99 * @param orientation the orientation, one of HORIZONTAL or VERTICAL.
100 * @param hAlign the horizontal alignment, one of LEFT, CENTER, or RIGHT.
101 * @param vAlign the vertical alignment, one of TOP, CENTER, or BOTTOM.
102 * @param hHGap the horizontal gap between components in HORIZONTAL.
103 * @param hVGap the vertical gap between components in HORIZONTAL.
104 * @param vHGap the horizontal gap between components in VERTICAL.
105 * @param vVGap the vertical gap between components in VERTICAL.
106 */
107 public OrientableFlowLayout(int orientation, int hAlign, int vAlign, int hHGap, int hVGap, int vHGap, int vVGap) {
108 super(hAlign, hHGap, hVGap);
109 this.orientation = orientation;
110 this.vAlign = vAlign;
111 this.vHGap = vHGap;
112 this.vVGap = vVGap;
113 }
114
115 /**
116 * Set the layout's current orientation to horizontal.
117 */
118 public synchronized void orientHorizontally() {
119 orientation = HORIZONTAL;
120 }
121
122 /**
123 * Set the layout's current orientation to vertical.
124 */
125 public synchronized void orientVertically() {
126 orientation = VERTICAL;
127 }
128
129 /**
130 * Returns the preferred dimensions for this layout given the
131 * components in the specified target container.
132 *
133 * @param target the component which needs to be laid out.
134 * @see Container
135 * @see FlowLayout
136 * @see #minimumLayoutSize
137 */
138 public Dimension preferredLayoutSize(Container target) {
139 if (orientation == HORIZONTAL) {
140 return super.preferredLayoutSize(target);
141 }
142 else {
143 Dimension dim = new Dimension(0, 0);
144
145 int n = target.countComponents();
146 for (int i = 0; i < n; i++) {
147 Component c = target.getComponent(i);
148 if (c.isVisible()) {
149 Dimension cDim = c.preferredSize();
150 dim.width = Math.max(dim.width, cDim.width);
151 if (i > 0) {
152 dim.height += vVGap;
153 }
154 dim.height += cDim.height;
155 }
156 }
157
158 Insets insets = target.insets();;
159 dim.width += insets.left + insets.right + vHGap*2;
160 dim.height += insets.top + insets.bottom + vVGap*2;
161
162 return dim;
163 }
164 }
165
166 /**
167 * Returns the minimum dimensions needed to layout the components
168 * contained in the specified target container.
169 *
170 * @param target the component which needs to be laid out.
171 * @see #preferredLayoutSize.
172 */
173 public Dimension minimumLayoutSize(Container target) {
174 if (orientation == HORIZONTAL) {
175 return super.minimumLayoutSize(target);
176 }
177 else {
178 Dimension dim = new Dimension(0, 0);
179
180 int n = target.countComponents();
181 for (int i = 0; i < n; i++) {
182 Component c = target.getComponent(i);
183 if (c.isVisible()) {
184 Dimension cDim = c.minimumSize();
185 dim.width = Math.max(dim.width, cDim.width);
186 if (i > 0) {
187 dim.height += vVGap;
188 }
189 dim.height += cDim.height;
190 }
191 }
192
193 Insets insets = target.insets();
194 dim.width += insets.left + insets.right + vHGap*2;
195 dim.height += insets.top + insets.bottom + vVGap*2;
196
197 return dim;
198 }
199 }
200
201 /**
202 * Lays out the container. This method will reshape the
203 * components in the target to satisfy the constraints of the
204 * layout.
205 *
206 * @param target the specified component being laid out.
207 * @see Container.
208 */
209 public void layoutContainer(Container target) {
210 if (orientation == HORIZONTAL) {
211 super.layoutContainer(target);
212 }
213 else {
214 Insets insets = target.insets();
215 Dimension targetDim = target.size();
216 int maxHeight = targetDim.height - (insets.top + insets.bottom + vVGap*2);
217 int x = insets.left + vHGap;
218 int y = 0;
219 int colWidth = 0;
220 int start = 0;
221
222 int n = target.countComponents();
223 for (int i = 0; i < n; i++) {
224 Component c = target.getComponent(i);
225 if (c.isVisible()) {
226 Dimension cDim = c.preferredSize();
227 c.resize(cDim.width, cDim.height);
228
229 if ((y == 0) || ((y + cDim.height) <= maxHeight)) {
230 if (y > 0) {
231 y += vVGap;
232 }
233 y += cDim.height;
234 colWidth = Math.max(colWidth, cDim.width);
235 }
236 else {
237 moveComponents(target,
238 x,
239 insets.top + vVGap,
240 colWidth,
241 maxHeight - y,
242 start,
243 i);
244 x += vHGap + colWidth;
245 y = cDim.width;
246 colWidth = cDim.width;
247 start = i;
248 }
249 }
250 }
251
252 moveComponents(target,
253 x,
254 insets.top + vVGap,
255 colWidth,
256 maxHeight - y,
257 start,
258 n);
259 }
260 }
261
262 /**
263 * Aligns the components vertically if there is any slack.
264 *
265 * @param target the container whose components need to be moved.
266 * @param x the x coordinate.
267 * @param y the y coordinate.
268 * @param width the width available.
269 * @param height the height available.
270 * @param colStart the beginning of the column.
271 * @param colEnd the end of the column.
272 */
273 private void moveComponents(Container target, int x, int y, int width, int height, int colStart, int colEnd) {
274 switch (vAlign) {
275 case TOP:
276 break;
277 case CENTER:
278 y += height/2;
279 break;
280 case BOTTOM:
281 y += height;
282 }
283
284 for (int i = colStart; i < colEnd; i++) {
285 Component c = target.getComponent(i);
286 Dimension cDim = c.size();
287 if (c.isVisible()) {
288 c.move(x + (width - cDim.width)/2, y);
289 y += vVGap + cDim.height;
290 }
291 }
292 }
293
294 /**
295 * Returns the String representation of this layout's values.
296 */
297 public String toString() {
298 String str = "";
299 switch (orientation) {
300 case HORIZONTAL:
301 str = "orientation=horizontal, ";
302 break;
303 case VERTICAL:
304 str = "orientation=vertical, ";
305 break;
306 }
307
308 return getClass().getName() + "[" + str + super.toString() + "]";
309 }
310}