1 |
/* OverlayLayout.java -- |
/* OverlayLayout.java -- A layout manager |
2 |
Copyright (C) 2002, 2004 Free Software Foundation, Inc. |
Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
37 |
|
|
38 |
package javax.swing; |
package javax.swing; |
39 |
|
|
40 |
|
import java.awt.AWTError; |
41 |
import java.awt.Component; |
import java.awt.Component; |
42 |
import java.awt.Container; |
import java.awt.Container; |
43 |
import java.awt.Dimension; |
import java.awt.Dimension; |
44 |
|
import java.awt.Insets; |
45 |
import java.awt.LayoutManager2; |
import java.awt.LayoutManager2; |
46 |
import java.io.Serializable; |
import java.io.Serializable; |
47 |
|
|
48 |
/** |
/** |
49 |
* OverlayLayout |
* A layout manager that lays out the components of a container one over |
50 |
* @author Andrew Selkirk |
* another. |
51 |
* @version 1.0 |
* |
52 |
|
* The components take as much space as is available in the container, but not |
53 |
|
* more than specified by their maximum size. |
54 |
|
* |
55 |
|
* The overall layout is mainly affected by the components |
56 |
|
* <code>alignmentX</code> and <code>alignmentY</code> properties. All |
57 |
|
* components are aligned, so that their alignment points (for either |
58 |
|
* direction) are placed in one line (the baseline for this direction). |
59 |
|
* |
60 |
|
* For example: An X alignment of 0.0 means that the component's alignment |
61 |
|
* point is at it's left edge, an X alignment of 0.5 means that the alignment |
62 |
|
* point is in the middle, an X alignment of 1.0 means, the aligment point is |
63 |
|
* at the right edge. So if you have three components, the first with 0.0, the |
64 |
|
* second with 0.5 and the third with 1.0, then they are laid out like this: |
65 |
|
* |
66 |
|
* <pre> |
67 |
|
* +-------+ |
68 |
|
* | 1 | |
69 |
|
* +-------+ |
70 |
|
* +-------+ |
71 |
|
* | 2 | |
72 |
|
* +-------+ |
73 |
|
* +---------+ |
74 |
|
* | 3 + |
75 |
|
* +---------+ |
76 |
|
* </pre> |
77 |
|
* The above picture shows the X alignment between the components. An Y |
78 |
|
* alignment like shown above cannot be achieved with this layout manager. The |
79 |
|
* components are place on top of each other, with the X alignment shown above. |
80 |
|
* |
81 |
|
* @author Roman Kennke (kennke@aicas.com) |
82 |
|
* @author Andrew Selkirk |
83 |
*/ |
*/ |
84 |
public class OverlayLayout implements LayoutManager2, Serializable |
public class OverlayLayout implements LayoutManager2, Serializable |
85 |
{ |
{ |
86 |
private static final long serialVersionUID = 18082829169631543L; |
private static final long serialVersionUID = 18082829169631543L; |
87 |
|
|
88 |
/** |
/** |
89 |
* target |
* The container to be laid out. |
90 |
*/ |
*/ |
91 |
private Container target; |
private Container target; |
92 |
|
|
93 |
/** |
/** |
94 |
* xChildren |
* The size requirements of the containers children for the X direction. |
95 |
*/ |
*/ |
96 |
private SizeRequirements[] xChildren; |
private SizeRequirements[] xChildren; |
97 |
|
|
98 |
/** |
/** |
99 |
* yChildren |
* The size requirements of the containers children for the Y direction. |
100 |
*/ |
*/ |
101 |
private SizeRequirements[] yChildren; |
private SizeRequirements[] yChildren; |
102 |
|
|
103 |
/** |
/** |
104 |
* xTotal |
* The size requirements of the container to be laid out for the X direction. |
105 |
*/ |
*/ |
106 |
private SizeRequirements xTotal; |
private SizeRequirements xTotal; |
107 |
|
|
108 |
/** |
/** |
109 |
* yTotal |
* The size requirements of the container to be laid out for the Y direction. |
110 |
*/ |
*/ |
111 |
private SizeRequirements yTotal; |
private SizeRequirements yTotal; |
112 |
|
|
113 |
/** |
/** |
114 |
* Constructor OverlayLayout |
* The offsets of the child components in the X direction. |
115 |
* @param target TODO |
*/ |
116 |
|
private int[] offsetsX; |
117 |
|
|
118 |
|
/** |
119 |
|
* The offsets of the child components in the Y direction. |
120 |
|
*/ |
121 |
|
private int[] offsetsY; |
122 |
|
|
123 |
|
/** |
124 |
|
* The spans of the child components in the X direction. |
125 |
|
*/ |
126 |
|
private int[] spansX; |
127 |
|
|
128 |
|
/** |
129 |
|
* The spans of the child components in the Y direction. |
130 |
|
*/ |
131 |
|
private int[] spansY; |
132 |
|
|
133 |
|
/** |
134 |
|
* Creates a new OverlayLayout for the specified container. |
135 |
|
* |
136 |
|
* @param target the container to be laid out |
137 |
*/ |
*/ |
138 |
public OverlayLayout(Container target) |
public OverlayLayout(Container target) |
139 |
{ |
{ |
140 |
// TODO |
this.target = target; |
141 |
} |
} |
142 |
|
|
143 |
/** |
/** |
144 |
* invalidateLayout |
* Notifies the layout manager that the layout has become invalid. It throws |
145 |
* @param target TODO |
* away cached layout information and recomputes it the next time it is |
146 |
|
* requested. |
147 |
|
* |
148 |
|
* @param target not used here |
149 |
*/ |
*/ |
150 |
public void invalidateLayout(Container target) |
public void invalidateLayout(Container target) |
151 |
{ |
{ |
152 |
// TODO |
xChildren = null; |
153 |
|
yChildren = null; |
154 |
|
xTotal = null; |
155 |
|
yTotal = null; |
156 |
|
offsetsX = null; |
157 |
|
offsetsY = null; |
158 |
|
spansX = null; |
159 |
|
spansY = null; |
160 |
} |
} |
161 |
|
|
162 |
/** |
/** |
163 |
* addLayoutComponent |
* This method is not used in this layout manager. |
164 |
* @param string TODO |
* |
165 |
* @param component TODO |
* @param string not used here |
166 |
|
* @param component not used here |
167 |
*/ |
*/ |
168 |
public void addLayoutComponent(String string, Component component) |
public void addLayoutComponent(String string, Component component) |
169 |
{ |
{ |
170 |
// TODO |
// Nothing to do here. |
171 |
} |
} |
172 |
|
|
173 |
/** |
/** |
174 |
* addLayoutComponent |
* This method is not used in this layout manager. |
175 |
* @param component TODO |
* |
176 |
* @param constraints TODO |
* @param component not used here |
177 |
|
* @param constraints not used here |
178 |
*/ |
*/ |
179 |
public void addLayoutComponent(Component component, Object constraints) |
public void addLayoutComponent(Component component, Object constraints) |
180 |
{ |
{ |
181 |
// TODO |
// Nothing to do here. |
182 |
} |
} |
183 |
|
|
184 |
/** |
/** |
185 |
* removeLayoutComponent |
* This method is not used in this layout manager. |
186 |
* @param component TODO |
* |
187 |
|
* @param component not used here |
188 |
*/ |
*/ |
189 |
public void removeLayoutComponent(Component component) |
public void removeLayoutComponent(Component component) |
190 |
{ |
{ |
191 |
// TODO |
// Nothing to do here. |
192 |
} |
} |
193 |
|
|
194 |
/** |
/** |
195 |
* preferredLayoutSize |
* Returns the preferred size of the container that is laid out. This is |
196 |
* @param target TODO |
* computed by the children's preferred sizes, taking their alignments into |
197 |
* @returns Dimension |
* account. |
198 |
|
* |
199 |
|
* @param target not used here |
200 |
|
* |
201 |
|
* @returns the preferred size of the container that is laid out |
202 |
*/ |
*/ |
203 |
public Dimension preferredLayoutSize(Container target) |
public Dimension preferredLayoutSize(Container target) |
204 |
{ |
{ |
205 |
return null; // TODO |
if (target != this.target) |
206 |
|
throw new AWTError("OverlayLayout can't be shared"); |
207 |
|
|
208 |
|
checkTotalRequirements(); |
209 |
|
return new Dimension(xTotal.preferred, yTotal.preferred); |
210 |
} |
} |
211 |
|
|
212 |
/** |
/** |
213 |
* minimumLayoutSize |
* Returns the minimum size of the container that is laid out. This is |
214 |
* @param target TODO |
* computed by the children's minimum sizes, taking their alignments into |
215 |
* @returns Dimension |
* account. |
216 |
|
* |
217 |
|
* @param target not used here |
218 |
|
* |
219 |
|
* @returns the minimum size of the container that is laid out |
220 |
*/ |
*/ |
221 |
public Dimension minimumLayoutSize(Container target) |
public Dimension minimumLayoutSize(Container target) |
222 |
{ |
{ |
223 |
return null; // TODO |
if (target != this.target) |
224 |
|
throw new AWTError("OverlayLayout can't be shared"); |
225 |
|
|
226 |
|
checkTotalRequirements(); |
227 |
|
return new Dimension(xTotal.minimum, yTotal.minimum); |
228 |
} |
} |
229 |
|
|
230 |
/** |
/** |
231 |
* maximumLayoutSize |
* Returns the maximum size of the container that is laid out. This is |
232 |
* @param target TODO |
* computed by the children's maximum sizes, taking their alignments into |
233 |
* @returns Dimension |
* account. |
234 |
|
* |
235 |
|
* @param target not used here |
236 |
|
* |
237 |
|
* @returns the maximum size of the container that is laid out |
238 |
*/ |
*/ |
239 |
public Dimension maximumLayoutSize(Container target) |
public Dimension maximumLayoutSize(Container target) |
240 |
{ |
{ |
241 |
return null; // TODO |
if (target != this.target) |
242 |
|
throw new AWTError("OverlayLayout can't be shared"); |
243 |
|
|
244 |
|
checkTotalRequirements(); |
245 |
|
return new Dimension(xTotal.maximum, yTotal.maximum); |
246 |
} |
} |
247 |
|
|
248 |
/** |
/** |
249 |
* getLayoutAlignmentX |
* Returns the X alignment of the container that is laid out. This is |
250 |
* @param target TODO |
* computed by the children's preferred sizes, taking their alignments into |
251 |
* @returns float |
* account. |
252 |
|
* |
253 |
|
* @param target not used here |
254 |
|
* |
255 |
|
* @returns the X alignment of the container that is laid out |
256 |
*/ |
*/ |
257 |
public float getLayoutAlignmentX(Container target) |
public float getLayoutAlignmentX(Container target) |
258 |
{ |
{ |
259 |
return (float) 0.0; // TODO |
if (target != this.target) |
260 |
|
throw new AWTError("OverlayLayout can't be shared"); |
261 |
|
|
262 |
|
checkTotalRequirements(); |
263 |
|
return xTotal.alignment; |
264 |
} |
} |
265 |
|
|
266 |
/** |
/** |
267 |
* getLayoutAlignmentY |
* Returns the Y alignment of the container that is laid out. This is |
268 |
* @param target TODO |
* computed by the children's preferred sizes, taking their alignments into |
269 |
* @returns float |
* account. |
270 |
|
* |
271 |
|
* @param target not used here |
272 |
|
* |
273 |
|
* @returns the X alignment of the container that is laid out |
274 |
*/ |
*/ |
275 |
public float getLayoutAlignmentY(Container target) |
public float getLayoutAlignmentY(Container target) |
276 |
{ |
{ |
277 |
return (float) 0.0; // TODO |
if (target != this.target) |
278 |
|
throw new AWTError("OverlayLayout can't be shared"); |
279 |
|
|
280 |
|
checkTotalRequirements(); |
281 |
|
return yTotal.alignment; |
282 |
} |
} |
283 |
|
|
284 |
/** |
/** |
285 |
* layoutContainer |
* Lays out the container and it's children. |
286 |
* @param target TODO |
* |
287 |
|
* The children are laid out one over another. |
288 |
|
* |
289 |
|
* The components take as much space as is available in the container, but |
290 |
|
* not more than specified by their maximum size. |
291 |
|
* |
292 |
|
* The overall layout is mainly affected by the components |
293 |
|
* <code>alignmentX</code> and <code>alignmentY</code> properties. All |
294 |
|
* components are aligned, so that their alignment points (for either |
295 |
|
* direction) are placed in one line (the baseline for this direction). |
296 |
|
* |
297 |
|
* For example: An X alignment of 0.0 means that the component's alignment |
298 |
|
* point is at it's left edge, an X alignment of 0.5 means that the alignment |
299 |
|
* point is in the middle, an X alignment of 1.0 means, the aligment point is |
300 |
|
* at the right edge. So if you have three components, the first with 0.0, |
301 |
|
* the second with 0.5 and the third with 1.0, then they are laid out like |
302 |
|
* this: |
303 |
|
* |
304 |
|
* <pre> |
305 |
|
* +-------+ |
306 |
|
* | 1 | |
307 |
|
* +-------+ |
308 |
|
* +-------+ |
309 |
|
* | 2 | |
310 |
|
* +-------+ |
311 |
|
* +---------+ |
312 |
|
* | 3 + |
313 |
|
* +---------+ |
314 |
|
* </pre> |
315 |
|
* The above picture shows the X alignment between the components. An Y |
316 |
|
* alignment like shown above cannot be achieved with this layout manager. |
317 |
|
* The components are place on top of each other, with the X alignment shown |
318 |
|
* above. |
319 |
|
* |
320 |
|
* @param target not used here |
321 |
*/ |
*/ |
322 |
public void layoutContainer(Container target) |
public void layoutContainer(Container target) |
323 |
{ |
{ |
324 |
// TODO |
if (target != this.target) |
325 |
} |
throw new AWTError("OverlayLayout can't be shared"); |
326 |
|
|
327 |
|
checkLayout(); |
328 |
|
Component[] children = target.getComponents(); |
329 |
|
for (int i = 0; i < children.length; i++) |
330 |
|
children[i].setBounds(offsetsX[i], offsetsY[i], spansX[i], spansY[i]); |
331 |
|
} |
332 |
|
|
333 |
|
/** |
334 |
|
* Makes sure that the xChildren and yChildren fields are correctly set up. |
335 |
|
* A call to {@link #invalidateLayout(Container)} sets these fields to null, |
336 |
|
* so they have to be set up again. |
337 |
|
*/ |
338 |
|
private void checkRequirements() |
339 |
|
{ |
340 |
|
if (xChildren == null || yChildren == null) |
341 |
|
{ |
342 |
|
Component[] children = target.getComponents(); |
343 |
|
xChildren = new SizeRequirements[children.length]; |
344 |
|
yChildren = new SizeRequirements[children.length]; |
345 |
|
for (int i = 0; i < children.length; i++) |
346 |
|
{ |
347 |
|
if (! children[i].isVisible()) |
348 |
|
{ |
349 |
|
xChildren[i] = new SizeRequirements(); |
350 |
|
yChildren[i] = new SizeRequirements(); |
351 |
|
} |
352 |
|
else |
353 |
|
{ |
354 |
|
xChildren[i] = |
355 |
|
new SizeRequirements(children[i].getMinimumSize().width, |
356 |
|
children[i].getPreferredSize().width, |
357 |
|
children[i].getMaximumSize().width, |
358 |
|
children[i].getAlignmentX()); |
359 |
|
yChildren[i] = |
360 |
|
new SizeRequirements(children[i].getMinimumSize().height, |
361 |
|
children[i].getPreferredSize().height, |
362 |
|
children[i].getMaximumSize().height, |
363 |
|
children[i].getAlignmentY()); |
364 |
|
} |
365 |
|
} |
366 |
|
} |
367 |
|
} |
368 |
|
|
369 |
|
/** |
370 |
|
* Makes sure that the xTotal and yTotal fields are set up correctly. A call |
371 |
|
* to {@link #invalidateLayout} sets these fields to null and they have to be |
372 |
|
* recomputed. |
373 |
|
*/ |
374 |
|
private void checkTotalRequirements() |
375 |
|
{ |
376 |
|
if (xTotal == null || yTotal == null) |
377 |
|
{ |
378 |
|
checkRequirements(); |
379 |
|
xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren); |
380 |
|
yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren); |
381 |
|
} |
382 |
|
} |
383 |
|
|
384 |
|
/** |
385 |
|
* Makes sure that the offsetsX, offsetsY, spansX and spansY fields are set |
386 |
|
* up correctly. A call to {@link #invalidateLayout} sets these fields |
387 |
|
* to null and they have to be recomputed. |
388 |
|
*/ |
389 |
|
private void checkLayout() |
390 |
|
{ |
391 |
|
if (offsetsX == null || offsetsY == null || spansX == null |
392 |
|
|| spansY == null) |
393 |
|
{ |
394 |
|
checkRequirements(); |
395 |
|
checkTotalRequirements(); |
396 |
|
int len = target.getComponents().length; |
397 |
|
offsetsX = new int[len]; |
398 |
|
offsetsY = new int[len]; |
399 |
|
spansX = new int[len]; |
400 |
|
spansY = new int[len]; |
401 |
|
|
402 |
|
Insets in = target.getInsets(); |
403 |
|
int width = target.getWidth() - in.left - in.right; |
404 |
|
int height = target.getHeight() - in.top - in.bottom; |
405 |
|
|
406 |
|
SizeRequirements.calculateAlignedPositions(width, xTotal, |
407 |
|
xChildren, offsetsX, spansX); |
408 |
|
SizeRequirements.calculateAlignedPositions(height, yTotal, |
409 |
|
yChildren, offsetsY, spansY); |
410 |
|
} |
411 |
|
} |
412 |
} |
} |