bb.gui
Class LineLayout

java.lang.Object
  extended by bb.gui.LineLayout
All Implemented Interfaces:
LayoutManager, LayoutManager2, Serializable

public class LineLayout
extends Object
implements LayoutManager2, Serializable

This layout manager is intended to offer similar functionality as BoxLayout. It was written solely to fix bugs/bad behavior in BoxLayout.

Because of this class's deep similarity with BoxLayout, the following description, which was lifted from the javadocs of BoxLayout and customized, applies here:

LineLayout is a layout manager that allows multiple Components to be layed out either vertically or horizontally. The Components will not wrap so, for example, a vertical arrangement of Components will stay vertically arranged when the frame is resized.

When you create a LineLayout, you specify whether its major axis is the x-axis (i.e. left to right placement) or y-axis (i.e. top to bottom placement). Components are arranged from left to right (or top to bottom), in the same order as they were added to the Container. Invisible Components are ignored (they never affect the layout).

For left to right layout, Components start to the right of the left edge, and are laid out edge-edge, heading right, in the order in which they were added, at their preferred sizes. Each Component's y-alignment is used to determine where it sits above or below the horizontal line going thru the middle of the target Container. (Its x-alignment is ignored.)

For top to bottom layout, Components start below the top edge, and are laid out edge-edge, heading to the bottom, in the order in which they were added, at their preferred sizes. Each Component's x-alignment is used to determine where it sits left or right of the vertical line going down the middle of the target Container. (Its y-alignment is ignored.)

Nesting multiple panels with different combinations of horizontal and vertical layout gives an effect similar to GridBagLayout, without the complexity.

Instead of using LineLayout directly, programs may find it convenient to use the LinePanel class. LinePanel is a lightweight Swing container that initially uses a LineLayout. LinePanel also provides handy strut methods to help you use LineLayout well.

In terms of the API exposed by this class, it is identical to BoxLayout with one exception: its sole constructor only requires specification of the alignment axis.

Moving beyond method signatures to method semantics, this class is mostly identical to BoxLayout with the following exceptions:

  1. LineLayout always draws Components at their preferred dimensions.
    Warning: one consequence is that Glue Components (e.g. from Box.createHorizontalGlue) are always displayed at zero size (since that is their preferred size), so they probably will not have the same effect as they do in other LayoutManagers.
  2. LineLayout uses the x or y alignment of a Component to set its justification in a consistent and natural way. Specificly, for a vertical (y-axis) layout, an x-alignment value of 0 will make the Component left justified, 0.5f will make it center justified, 1.0f will make it right justified, and other values cause intermediate justification. Similarly, for a horizontal (x-axis) layout, a y-alignment value of 0 will make the Component top justified, 0.5f will make it center justified, 1.0f will make it bottom justified, and other values cause intermediate justification. (BoxLayout works inconsistently with alignment values. Consequently, the only way to achieve justification with it is to use barbaric techniques such as embedding Components inside Panels, and placing Glue/Strut Components to the sides.)
  3. Both getLayoutAlignmentX and getLayoutAlignmentY always return 0.5f to indicate centered. (This behavior is identical to BorderLayout, CardLayout, and GridBagLayout, while BoxLayout and OverlayLayout do more complicated stuff.)
  4. This class currently does not support the relative LINE_AXIS and PAGE_AXIS axis options of BoxLayout; support for these options is intended to be added in the future.

Other than the LineLayout.UnitTest inner class of this class, there is no Swing-specific functionality in this class. Thus, this LayoutManager may be used even in all-AWT programs.

Like typical Java GUI code, this class is not multithread safe: it expects to only be called by EventQueue's dispatch thread. This threading limitation is checked in every public method.

Author:
Brent Boyer
See Also:
Serialized Form

Nested Class Summary
static class LineLayout.UnitTest
          See the Overview page of the project's javadocs for a general description of this unit test class.
 
Field Summary
private  int axis
          Stores which axis to align along (i.e. the tiled dimension).
private  Container firstTarget
          Stores the first Container to use this instance (only one may ever use it).
private static long serialVersionUID
           
private  Dimension totalMaximumSize
          Caches the value returned by maximumLayoutSize.
private  Dimension totalMinimumSize
          Caches the value returned by minimumLayoutSize.
private  Dimension totalPreferredSize
          Caches the value returned by preferredLayoutSize.
private  boolean validatedStatus
          Records whether or not this LayoutManager has been validated against the current version of the target Container.
static int xAxis
          Specifies that Components should be laid out left to right.
static int yAxis
          Specifies that Components should be laid out top to bottom.
 
Constructor Summary
LineLayout(int axis)
          Creates a layout manager that will lay out Components in a line either left to right or top to bottom, as specified in the axis argument.
 
Method Summary
 void addLayoutComponent(Component comp, Object constraints)
          Not used by this class (is implemented as an empty method).
 void addLayoutComponent(String name, Component comp)
          Not used by this class (is implemented as an empty method).
protected  int calcXOffset(Component c, Dimension allocSize, Insets insets)
          Calculates the x-offset of a Component, taking into effect both the x-axis alignment of the Component and the Insets of the parent Container.
protected  int calcYOffset(Component c, Dimension allocSize, Insets insets)
          Calculates the y-offset of a Component, taking into effect both the y-axis alignment of the Component and the Insets of the parent Container.
protected  void checkContainerArgAndThread(Container target)
          Confirms that target is the same Container that this LineLayout instance was first used with.
protected  Dimension decreaseSizeForInsets(Dimension size, Insets insets)
          Returns a new Dimension instance that comes from decreasing the supplied Dimension arg to account for the target Container's Insets.
 float getLayoutAlignmentX(Container target)
          Returns the alignment along the x axis.
 float getLayoutAlignmentY(Container target)
          Returns the alignment along the y axis.
protected  void increaseSizeForInsets(Dimension size, Container target)
          Increases the supplied Dimension arg to account for the target Container's Insets.
 void invalidateLayout(Container target)
          Indicates that a child has changed its layout related information, and thus any cached calculations should be flushed.
 void layoutContainer(Container target)
          Called by the AWT when the specified Container needs to be laid out.
static LineLayout makeHorizontal()
          Simply returns new LineLayout(xAxis).
static LineLayout makeVertical()
          Simply returns new LineLayout(yAxis).
 Dimension maximumLayoutSize(Container target)
          Returns the maximum dimensions needed to lay out the Components contained in the specified target container.
 Dimension minimumLayoutSize(Container target)
          Returns the minimum dimensions needed to lay out the Components contained in the specified target container.
 Dimension preferredLayoutSize(Container target)
          Returns the preferred dimensions needed to lay out the Components contained in the specified target container.
 void removeLayoutComponent(Component comp)
          Not used by this class (is implemented as an empty method).
protected  void revalidateLayout(Container target)
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

serialVersionUID

private static final long serialVersionUID
See Also:
Constant Field Values

xAxis

public static final int xAxis
Specifies that Components should be laid out left to right. In other words, this value selects the x-axis as the tiled dimension, and the y-axis as the aligned dimension.

See Also:
Constant Field Values

yAxis

public static final int yAxis
Specifies that Components should be laid out top to bottom. In other words, this value selects the y-axis as the tiled dimension, and the x-axis as the aligned dimension.

See Also:
Constant Field Values

axis

private final int axis
Stores which axis to align along (i.e. the tiled dimension).


firstTarget

private Container firstTarget
Stores the first Container to use this instance (only one may ever use it).


totalMinimumSize

private final Dimension totalMinimumSize
Caches the value returned by minimumLayoutSize. Calculated inside revalidateLayout as follows:
  1. in the tiled dimension, is the sum of the minimum sizes of each Component held in the Container
  2. in the aligned dimension, is the individual maximum of all the minimum sizes among all such Components.
Finally, both dimensions are increased to account for the target Container's insets.

See Also:
xAxis, yAxis

totalPreferredSize

private final Dimension totalPreferredSize
Caches the value returned by preferredLayoutSize. Calculated inside revalidateLayout as follows:
  1. in the tiled dimension, is the sum of the preferred sizes of each Component held in the Container
  2. in the aligned dimension, is the preferred maximum of all the minimum sizes among all such Components.
Finally, both dimensions are increased to account for the target Container's insets.

See Also:
xAxis, yAxis

totalMaximumSize

private final Dimension totalMaximumSize
Caches the value returned by maximumLayoutSize. Calculated inside revalidateLayout as follows:
  1. in the tiled dimension, is the sum of the maximum sizes of each Component held in the Container
  2. in the aligned dimension, is the individual maximum of all the maximum sizes among all such Components.
Finally, both dimensions are increased to account for the target Container's insets.

See Also:
xAxis, yAxis

validatedStatus

private boolean validatedStatus
Records whether or not this LayoutManager has been validated against the current version of the target Container.

See Also:
invalidateLayout, revalidateLayout
Constructor Detail

LineLayout

public LineLayout(int axis)
           throws IllegalArgumentException,
                  IllegalStateException
Creates a layout manager that will lay out Components in a line either left to right or top to bottom, as specified in the axis argument.

Note: unlike the corresponding BoxLayout constructor, the LineLayout constructor does not take a Container arg. Instead, the target Container is more conveniently established by "lazy initialization". Specificly, the first Container arg that is presented to one of the LayoutManager or LayoutManager2 methods of this class will establish what target Container this instance is for.

This elimination of the Container arg allows for a convenient compaction of code. Compare:


        JPanel jpanel = new JPanel( new LineLayout(LineLayout.xAxis) );
 
versus

        JPanel jpanel = new JPanel();
        jpanel.setLayout( new BoxLayout(jpanel, BoxLayout.xAxis) );
 
(Even more convenient are the methods makeHorizontal and makeVertical.)

Parameters:
axis - the axis to lay out Components along. For left-to-right layout, specify LineLayout.xAxis; for top-to-bottom layout, specify LineLayout.yAxis
Throws:
IllegalArgumentException - if the axis arg has an invalid value
IllegalStateException - if calling thread is not EventQueue's dispatch thread
Method Detail

makeHorizontal

public static LineLayout makeHorizontal()
                                 throws IllegalStateException
Simply returns new LineLayout(xAxis).

Example use: JPanel jpanel = new JPanel( LineLayout.makeHorizontal() );

Throws:
IllegalStateException - if calling thread is not EventQueue's dispatch thread

makeVertical

public static LineLayout makeVertical()
                               throws IllegalStateException
Simply returns new LineLayout(yAxis).

Example use: JPanel jpanel = new JPanel( LineLayout.makeVertical() );

Throws:
IllegalStateException - if calling thread is not EventQueue's dispatch thread

getLayoutAlignmentX

public float getLayoutAlignmentX(Container target)
                          throws AWTError,
                                 IllegalStateException
Returns the alignment along the x axis. This specifies how target would like to be aligned relative to other Components. The value should be a number between 0 and 1 where 0 represents alignment along the origin, 1 is aligned the furthest away from the origin, 0.5 is centered, etc.

Specified by:
getLayoutAlignmentX in interface LayoutManager2
Parameters:
target - a Container
Returns:
the value 0.5f to indicate centered
Throws:
AWTError - if checkContainerArgAndThread objects to container
IllegalStateException - if calling thread is not EventQueue's dispatch thread

getLayoutAlignmentY

public float getLayoutAlignmentY(Container target)
                          throws AWTError,
                                 IllegalStateException
Returns the alignment along the y axis. This specifies how target would like to be aligned relative to other Components. The value should be a number between 0 and 1 where 0 represents alignment along the origin, 1 is aligned the furthest away from the origin, 0.5 is centered, etc.

Specified by:
getLayoutAlignmentY in interface LayoutManager2
Parameters:
target - a Container
Returns:
the value 0.5f to indicate centered
Throws:
AWTError - if checkContainerArgAndThread objects to container
IllegalStateException - if calling thread is not EventQueue's dispatch thread

minimumLayoutSize

public Dimension minimumLayoutSize(Container target)
                            throws AWTError,
                                   IllegalStateException
Returns the minimum dimensions needed to lay out the Components contained in the specified target container. Invisible child Components are ignored in the calculation. The result includes the effects of the target container's insets.

Specified by:
minimumLayoutSize in interface LayoutManager
Parameters:
target - the Container that needs to be laid out
Returns:
a new Dimension instance (both the height and width are >= 0 && <= Integer.MAX_VALUE)
Throws:
AWTError - if checkContainerArgAndThread objects to container
IllegalStateException - if calling thread is not EventQueue's dispatch thread
See Also:
preferredLayoutSize, maximumLayoutSize

preferredLayoutSize

public Dimension preferredLayoutSize(Container target)
                              throws AWTError,
                                     IllegalStateException
Returns the preferred dimensions needed to lay out the Components contained in the specified target container. Invisible child Components are ignored in the calculation. The result includes the effects of the target container's insets.

Specified by:
preferredLayoutSize in interface LayoutManager
Parameters:
target - the Container that needs to be laid out
Returns:
a new Dimension instance (both the height and width are >= 0 && <= Integer.MAX_VALUE)
Throws:
IllegalStateException - if calling thread is not EventQueue's dispatch thread
AWTError - if checkContainerArgAndThread objects to container
See Also:
minimumLayoutSize, maximumLayoutSize

maximumLayoutSize

public Dimension maximumLayoutSize(Container target)
                            throws AWTError,
                                   IllegalStateException
Returns the maximum dimensions needed to lay out the Components contained in the specified target container. Invisible child Components are ignored in the calculation. The result includes the effects of the target container's insets.

Specified by:
maximumLayoutSize in interface LayoutManager2
Parameters:
target - the Container that needs to be laid out
Returns:
a new Dimension instance (both the height and width are >= 0 && <= Integer.MAX_VALUE)
Throws:
AWTError - if checkContainerArgAndThread objects to container
IllegalStateException - if calling thread is not EventQueue's dispatch thread
See Also:
minimumLayoutSize, preferredLayoutSize

addLayoutComponent

public void addLayoutComponent(String name,
                               Component comp)
                        throws IllegalStateException
Not used by this class (is implemented as an empty method).

Specified by:
addLayoutComponent in interface LayoutManager
Parameters:
name - the name of the Component
comp - the Component
Throws:
IllegalStateException - if calling thread is not EventQueue's dispatch thread

addLayoutComponent

public void addLayoutComponent(Component comp,
                               Object constraints)
                        throws IllegalStateException
Not used by this class (is implemented as an empty method).

Specified by:
addLayoutComponent in interface LayoutManager2
Parameters:
comp - the Component
constraints - constraints
Throws:
IllegalStateException - if calling thread is not EventQueue's dispatch thread

invalidateLayout

public void invalidateLayout(Container target)
                      throws AWTError,
                             IllegalStateException
Indicates that a child has changed its layout related information, and thus any cached calculations should be flushed.

Specified by:
invalidateLayout in interface LayoutManager2
Parameters:
target - the affected container
Throws:
AWTError - if checkContainerArgAndThread objects to container
IllegalStateException - if calling thread is not EventQueue's dispatch thread

layoutContainer

public void layoutContainer(Container target)
                     throws AWTError,
                            IllegalStateException
Called by the AWT when the specified Container needs to be laid out.

Specified by:
layoutContainer in interface LayoutManager
Parameters:
target - the container to lay out
Throws:
AWTError - if checkContainerArgAndThread objects to container
IllegalStateException - if calling thread is not EventQueue's dispatch thread

removeLayoutComponent

public void removeLayoutComponent(Component comp)
                           throws IllegalStateException
Not used by this class (is implemented as an empty method).

Specified by:
removeLayoutComponent in interface LayoutManager
Parameters:
comp - the Component
Throws:
IllegalStateException - if calling thread is not EventQueue's dispatch thread

checkContainerArgAndThread

protected void checkContainerArgAndThread(Container target)
                                   throws AWTError,
                                          IllegalStateException
Confirms that target is the same Container that this LineLayout instance was first used with. (The first time this method is called with a non-null value for target, that Container is stored and used to compare against subsequent calls.)

Throws:
AWTError - if target is null or isn't the first Container used by this instance
IllegalStateException - if calling thread is not EventQueue's dispatch thread

revalidateLayout

protected void revalidateLayout(Container target)

increaseSizeForInsets

protected void increaseSizeForInsets(Dimension size,
                                     Container target)
Increases the supplied Dimension arg to account for the target Container's Insets.


decreaseSizeForInsets

protected Dimension decreaseSizeForInsets(Dimension size,
                                          Insets insets)
Returns a new Dimension instance that comes from decreasing the supplied Dimension arg to account for the target Container's Insets.


calcXOffset

protected int calcXOffset(Component c,
                          Dimension allocSize,
                          Insets insets)
Calculates the x-offset of a Component, taking into effect both the x-axis alignment of the Component and the Insets of the parent Container.


calcYOffset

protected int calcYOffset(Component c,
                          Dimension allocSize,
                          Insets insets)
Calculates the y-offset of a Component, taking into effect both the y-axis alignment of the Component and the Insets of the parent Container.