Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/javax/swing/BoxLayout.java
+++ new/src/share/classes/javax/swing/BoxLayout.java
1 1 /*
2 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25
26 26
27 27 package javax.swing;
28 28
29 29 import java.awt.*;
30 30 import java.beans.ConstructorProperties;
31 31 import java.io.Serializable;
32 32 import java.io.PrintStream;
33 33
34 34 /**
35 35 * A layout manager that allows multiple components to be laid out either
36 36 * vertically or horizontally. The components will not wrap so, for
37 37 * example, a vertical arrangement of components will stay vertically
38 38 * arranged when the frame is resized.
39 39 * <TABLE STYLE="FLOAT:RIGHT" BORDER="0" SUMMARY="layout">
40 40 * <TR>
41 41 * <TD ALIGN="CENTER">
42 42 * <P STYLE="TEXT-ALIGN:CENTER"><IMG SRC="doc-files/BoxLayout-1.gif"
43 43 * alt="The following text describes this graphic."
44 44 * WIDTH="191" HEIGHT="201" STYLE="FLOAT:BOTTOM; BORDER:0">
45 45 * </TD>
46 46 * </TR>
47 47 * </TABLE>
48 48 * <p>
49 49 * Nesting multiple panels with different combinations of horizontal and
50 50 * vertical gives an effect similar to GridBagLayout, without the
51 51 * complexity. The diagram shows two panels arranged horizontally, each
52 52 * of which contains 3 components arranged vertically.
53 53 *
54 54 * <p> The BoxLayout manager is constructed with an axis parameter that
55 55 * specifies the type of layout that will be done. There are four choices:
56 56 *
57 57 * <blockquote><b><tt>X_AXIS</tt></b> - Components are laid out horizontally
58 58 * from left to right.</blockquote>
59 59 *
60 60 * <blockquote><b><tt>Y_AXIS</tt></b> - Components are laid out vertically
61 61 * from top to bottom.</blockquote>
62 62 *
63 63 * <blockquote><b><tt>LINE_AXIS</tt></b> - Components are laid out the way
64 64 * words are laid out in a line, based on the container's
65 65 * <tt>ComponentOrientation</tt> property. If the container's
66 66 * <tt>ComponentOrientation</tt> is horizontal then components are laid out
67 67 * horizontally, otherwise they are laid out vertically. For horizontal
68 68 * orientations, if the container's <tt>ComponentOrientation</tt> is left to
69 69 * right then components are laid out left to right, otherwise they are laid
70 70 * out right to left. For vertical orientations components are always laid out
71 71 * from top to bottom.</blockquote>
72 72 *
73 73 * <blockquote><b><tt>PAGE_AXIS</tt></b> - Components are laid out the way
74 74 * text lines are laid out on a page, based on the container's
75 75 * <tt>ComponentOrientation</tt> property. If the container's
76 76 * <tt>ComponentOrientation</tt> is horizontal then components are laid out
77 77 * vertically, otherwise they are laid out horizontally. For horizontal
78 78 * orientations, if the container's <tt>ComponentOrientation</tt> is left to
79 79 * right then components are laid out left to right, otherwise they are laid
80 80 * out right to left. For vertical orientations components are always
81 81 * laid out from top to bottom.</blockquote>
82 82 * <p>
83 83 * For all directions, components are arranged in the same order as they were
84 84 * added to the container.
85 85 * <p>
86 86 * BoxLayout attempts to arrange components
87 87 * at their preferred widths (for horizontal layout)
88 88 * or heights (for vertical layout).
89 89 * For a horizontal layout,
90 90 * if not all the components are the same height,
91 91 * BoxLayout attempts to make all the components
92 92 * as high as the highest component.
93 93 * If that's not possible for a particular component,
94 94 * then BoxLayout aligns that component vertically,
95 95 * according to the component's Y alignment.
96 96 * By default, a component has a Y alignment of 0.5,
97 97 * which means that the vertical center of the component
98 98 * should have the same Y coordinate as
99 99 * the vertical centers of other components with 0.5 Y alignment.
100 100 * <p>
101 101 * Similarly, for a vertical layout,
102 102 * BoxLayout attempts to make all components in the column
103 103 * as wide as the widest component.
104 104 * If that fails, it aligns them horizontally
105 105 * according to their X alignments. For <code>PAGE_AXIS</code> layout,
106 106 * horizontal alignment is done based on the leading edge of the component.
107 107 * In other words, an X alignment value of 0.0 means the left edge of a
108 108 * component if the container's <code>ComponentOrientation</code> is left to
↓ open down ↓ |
108 lines elided |
↑ open up ↑ |
109 109 * right and it means the right edge of the component otherwise.
110 110 * <p>
111 111 * Instead of using BoxLayout directly, many programs use the Box class.
112 112 * The Box class is a lightweight container that uses a BoxLayout.
113 113 * It also provides handy methods to help you use BoxLayout well.
114 114 * Adding components to multiple nested boxes is a powerful way to get
115 115 * the arrangement you want.
116 116 * <p>
117 117 * For further information and examples see
118 118 * <a
119 - href="http://docs.oracle.com/javase/tutorial/uiswing/layout/box.html">How to Use BoxLayout</a>,
119 + href="https://docs.oracle.com/javase/tutorial/uiswing/layout/box.html">How to Use BoxLayout</a>,
120 120 * a section in <em>The Java Tutorial.</em>
121 121 * <p>
122 122 * <strong>Warning:</strong>
123 123 * Serialized objects of this class will not be compatible with
124 124 * future Swing releases. The current serialization support is
125 125 * appropriate for short term storage or RMI between applications running
126 126 * the same version of Swing. As of 1.4, support for long term storage
127 127 * of all JavaBeans™
128 128 * has been added to the <code>java.beans</code> package.
129 129 * Please see {@link java.beans.XMLEncoder}.
130 130 *
131 131 * @see Box
132 132 * @see java.awt.ComponentOrientation
133 133 * @see JComponent#getAlignmentX
134 134 * @see JComponent#getAlignmentY
135 135 *
136 136 * @author Timothy Prinzing
137 137 */
138 138 @SuppressWarnings("serial")
139 139 public class BoxLayout implements LayoutManager2, Serializable {
140 140
141 141 /**
142 142 * Specifies that components should be laid out left to right.
143 143 */
144 144 public static final int X_AXIS = 0;
145 145
146 146 /**
147 147 * Specifies that components should be laid out top to bottom.
148 148 */
149 149 public static final int Y_AXIS = 1;
150 150
151 151 /**
152 152 * Specifies that components should be laid out in the direction of
153 153 * a line of text as determined by the target container's
154 154 * <code>ComponentOrientation</code> property.
155 155 */
156 156 public static final int LINE_AXIS = 2;
157 157
158 158 /**
159 159 * Specifies that components should be laid out in the direction that
160 160 * lines flow across a page as determined by the target container's
161 161 * <code>ComponentOrientation</code> property.
162 162 */
163 163 public static final int PAGE_AXIS = 3;
164 164
165 165 /**
166 166 * Creates a layout manager that will lay out components along the
167 167 * given axis.
168 168 *
169 169 * @param target the container that needs to be laid out
170 170 * @param axis the axis to lay out components along. Can be one of:
171 171 * <code>BoxLayout.X_AXIS</code>,
172 172 * <code>BoxLayout.Y_AXIS</code>,
173 173 * <code>BoxLayout.LINE_AXIS</code> or
174 174 * <code>BoxLayout.PAGE_AXIS</code>
175 175 *
176 176 * @exception AWTError if the value of <code>axis</code> is invalid
177 177 */
178 178 @ConstructorProperties({"target", "axis"})
179 179 public BoxLayout(Container target, int axis) {
180 180 if (axis != X_AXIS && axis != Y_AXIS &&
181 181 axis != LINE_AXIS && axis != PAGE_AXIS) {
182 182 throw new AWTError("Invalid axis");
183 183 }
184 184 this.axis = axis;
185 185 this.target = target;
186 186 }
187 187
188 188 /**
189 189 * Constructs a BoxLayout that
190 190 * produces debugging messages.
191 191 *
192 192 * @param target the container that needs to be laid out
193 193 * @param axis the axis to lay out components along. Can be one of:
194 194 * <code>BoxLayout.X_AXIS</code>,
195 195 * <code>BoxLayout.Y_AXIS</code>,
196 196 * <code>BoxLayout.LINE_AXIS</code> or
197 197 * <code>BoxLayout.PAGE_AXIS</code>
198 198 *
199 199 * @param dbg the stream to which debugging messages should be sent,
200 200 * null if none
201 201 */
202 202 BoxLayout(Container target, int axis, PrintStream dbg) {
203 203 this(target, axis);
204 204 this.dbg = dbg;
205 205 }
206 206
207 207 /**
208 208 * Returns the container that uses this layout manager.
209 209 *
210 210 * @return the container that uses this layout manager
211 211 *
212 212 * @since 1.6
213 213 */
214 214 public final Container getTarget() {
215 215 return this.target;
216 216 }
217 217
218 218 /**
219 219 * Returns the axis that was used to lay out components.
220 220 * Returns one of:
221 221 * <code>BoxLayout.X_AXIS</code>,
222 222 * <code>BoxLayout.Y_AXIS</code>,
223 223 * <code>BoxLayout.LINE_AXIS</code> or
224 224 * <code>BoxLayout.PAGE_AXIS</code>
225 225 *
226 226 * @return the axis that was used to lay out components
227 227 *
228 228 * @since 1.6
229 229 */
230 230 public final int getAxis() {
231 231 return this.axis;
232 232 }
233 233
234 234 /**
235 235 * Indicates that a child has changed its layout related information,
236 236 * and thus any cached calculations should be flushed.
237 237 * <p>
238 238 * This method is called by AWT when the invalidate method is called
239 239 * on the Container. Since the invalidate method may be called
240 240 * asynchronously to the event thread, this method may be called
241 241 * asynchronously.
242 242 *
243 243 * @param target the affected container
244 244 *
245 245 * @exception AWTError if the target isn't the container specified to the
246 246 * BoxLayout constructor
247 247 */
248 248 public synchronized void invalidateLayout(Container target) {
249 249 checkContainer(target);
250 250 xChildren = null;
251 251 yChildren = null;
252 252 xTotal = null;
253 253 yTotal = null;
254 254 }
255 255
256 256 /**
257 257 * Not used by this class.
258 258 *
259 259 * @param name the name of the component
260 260 * @param comp the component
261 261 */
262 262 public void addLayoutComponent(String name, Component comp) {
263 263 invalidateLayout(comp.getParent());
264 264 }
265 265
266 266 /**
267 267 * Not used by this class.
268 268 *
269 269 * @param comp the component
270 270 */
271 271 public void removeLayoutComponent(Component comp) {
272 272 invalidateLayout(comp.getParent());
273 273 }
274 274
275 275 /**
276 276 * Not used by this class.
277 277 *
278 278 * @param comp the component
279 279 * @param constraints constraints
280 280 */
281 281 public void addLayoutComponent(Component comp, Object constraints) {
282 282 invalidateLayout(comp.getParent());
283 283 }
284 284
285 285 /**
286 286 * Returns the preferred dimensions for this layout, given the components
287 287 * in the specified target container.
288 288 *
289 289 * @param target the container that needs to be laid out
290 290 * @return the dimensions >= 0 && <= Integer.MAX_VALUE
291 291 * @exception AWTError if the target isn't the container specified to the
292 292 * BoxLayout constructor
293 293 * @see Container
294 294 * @see #minimumLayoutSize
295 295 * @see #maximumLayoutSize
296 296 */
297 297 public Dimension preferredLayoutSize(Container target) {
298 298 Dimension size;
299 299 synchronized(this) {
300 300 checkContainer(target);
301 301 checkRequests();
302 302 size = new Dimension(xTotal.preferred, yTotal.preferred);
303 303 }
304 304
305 305 Insets insets = target.getInsets();
306 306 size.width = (int) Math.min((long) size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE);
307 307 size.height = (int) Math.min((long) size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE);
308 308 return size;
309 309 }
310 310
311 311 /**
312 312 * Returns the minimum dimensions needed to lay out the components
313 313 * contained in the specified target container.
314 314 *
315 315 * @param target the container that needs to be laid out
316 316 * @return the dimensions >= 0 && <= Integer.MAX_VALUE
317 317 * @exception AWTError if the target isn't the container specified to the
318 318 * BoxLayout constructor
319 319 * @see #preferredLayoutSize
320 320 * @see #maximumLayoutSize
321 321 */
322 322 public Dimension minimumLayoutSize(Container target) {
323 323 Dimension size;
324 324 synchronized(this) {
325 325 checkContainer(target);
326 326 checkRequests();
327 327 size = new Dimension(xTotal.minimum, yTotal.minimum);
328 328 }
329 329
330 330 Insets insets = target.getInsets();
331 331 size.width = (int) Math.min((long) size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE);
332 332 size.height = (int) Math.min((long) size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE);
333 333 return size;
334 334 }
335 335
336 336 /**
337 337 * Returns the maximum dimensions the target container can use
338 338 * to lay out the components it contains.
339 339 *
340 340 * @param target the container that needs to be laid out
341 341 * @return the dimensions >= 0 && <= Integer.MAX_VALUE
342 342 * @exception AWTError if the target isn't the container specified to the
343 343 * BoxLayout constructor
344 344 * @see #preferredLayoutSize
345 345 * @see #minimumLayoutSize
346 346 */
347 347 public Dimension maximumLayoutSize(Container target) {
348 348 Dimension size;
349 349 synchronized(this) {
350 350 checkContainer(target);
351 351 checkRequests();
352 352 size = new Dimension(xTotal.maximum, yTotal.maximum);
353 353 }
354 354
355 355 Insets insets = target.getInsets();
356 356 size.width = (int) Math.min((long) size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE);
357 357 size.height = (int) Math.min((long) size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE);
358 358 return size;
359 359 }
360 360
361 361 /**
362 362 * Returns the alignment along the X axis for the container.
363 363 * If the box is horizontal, the default
364 364 * alignment will be returned. Otherwise, the alignment needed
365 365 * to place the children along the X axis will be returned.
366 366 *
367 367 * @param target the container
368 368 * @return the alignment >= 0.0f && <= 1.0f
369 369 * @exception AWTError if the target isn't the container specified to the
370 370 * BoxLayout constructor
371 371 */
372 372 public synchronized float getLayoutAlignmentX(Container target) {
373 373 checkContainer(target);
374 374 checkRequests();
375 375 return xTotal.alignment;
376 376 }
377 377
378 378 /**
379 379 * Returns the alignment along the Y axis for the container.
380 380 * If the box is vertical, the default
381 381 * alignment will be returned. Otherwise, the alignment needed
382 382 * to place the children along the Y axis will be returned.
383 383 *
384 384 * @param target the container
385 385 * @return the alignment >= 0.0f && <= 1.0f
386 386 * @exception AWTError if the target isn't the container specified to the
387 387 * BoxLayout constructor
388 388 */
389 389 public synchronized float getLayoutAlignmentY(Container target) {
390 390 checkContainer(target);
391 391 checkRequests();
392 392 return yTotal.alignment;
393 393 }
394 394
395 395 /**
396 396 * Called by the AWT <!-- XXX CHECK! --> when the specified container
397 397 * needs to be laid out.
398 398 *
399 399 * @param target the container to lay out
400 400 *
401 401 * @exception AWTError if the target isn't the container specified to the
402 402 * BoxLayout constructor
403 403 */
404 404 public void layoutContainer(Container target) {
405 405 checkContainer(target);
406 406 int nChildren = target.getComponentCount();
407 407 int[] xOffsets = new int[nChildren];
408 408 int[] xSpans = new int[nChildren];
409 409 int[] yOffsets = new int[nChildren];
410 410 int[] ySpans = new int[nChildren];
411 411
412 412 Dimension alloc = target.getSize();
413 413 Insets in = target.getInsets();
414 414 alloc.width -= in.left + in.right;
415 415 alloc.height -= in.top + in.bottom;
416 416
417 417 // Resolve axis to an absolute value (either X_AXIS or Y_AXIS)
418 418 ComponentOrientation o = target.getComponentOrientation();
419 419 int absoluteAxis = resolveAxis( axis, o );
420 420 boolean ltr = (absoluteAxis != axis) ? o.isLeftToRight() : true;
421 421
422 422
423 423 // determine the child placements
424 424 synchronized(this) {
425 425 checkRequests();
426 426
427 427 if (absoluteAxis == X_AXIS) {
428 428 SizeRequirements.calculateTiledPositions(alloc.width, xTotal,
429 429 xChildren, xOffsets,
430 430 xSpans, ltr);
431 431 SizeRequirements.calculateAlignedPositions(alloc.height, yTotal,
432 432 yChildren, yOffsets,
433 433 ySpans);
434 434 } else {
435 435 SizeRequirements.calculateAlignedPositions(alloc.width, xTotal,
436 436 xChildren, xOffsets,
437 437 xSpans, ltr);
438 438 SizeRequirements.calculateTiledPositions(alloc.height, yTotal,
439 439 yChildren, yOffsets,
440 440 ySpans);
441 441 }
442 442 }
443 443
444 444 // flush changes to the container
445 445 for (int i = 0; i < nChildren; i++) {
446 446 Component c = target.getComponent(i);
447 447 c.setBounds((int) Math.min((long) in.left + (long) xOffsets[i], Integer.MAX_VALUE),
448 448 (int) Math.min((long) in.top + (long) yOffsets[i], Integer.MAX_VALUE),
449 449 xSpans[i], ySpans[i]);
450 450
451 451 }
452 452 if (dbg != null) {
453 453 for (int i = 0; i < nChildren; i++) {
454 454 Component c = target.getComponent(i);
455 455 dbg.println(c.toString());
456 456 dbg.println("X: " + xChildren[i]);
457 457 dbg.println("Y: " + yChildren[i]);
458 458 }
459 459 }
460 460
461 461 }
462 462
463 463 void checkContainer(Container target) {
464 464 if (this.target != target) {
465 465 throw new AWTError("BoxLayout can't be shared");
466 466 }
467 467 }
468 468
469 469 void checkRequests() {
470 470 if (xChildren == null || yChildren == null) {
471 471 // The requests have been invalidated... recalculate
472 472 // the request information.
473 473 int n = target.getComponentCount();
474 474 xChildren = new SizeRequirements[n];
475 475 yChildren = new SizeRequirements[n];
476 476 for (int i = 0; i < n; i++) {
477 477 Component c = target.getComponent(i);
478 478 if (!c.isVisible()) {
479 479 xChildren[i] = new SizeRequirements(0,0,0, c.getAlignmentX());
480 480 yChildren[i] = new SizeRequirements(0,0,0, c.getAlignmentY());
481 481 continue;
482 482 }
483 483 Dimension min = c.getMinimumSize();
484 484 Dimension typ = c.getPreferredSize();
485 485 Dimension max = c.getMaximumSize();
486 486 xChildren[i] = new SizeRequirements(min.width, typ.width,
487 487 max.width,
488 488 c.getAlignmentX());
489 489 yChildren[i] = new SizeRequirements(min.height, typ.height,
490 490 max.height,
491 491 c.getAlignmentY());
492 492 }
493 493
494 494 // Resolve axis to an absolute value (either X_AXIS or Y_AXIS)
495 495 int absoluteAxis = resolveAxis(axis,target.getComponentOrientation());
496 496
497 497 if (absoluteAxis == X_AXIS) {
498 498 xTotal = SizeRequirements.getTiledSizeRequirements(xChildren);
499 499 yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren);
500 500 } else {
501 501 xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren);
502 502 yTotal = SizeRequirements.getTiledSizeRequirements(yChildren);
503 503 }
504 504 }
505 505 }
506 506
507 507 /**
508 508 * Given one of the 4 axis values, resolve it to an absolute axis.
509 509 * The relative axis values, PAGE_AXIS and LINE_AXIS are converted
510 510 * to their absolute couterpart given the target's ComponentOrientation
511 511 * value. The absolute axes, X_AXIS and Y_AXIS are returned unmodified.
512 512 *
513 513 * @param axis the axis to resolve
514 514 * @param o the ComponentOrientation to resolve against
515 515 * @return the resolved axis
516 516 */
517 517 private int resolveAxis( int axis, ComponentOrientation o ) {
518 518 int absoluteAxis;
519 519 if( axis == LINE_AXIS ) {
520 520 absoluteAxis = o.isHorizontal() ? X_AXIS : Y_AXIS;
521 521 } else if( axis == PAGE_AXIS ) {
522 522 absoluteAxis = o.isHorizontal() ? Y_AXIS : X_AXIS;
523 523 } else {
524 524 absoluteAxis = axis;
525 525 }
526 526 return absoluteAxis;
527 527 }
528 528
529 529
530 530 private int axis;
531 531 private Container target;
532 532
533 533 private transient SizeRequirements[] xChildren;
534 534 private transient SizeRequirements[] yChildren;
535 535 private transient SizeRequirements xTotal;
536 536 private transient SizeRequirements yTotal;
537 537
538 538 private transient PrintStream dbg;
539 539 }
↓ open down ↓ |
410 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX