1 /*
2  * Copyright (c) 1997, 2015, Oracle and/or its affiliates. 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package javax.swing;
26 
27 import java.awt.*;
28 import java.beans.JavaBean;
29 import java.beans.BeanProperty;
30 import java.beans.ConstructorProperties;
31 import javax.accessibility.*;
32 
33 /**
34  * A lightweight container
35  * that uses a BoxLayout object as its layout manager.
36  * Box provides several class methods
37  * that are useful for containers using BoxLayout --
38  * even non-Box containers.
39  *
40  * <p>
41  * The <code>Box</code> class can create several kinds
42  * of invisible components
43  * that affect layout:
44  * glue, struts, and rigid areas.
45  * If all the components your <code>Box</code> contains
46  * have a fixed size,
47  * you might want to use a glue component
48  * (returned by <code>createGlue</code>)
49  * to control the components' positions.
50  * If you need a fixed amount of space between two components,
51  * try using a strut
52  * (<code>createHorizontalStrut</code> or <code>createVerticalStrut</code>).
53  * If you need an invisible component
54  * that always takes up the same amount of space,
55  * get it by invoking <code>createRigidArea</code>.
56  * <p>
57  * If you are implementing a <code>BoxLayout</code> you
58  * can find further information and examples in
59  * <a
60  href="https://docs.oracle.com/javase/tutorial/uiswing/layout/box.html">How to Use BoxLayout</a>,
61  * a section in <em>The Java Tutorial.</em>
62  * <p>
63  * <strong>Warning:</strong>
64  * Serialized objects of this class will not be compatible with
65  * future Swing releases. The current serialization support is
66  * appropriate for short term storage or RMI between applications running
67  * the same version of Swing.  As of 1.4, support for long term storage
68  * of all JavaBeans&trade;
69  * has been added to the <code>java.beans</code> package.
70  * Please see {@link java.beans.XMLEncoder}.
71  *
72  * @see BoxLayout
73  *
74  * @author  Timothy Prinzing
75  * @since 1.2
76  */
77 @JavaBean(defaultProperty = "accessibleContext")
78 @SuppressWarnings("serial")
79 public class Box extends JComponent implements Accessible {
80 
81     /**
82      * Creates a <code>Box</code> that displays its components
83      * along the specified axis.
84      *
85      * @param axis  can be {@link BoxLayout#X_AXIS},
86      *              {@link BoxLayout#Y_AXIS},
87      *              {@link BoxLayout#LINE_AXIS} or
88      *              {@link BoxLayout#PAGE_AXIS}.
89      * @throws AWTError if the <code>axis</code> is invalid
90      * @see #createHorizontalBox
91      * @see #createVerticalBox
92      */
Box(int axis)93     public Box(int axis) {
94         super();
95         super.setLayout(new BoxLayout(this, axis));
96     }
97 
98     /**
99      * Creates a <code>Box</code> that displays its components
100      * from left to right. If you want a <code>Box</code> that
101      * respects the component orientation you should create the
102      * <code>Box</code> using the constructor and pass in
103      * <code>BoxLayout.LINE_AXIS</code>, eg:
104      * <pre>
105      *   Box lineBox = new Box(BoxLayout.LINE_AXIS);
106      * </pre>
107      *
108      * @return the box
109      */
createHorizontalBox()110     public static Box createHorizontalBox() {
111         return new Box(BoxLayout.X_AXIS);
112     }
113 
114     /**
115      * Creates a <code>Box</code> that displays its components
116      * from top to bottom. If you want a <code>Box</code> that
117      * respects the component orientation you should create the
118      * <code>Box</code> using the constructor and pass in
119      * <code>BoxLayout.PAGE_AXIS</code>, eg:
120      * <pre>
121      *   Box lineBox = new Box(BoxLayout.PAGE_AXIS);
122      * </pre>
123      *
124      * @return the box
125      */
createVerticalBox()126     public static Box createVerticalBox() {
127         return new Box(BoxLayout.Y_AXIS);
128     }
129 
130     /**
131      * Creates an invisible component that's always the specified size.
132      * <!-- WHEN WOULD YOU USE THIS AS OPPOSED TO A STRUT? -->
133      *
134      * @param d the dimensions of the invisible component
135      * @return the component
136      * @see #createGlue
137      * @see #createHorizontalStrut
138      * @see #createVerticalStrut
139      */
createRigidArea(Dimension d)140     public static Component createRigidArea(Dimension d) {
141         return new Filler(d, d, d);
142     }
143 
144     /**
145      * Creates an invisible, fixed-width component.
146      * In a horizontal box,
147      * you typically use this method
148      * to force a certain amount of space between two components.
149      * In a vertical box,
150      * you might use this method
151      * to force the box to be at least the specified width.
152      * The invisible component has no height
153      * unless excess space is available,
154      * in which case it takes its share of available space,
155      * just like any other component that has no maximum height.
156      *
157      * @param width the width of the invisible component, in pixels &gt;= 0
158      * @return the component
159      * @see #createVerticalStrut
160      * @see #createGlue
161      * @see #createRigidArea
162      */
createHorizontalStrut(int width)163     public static Component createHorizontalStrut(int width) {
164         return new Filler(new Dimension(width,0), new Dimension(width,0),
165                           new Dimension(width, Short.MAX_VALUE));
166     }
167 
168     /**
169      * Creates an invisible, fixed-height component.
170      * In a vertical box,
171      * you typically use this method
172      * to force a certain amount of space between two components.
173      * In a horizontal box,
174      * you might use this method
175      * to force the box to be at least the specified height.
176      * The invisible component has no width
177      * unless excess space is available,
178      * in which case it takes its share of available space,
179      * just like any other component that has no maximum width.
180      *
181      * @param height the height of the invisible component, in pixels &gt;= 0
182      * @return the component
183      * @see #createHorizontalStrut
184      * @see #createGlue
185      * @see #createRigidArea
186      */
createVerticalStrut(int height)187     public static Component createVerticalStrut(int height) {
188         return new Filler(new Dimension(0,height), new Dimension(0,height),
189                           new Dimension(Short.MAX_VALUE, height));
190     }
191 
192     /**
193      * Creates an invisible "glue" component
194      * that can be useful in a Box
195      * whose visible components have a maximum width
196      * (for a horizontal box)
197      * or height (for a vertical box).
198      * You can think of the glue component
199      * as being a gooey substance
200      * that expands as much as necessary
201      * to fill the space between its neighboring components.
202      *
203      * <p>
204      *
205      * For example, suppose you have
206      * a horizontal box that contains two fixed-size components.
207      * If the box gets extra space,
208      * the fixed-size components won't become larger,
209     * so where does the extra space go?
210      * Without glue,
211      * the extra space goes to the right of the second component.
212      * If you put glue between the fixed-size components,
213      * then the extra space goes there.
214      * If you put glue before the first fixed-size component,
215      * the extra space goes there,
216      * and the fixed-size components are shoved against the right
217      * edge of the box.
218      * If you put glue before the first fixed-size component
219      * and after the second fixed-size component,
220      * the fixed-size components are centered in the box.
221      *
222      * <p>
223      *
224      * To use glue,
225      * call <code>Box.createGlue</code>
226      * and add the returned component to a container.
227      * The glue component has no minimum or preferred size,
228      * so it takes no space unless excess space is available.
229      * If excess space is available,
230      * then the glue component takes its share of available
231      * horizontal or vertical space,
232      * just like any other component that has no maximum width or height.
233      *
234      * @return the component
235      */
createGlue()236     public static Component createGlue() {
237         return new Filler(new Dimension(0,0), new Dimension(0,0),
238                           new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
239     }
240 
241     /**
242      * Creates a horizontal glue component.
243      *
244      * @return the component
245      */
createHorizontalGlue()246     public static Component createHorizontalGlue() {
247         return new Filler(new Dimension(0,0), new Dimension(0,0),
248                           new Dimension(Short.MAX_VALUE, 0));
249     }
250 
251     /**
252      * Creates a vertical glue component.
253      *
254      * @return the component
255      */
createVerticalGlue()256     public static Component createVerticalGlue() {
257         return new Filler(new Dimension(0,0), new Dimension(0,0),
258                           new Dimension(0, Short.MAX_VALUE));
259     }
260 
261     /**
262      * Throws an AWTError, since a Box can use only a BoxLayout.
263      *
264      * @param l the layout manager to use
265      */
setLayout(LayoutManager l)266     public void setLayout(LayoutManager l) {
267         throw new AWTError("Illegal request");
268     }
269 
270     /**
271      * Paints this <code>Box</code>.  If this <code>Box</code> has a UI this
272      * method invokes super's implementation, otherwise if this
273      * <code>Box</code> is opaque the <code>Graphics</code> is filled
274      * using the background.
275      *
276      * @param g the <code>Graphics</code> to paint to
277      * @throws NullPointerException if <code>g</code> is null
278      * @since 1.6
279      */
paintComponent(Graphics g)280     protected void paintComponent(Graphics g) {
281         if (ui != null) {
282             // On the off chance some one created a UI, honor it
283             super.paintComponent(g);
284         } else if (isOpaque()) {
285             g.setColor(getBackground());
286             g.fillRect(0, 0, getWidth(), getHeight());
287         }
288     }
289 
290 
291     /**
292      * An implementation of a lightweight component that participates in
293      * layout but has no view.
294      * <p>
295      * <strong>Warning:</strong>
296      * Serialized objects of this class will not be compatible with
297      * future Swing releases. The current serialization support is
298      * appropriate for short term storage or RMI between applications running
299      * the same version of Swing.  As of 1.4, support for long term storage
300      * of all JavaBeans&trade;
301      * has been added to the <code>java.beans</code> package.
302      * Please see {@link java.beans.XMLEncoder}.
303      */
304     @SuppressWarnings("serial")
305     public static class Filler extends JComponent implements Accessible {
306 
307         /**
308          * Constructor to create shape with the given size ranges.
309          *
310          * @param min   Minimum size
311          * @param pref  Preferred size
312          * @param max   Maximum size
313          */
314         @ConstructorProperties({"minimumSize", "preferredSize", "maximumSize"})
Filler(Dimension min, Dimension pref, Dimension max)315         public Filler(Dimension min, Dimension pref, Dimension max) {
316             setMinimumSize(min);
317             setPreferredSize(pref);
318             setMaximumSize(max);
319         }
320 
321         /**
322          * Change the size requests for this shape.  An invalidate() is
323          * propagated upward as a result so that layout will eventually
324          * happen with using the new sizes.
325          *
326          * @param min   Value to return for getMinimumSize
327          * @param pref  Value to return for getPreferredSize
328          * @param max   Value to return for getMaximumSize
329          */
changeShape(Dimension min, Dimension pref, Dimension max)330         public void changeShape(Dimension min, Dimension pref, Dimension max) {
331             setMinimumSize(min);
332             setPreferredSize(pref);
333             setMaximumSize(max);
334             revalidate();
335         }
336 
337         // ---- Component methods ------------------------------------------
338 
339         /**
340          * Paints this <code>Filler</code>.  If this
341          * <code>Filler</code> has a UI this method invokes super's
342          * implementation, otherwise if this <code>Filler</code> is
343          * opaque the <code>Graphics</code> is filled using the
344          * background.
345          *
346          * @param g the <code>Graphics</code> to paint to
347          * @throws NullPointerException if <code>g</code> is null
348          * @since 1.6
349          */
paintComponent(Graphics g)350         protected void paintComponent(Graphics g) {
351             if (ui != null) {
352                 // On the off chance some one created a UI, honor it
353                 super.paintComponent(g);
354             } else if (isOpaque()) {
355                 g.setColor(getBackground());
356                 g.fillRect(0, 0, getWidth(), getHeight());
357             }
358         }
359 
360 /////////////////
361 // Accessibility support for Box$Filler
362 ////////////////
363 
364         /**
365          * Gets the AccessibleContext associated with this Box.Filler.
366          * For box fillers, the AccessibleContext takes the form of an
367          * AccessibleBoxFiller.
368          * A new AccessibleAWTBoxFiller instance is created if necessary.
369          *
370          * @return an AccessibleBoxFiller that serves as the
371          *         AccessibleContext of this Box.Filler.
372          */
getAccessibleContext()373         public AccessibleContext getAccessibleContext() {
374             if (accessibleContext == null) {
375                 accessibleContext = new AccessibleBoxFiller();
376             }
377             return accessibleContext;
378         }
379 
380         /**
381          * This class implements accessibility support for the
382          * <code>Box.Filler</code> class.
383          */
384         @SuppressWarnings("serial")
385         protected class AccessibleBoxFiller extends AccessibleAWTComponent {
386             // AccessibleContext methods
387             //
388             /**
389              * Gets the role of this object.
390              *
391              * @return an instance of AccessibleRole describing the role of
392              *   the object (AccessibleRole.FILLER)
393              * @see AccessibleRole
394              */
getAccessibleRole()395             public AccessibleRole getAccessibleRole() {
396                 return AccessibleRole.FILLER;
397             }
398         }
399     }
400 
401 /////////////////
402 // Accessibility support for Box
403 ////////////////
404 
405     /**
406      * Gets the AccessibleContext associated with this Box.
407      * For boxes, the AccessibleContext takes the form of an
408      * AccessibleBox.
409      * A new AccessibleAWTBox instance is created if necessary.
410      *
411      * @return an AccessibleBox that serves as the
412      *         AccessibleContext of this Box
413      */
414     @BeanProperty(bound = false)
getAccessibleContext()415     public AccessibleContext getAccessibleContext() {
416         if (accessibleContext == null) {
417             accessibleContext = new AccessibleBox();
418         }
419         return accessibleContext;
420     }
421 
422     /**
423      * This class implements accessibility support for the
424      * <code>Box</code> class.
425      */
426     @SuppressWarnings("serial")
427     protected class AccessibleBox extends AccessibleAWTContainer {
428         // AccessibleContext methods
429         //
430         /**
431          * Gets the role of this object.
432          *
433          * @return an instance of AccessibleRole describing the role of the
434          *   object (AccessibleRole.FILLER)
435          * @see AccessibleRole
436          */
getAccessibleRole()437         public AccessibleRole getAccessibleRole() {
438             return AccessibleRole.FILLER;
439         }
440     } // inner class AccessibleBox
441 }
442