/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.io.ObjectInputStream;
import java.io.IOException;
A flow layout arranges components in a directional flow, much like lines of text in a paragraph. The flow direction is determined by the container's componentOrientation
property and may be one of two values:
ComponentOrientation.LEFT_TO_RIGHT
ComponentOrientation.RIGHT_TO_LEFT
Flow layouts are typically used to arrange buttons in a panel. It arranges buttons horizontally until no more buttons fit on the same line. The line alignment is determined by the align
property. The possible values are:
For example, the following picture shows an applet using the flow
layout manager (its default layout manager) to position three buttons:
Here is the code for this applet:
import java.awt.*;
import java.applet.Applet;
public class myButtons extends Applet {
Button button1, button2, button3;
public void init() {
button1 = new Button("Ok");
button2 = new Button("Open");
button3 = new Button("Close");
add(button1);
add(button2);
add(button3);
}
}
A flow layout lets each component assume its natural (preferred) size.
Author: Arthur van Hoff, Sami Shaio See Also: Since: 1.0
/**
* A flow layout arranges components in a directional flow, much
* like lines of text in a paragraph. The flow direction is
* determined by the container's {@code componentOrientation}
* property and may be one of two values:
* <ul>
* <li>{@code ComponentOrientation.LEFT_TO_RIGHT}
* <li>{@code ComponentOrientation.RIGHT_TO_LEFT}
* </ul>
* Flow layouts are typically used
* to arrange buttons in a panel. It arranges buttons
* horizontally until no more buttons fit on the same line.
* The line alignment is determined by the {@code align}
* property. The possible values are:
* <ul>
* <li>{@link #LEFT LEFT}
* <li>{@link #RIGHT RIGHT}
* <li>{@link #CENTER CENTER}
* <li>{@link #LEADING LEADING}
* <li>{@link #TRAILING TRAILING}
* </ul>
* <p>
* For example, the following picture shows an applet using the flow
* layout manager (its default layout manager) to position three buttons:
* <p>
* <img src="doc-files/FlowLayout-1.gif"
* ALT="Graphic of Layout for Three Buttons"
* style="float:center; margin: 7px 10px;">
* <p>
* Here is the code for this applet:
*
* <hr><blockquote><pre>
* import java.awt.*;
* import java.applet.Applet;
*
* public class myButtons extends Applet {
* Button button1, button2, button3;
* public void init() {
* button1 = new Button("Ok");
* button2 = new Button("Open");
* button3 = new Button("Close");
* add(button1);
* add(button2);
* add(button3);
* }
* }
* </pre></blockquote><hr>
* <p>
* A flow layout lets each component assume its natural (preferred) size.
*
* @author Arthur van Hoff
* @author Sami Shaio
* @since 1.0
* @see ComponentOrientation
*/
public class FlowLayout implements LayoutManager, java.io.Serializable {
This value indicates that each row of components
should be left-justified.
/**
* This value indicates that each row of components
* should be left-justified.
*/
public static final int LEFT = 0;
This value indicates that each row of components
should be centered.
/**
* This value indicates that each row of components
* should be centered.
*/
public static final int CENTER = 1;
This value indicates that each row of components
should be right-justified.
/**
* This value indicates that each row of components
* should be right-justified.
*/
public static final int RIGHT = 2;
This value indicates that each row of components
should be justified to the leading edge of the container's
orientation, for example, to the left in left-to-right orientations.
See Also: - getComponentOrientation.getComponentOrientation
- ComponentOrientation
Since: 1.2
/**
* This value indicates that each row of components
* should be justified to the leading edge of the container's
* orientation, for example, to the left in left-to-right orientations.
*
* @see java.awt.Component#getComponentOrientation
* @see java.awt.ComponentOrientation
* @since 1.2
*/
public static final int LEADING = 3;
This value indicates that each row of components
should be justified to the trailing edge of the container's
orientation, for example, to the right in left-to-right orientations.
See Also: - getComponentOrientation.getComponentOrientation
- ComponentOrientation
Since: 1.2
/**
* This value indicates that each row of components
* should be justified to the trailing edge of the container's
* orientation, for example, to the right in left-to-right orientations.
*
* @see java.awt.Component#getComponentOrientation
* @see java.awt.ComponentOrientation
* @since 1.2
*/
public static final int TRAILING = 4;
align
is the property that determines how each row distributes empty space. It can be one of the following values:
LEFT
RIGHT
CENTER
See Also: @serial
/**
* {@code align} is the property that determines
* how each row distributes empty space.
* It can be one of the following values:
* <ul>
* <li>{@code LEFT}
* <li>{@code RIGHT}
* <li>{@code CENTER}
* </ul>
*
* @serial
* @see #getAlignment
* @see #setAlignment
*/
int align; // This is for 1.1 serialization compatibility
newAlign
is the property that determines how each row distributes empty space for the Java 2 platform, v1.2 and greater. It can be one of the following three values:
LEFT
RIGHT
CENTER
LEADING
TRAILING
See Also: @serial Since: 1.2
/**
* {@code newAlign} is the property that determines
* how each row distributes empty space for the Java 2 platform,
* v1.2 and greater.
* It can be one of the following three values:
* <ul>
* <li>{@code LEFT}
* <li>{@code RIGHT}
* <li>{@code CENTER}
* <li>{@code LEADING}
* <li>{@code TRAILING}
* </ul>
*
* @serial
* @since 1.2
* @see #getAlignment
* @see #setAlignment
*/
int newAlign; // This is the one we actually use
The flow layout manager allows a separation of components with gaps. The horizontal gap will specify the space between components and between the components and the borders of the Container
. See Also: @serial
/**
* The flow layout manager allows a separation of
* components with gaps. The horizontal gap will
* specify the space between components and between
* the components and the borders of the
* {@code Container}.
*
* @serial
* @see #getHgap()
* @see #setHgap(int)
*/
int hgap;
The flow layout manager allows a separation of components with gaps. The vertical gap will specify the space between rows and between the the rows and the borders of the Container
. See Also: @serial
/**
* The flow layout manager allows a separation of
* components with gaps. The vertical gap will
* specify the space between rows and between the
* the rows and the borders of the {@code Container}.
*
* @serial
* @see #getHgap()
* @see #setHgap(int)
*/
int vgap;
If true, components will be aligned on their baseline.
/**
* If true, components will be aligned on their baseline.
*/
private boolean alignOnBaseline;
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = -7262534875583282631L;
Constructs a new FlowLayout
with a centered alignment and a default 5-unit horizontal and vertical gap. /**
* Constructs a new {@code FlowLayout} with a centered alignment and a
* default 5-unit horizontal and vertical gap.
*/
public FlowLayout() {
this(CENTER, 5, 5);
}
Constructs a new FlowLayout
with the specified alignment and a default 5-unit horizontal and vertical gap. The value of the alignment argument must be one of FlowLayout.LEFT
, FlowLayout.RIGHT
, FlowLayout.CENTER
, FlowLayout.LEADING
, or FlowLayout.TRAILING
. Params: - align – the alignment value
/**
* Constructs a new {@code FlowLayout} with the specified
* alignment and a default 5-unit horizontal and vertical gap.
* The value of the alignment argument must be one of
* {@code FlowLayout.LEFT}, {@code FlowLayout.RIGHT},
* {@code FlowLayout.CENTER}, {@code FlowLayout.LEADING},
* or {@code FlowLayout.TRAILING}.
* @param align the alignment value
*/
public FlowLayout(int align) {
this(align, 5, 5);
}
Creates a new flow layout manager with the indicated alignment
and the indicated horizontal and vertical gaps.
The value of the alignment argument must be one of FlowLayout.LEFT
, FlowLayout.RIGHT
, FlowLayout.CENTER
, FlowLayout.LEADING
, or FlowLayout.TRAILING
.
Params: - align – the alignment value
- hgap – the horizontal gap between components and between the components and the borders of the
Container
- vgap – the vertical gap between components and between the components and the borders of the
Container
/**
* Creates a new flow layout manager with the indicated alignment
* and the indicated horizontal and vertical gaps.
* <p>
* The value of the alignment argument must be one of
* {@code FlowLayout.LEFT}, {@code FlowLayout.RIGHT},
* {@code FlowLayout.CENTER}, {@code FlowLayout.LEADING},
* or {@code FlowLayout.TRAILING}.
* @param align the alignment value
* @param hgap the horizontal gap between components
* and between the components and the
* borders of the {@code Container}
* @param vgap the vertical gap between components
* and between the components and the
* borders of the {@code Container}
*/
public FlowLayout(int align, int hgap, int vgap) {
this.hgap = hgap;
this.vgap = vgap;
setAlignment(align);
}
Gets the alignment for this layout. Possible values are FlowLayout.LEFT
, FlowLayout.RIGHT
, FlowLayout.CENTER
, FlowLayout.LEADING
, or FlowLayout.TRAILING
. See Also: Returns: the alignment value for this layout Since: 1.1
/**
* Gets the alignment for this layout.
* Possible values are {@code FlowLayout.LEFT},
* {@code FlowLayout.RIGHT}, {@code FlowLayout.CENTER},
* {@code FlowLayout.LEADING},
* or {@code FlowLayout.TRAILING}.
* @return the alignment value for this layout
* @see java.awt.FlowLayout#setAlignment
* @since 1.1
*/
public int getAlignment() {
return newAlign;
}
Sets the alignment for this layout.
Possible values are
FlowLayout.LEFT
FlowLayout.RIGHT
FlowLayout.CENTER
FlowLayout.LEADING
FlowLayout.TRAILING
Params: - align – one of the alignment values shown above
See Also: Since: 1.1
/**
* Sets the alignment for this layout.
* Possible values are
* <ul>
* <li>{@code FlowLayout.LEFT}
* <li>{@code FlowLayout.RIGHT}
* <li>{@code FlowLayout.CENTER}
* <li>{@code FlowLayout.LEADING}
* <li>{@code FlowLayout.TRAILING}
* </ul>
* @param align one of the alignment values shown above
* @see #getAlignment()
* @since 1.1
*/
public void setAlignment(int align) {
this.newAlign = align;
// this.align is used only for serialization compatibility,
// so set it to a value compatible with the 1.1 version
// of the class
switch (align) {
case LEADING:
this.align = LEFT;
break;
case TRAILING:
this.align = RIGHT;
break;
default:
this.align = align;
break;
}
}
Gets the horizontal gap between components and between the components and the borders of the Container
See Also: Returns: the horizontal gap between components and between the components and the borders of the Container
Since: 1.1
/**
* Gets the horizontal gap between components
* and between the components and the borders
* of the {@code Container}
*
* @return the horizontal gap between components
* and between the components and the borders
* of the {@code Container}
* @see java.awt.FlowLayout#setHgap
* @since 1.1
*/
public int getHgap() {
return hgap;
}
Sets the horizontal gap between components and between the components and the borders of the Container
. Params: - hgap – the horizontal gap between components and between the components and the borders of the
Container
See Also: Since: 1.1
/**
* Sets the horizontal gap between components and
* between the components and the borders of the
* {@code Container}.
*
* @param hgap the horizontal gap between components
* and between the components and the borders
* of the {@code Container}
* @see java.awt.FlowLayout#getHgap
* @since 1.1
*/
public void setHgap(int hgap) {
this.hgap = hgap;
}
Gets the vertical gap between components and between the components and the borders of the Container
. See Also: Returns: the vertical gap between components and between the components and the borders of the Container
Since: 1.1
/**
* Gets the vertical gap between components and
* between the components and the borders of the
* {@code Container}.
*
* @return the vertical gap between components
* and between the components and the borders
* of the {@code Container}
* @see java.awt.FlowLayout#setVgap
* @since 1.1
*/
public int getVgap() {
return vgap;
}
Sets the vertical gap between components and between the components and the borders of the Container
. Params: - vgap – the vertical gap between components and between the components and the borders of the
Container
See Also: Since: 1.1
/**
* Sets the vertical gap between components and between
* the components and the borders of the {@code Container}.
*
* @param vgap the vertical gap between components
* and between the components and the borders
* of the {@code Container}
* @see java.awt.FlowLayout#getVgap
* @since 1.1
*/
public void setVgap(int vgap) {
this.vgap = vgap;
}
Sets whether or not components should be vertically aligned along their
baseline. Components that do not have a baseline will be centered.
The default is false.
Params: - alignOnBaseline – whether or not components should be
vertically aligned on their baseline
Since: 1.6
/**
* Sets whether or not components should be vertically aligned along their
* baseline. Components that do not have a baseline will be centered.
* The default is false.
*
* @param alignOnBaseline whether or not components should be
* vertically aligned on their baseline
* @since 1.6
*/
public void setAlignOnBaseline(boolean alignOnBaseline) {
this.alignOnBaseline = alignOnBaseline;
}
Returns true if components are to be vertically aligned along
their baseline. The default is false.
Returns: true if components are to be vertically aligned along
their baseline Since: 1.6
/**
* Returns true if components are to be vertically aligned along
* their baseline. The default is false.
*
* @return true if components are to be vertically aligned along
* their baseline
* @since 1.6
*/
public boolean getAlignOnBaseline() {
return alignOnBaseline;
}
Adds the specified component to the layout.
Not used by this class.
Params: - name – the name of the component
- comp – the component to be added
/**
* Adds the specified component to the layout.
* Not used by this class.
* @param name the name of the component
* @param comp the component to be added
*/
public void addLayoutComponent(String name, Component comp) {
}
Removes the specified component from the layout.
Not used by this class.
Params: - comp – the component to remove
See Also:
/**
* Removes the specified component from the layout.
* Not used by this class.
* @param comp the component to remove
* @see java.awt.Container#removeAll
*/
public void removeLayoutComponent(Component comp) {
}
Returns the preferred dimensions for this layout given the
visible components in the specified target container.
Params: - target – the container that needs to be laid out
See Also: Returns: the preferred dimensions to lay out the
subcomponents of the specified container
/**
* Returns the preferred dimensions for this layout given the
* <i>visible</i> components in the specified target container.
*
* @param target the container that needs to be laid out
* @return the preferred dimensions to lay out the
* subcomponents of the specified container
* @see Container
* @see #minimumLayoutSize
* @see java.awt.Container#getPreferredSize
*/
public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
boolean firstVisibleComponent = true;
boolean useBaseline = getAlignOnBaseline();
int maxAscent = 0;
int maxDescent = 0;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
dim.height = Math.max(dim.height, d.height);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
dim.width += hgap;
}
dim.width += d.width;
if (useBaseline) {
int baseline = m.getBaseline(d.width, d.height);
if (baseline >= 0) {
maxAscent = Math.max(maxAscent, baseline);
maxDescent = Math.max(maxDescent, d.height - baseline);
}
}
}
}
if (useBaseline) {
dim.height = Math.max(maxAscent + maxDescent, dim.height);
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
Returns the minimum dimensions needed to layout the visible
components contained in the specified target container.
Params: - target – the container that needs to be laid out
See Also: Returns: the minimum dimensions to lay out the
subcomponents of the specified container
/**
* Returns the minimum dimensions needed to layout the <i>visible</i>
* components contained in the specified target container.
* @param target the container that needs to be laid out
* @return the minimum dimensions to lay out the
* subcomponents of the specified container
* @see #preferredLayoutSize
* @see java.awt.Container
* @see java.awt.Container#doLayout
*/
public Dimension minimumLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
boolean useBaseline = getAlignOnBaseline();
Dimension dim = new Dimension(0, 0);
int nmembers = target.getComponentCount();
int maxAscent = 0;
int maxDescent = 0;
boolean firstVisibleComponent = true;
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.visible) {
Dimension d = m.getMinimumSize();
dim.height = Math.max(dim.height, d.height);
if (firstVisibleComponent) {
firstVisibleComponent = false;
} else {
dim.width += hgap;
}
dim.width += d.width;
if (useBaseline) {
int baseline = m.getBaseline(d.width, d.height);
if (baseline >= 0) {
maxAscent = Math.max(maxAscent, baseline);
maxDescent = Math.max(maxDescent,
dim.height - baseline);
}
}
}
}
if (useBaseline) {
dim.height = Math.max(maxAscent + maxDescent, dim.height);
}
Insets insets = target.getInsets();
dim.width += insets.left + insets.right + hgap*2;
dim.height += insets.top + insets.bottom + vgap*2;
return dim;
}
}
Centers the elements in the specified row, if there is any slack.
Params: - target – the component which needs to be moved
- x – the x coordinate
- y – the y coordinate
- width – the width dimensions
- height – the height dimensions
- rowStart – the beginning of the row
- rowEnd – the ending of the row
- useBaseline – Whether or not to align on baseline.
- ascent – Ascent for the components. This is only valid if
useBaseline is true.
- descent – Ascent for the components. This is only valid if
useBaseline is true.
Returns: actual row height
/**
* Centers the elements in the specified row, if there is any slack.
* @param target the component which needs to be moved
* @param x the x coordinate
* @param y the y coordinate
* @param width the width dimensions
* @param height the height dimensions
* @param rowStart the beginning of the row
* @param rowEnd the ending of the row
* @param useBaseline Whether or not to align on baseline.
* @param ascent Ascent for the components. This is only valid if
* useBaseline is true.
* @param descent Ascent for the components. This is only valid if
* useBaseline is true.
* @return actual row height
*/
private int moveComponents(Container target, int x, int y, int width, int height,
int rowStart, int rowEnd, boolean ltr,
boolean useBaseline, int[] ascent,
int[] descent) {
switch (newAlign) {
case LEFT:
x += ltr ? 0 : width;
break;
case CENTER:
x += width / 2;
break;
case RIGHT:
x += ltr ? width : 0;
break;
case LEADING:
break;
case TRAILING:
x += width;
break;
}
int maxAscent = 0;
int nonbaselineHeight = 0;
int baselineOffset = 0;
if (useBaseline) {
int maxDescent = 0;
for (int i = rowStart ; i < rowEnd ; i++) {
Component m = target.getComponent(i);
if (m.visible) {
if (ascent[i] >= 0) {
maxAscent = Math.max(maxAscent, ascent[i]);
maxDescent = Math.max(maxDescent, descent[i]);
}
else {
nonbaselineHeight = Math.max(m.getHeight(),
nonbaselineHeight);
}
}
}
height = Math.max(maxAscent + maxDescent, nonbaselineHeight);
baselineOffset = (height - maxAscent - maxDescent) / 2;
}
for (int i = rowStart ; i < rowEnd ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
int cy;
if (useBaseline && ascent[i] >= 0) {
cy = y + baselineOffset + maxAscent - ascent[i];
}
else {
cy = y + (height - m.height) / 2;
}
if (ltr) {
m.setLocation(x, cy);
} else {
m.setLocation(target.width - x - m.width, cy);
}
x += m.width + hgap;
}
}
return height;
}
Lays out the container. This method lets each
visible component take its preferred size by reshaping the components in the target container in order to satisfy the alignment of this FlowLayout
object. Params: - target – the specified component being laid out
See Also:
/**
* Lays out the container. This method lets each
* <i>visible</i> component take
* its preferred size by reshaping the components in the
* target container in order to satisfy the alignment of
* this {@code FlowLayout} object.
*
* @param target the specified component being laid out
* @see Container
* @see java.awt.Container#doLayout
*/
public void layoutContainer(Container target) {
synchronized (target.getTreeLock()) {
Insets insets = target.getInsets();
int maxwidth = target.width - (insets.left + insets.right + hgap*2);
int nmembers = target.getComponentCount();
int x = 0, y = insets.top + vgap;
int rowh = 0, start = 0;
boolean ltr = target.getComponentOrientation().isLeftToRight();
boolean useBaseline = getAlignOnBaseline();
int[] ascent = null;
int[] descent = null;
if (useBaseline) {
ascent = new int[nmembers];
descent = new int[nmembers];
}
for (int i = 0 ; i < nmembers ; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
m.setSize(d.width, d.height);
if (useBaseline) {
int baseline = m.getBaseline(d.width, d.height);
if (baseline >= 0) {
ascent[i] = baseline;
descent[i] = d.height - baseline;
}
else {
ascent[i] = -1;
}
}
if ((x == 0) || ((x + d.width) <= maxwidth)) {
if (x > 0) {
x += hgap;
}
x += d.width;
rowh = Math.max(rowh, d.height);
} else {
rowh = moveComponents(target, insets.left + hgap, y,
maxwidth - x, rowh, start, i, ltr,
useBaseline, ascent, descent);
x = d.width;
y += vgap + rowh;
rowh = d.height;
start = i;
}
}
}
moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh,
start, nmembers, ltr, useBaseline, ascent, descent);
}
}
//
// the internal serial version which says which version was written
// - 0 (default) for versions before the Java 2 platform, v1.2
// - 1 for version >= Java 2 platform v1.2, which includes "newAlign" field
//
private static final int currentSerialVersion = 1;
This represent the currentSerialVersion
which is bein used. It will be one of two values: 0
versions before Java 2 platform v1.2, 1
versions after Java 2 platform v1.2. @serial Since: 1.2
/**
* This represent the {@code currentSerialVersion}
* which is bein used. It will be one of two values:
* {@code 0} versions before Java 2 platform v1.2,
* {@code 1} versions after Java 2 platform v1.2.
*
* @serial
* @since 1.2
*/
private int serialVersionOnStream = currentSerialVersion;
Reads this object out of a serialization stream, handling
objects written by older versions of the class that didn't contain all
of the fields we use now..
/**
* Reads this object out of a serialization stream, handling
* objects written by older versions of the class that didn't contain all
* of the fields we use now..
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
if (serialVersionOnStream < 1) {
// "newAlign" field wasn't present, so use the old "align" field.
setAlignment(this.align);
}
serialVersionOnStream = currentSerialVersion;
}
Returns a string representation of this FlowLayout
object and its values. Returns: a string representation of this layout
/**
* Returns a string representation of this {@code FlowLayout}
* object and its values.
* @return a string representation of this layout
*/
public String toString() {
String str = "";
switch (align) {
case LEFT: str = ",align=left"; break;
case CENTER: str = ",align=center"; break;
case RIGHT: str = ",align=right"; break;
case LEADING: str = ",align=leading"; break;
case TRAILING: str = ",align=trailing"; break;
}
return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";
}
}