| /* BoxLayout.java -- A layout for swing components. |
| Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath 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 for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| package javax.swing; |
| |
| import java.awt.AWTError; |
| import java.awt.Component; |
| import java.awt.ComponentOrientation; |
| import java.awt.Container; |
| import java.awt.Dimension; |
| import java.awt.Insets; |
| import java.awt.LayoutManager2; |
| import java.io.Serializable; |
| |
| /** |
| * A layout that stacks the children of a container in a Box, either |
| * horizontally or vertically. |
| * |
| * @author Ronald Veldema (rveldema@cs.vu.nl) |
| * @author Roman Kennke (roman@kennke.org) |
| */ |
| public class BoxLayout implements LayoutManager2, Serializable |
| { |
| |
| /** |
| * Specifies that components are laid out left to right. |
| */ |
| public static final int X_AXIS = 0; |
| |
| /** |
| * Specifies that components are laid out top to bottom. |
| */ |
| public static final int Y_AXIS = 1; |
| |
| /** |
| * Specifies that components are laid out in the direction of a line of text. |
| */ |
| public static final int LINE_AXIS = 2; |
| |
| /** |
| * Sepcifies that components are laid out in the direction of the line flow. |
| */ |
| public static final int PAGE_AXIS = 3; |
| |
| /* |
| * Needed for serialization. |
| */ |
| private static final long serialVersionUID = -2474455742719112368L; |
| |
| /* |
| * The container given to the constructor. |
| */ |
| private Container container; |
| |
| /** |
| * Current type of component layouting. Defaults to X_AXIS. |
| */ |
| private int way = X_AXIS; |
| |
| /** |
| * The size requirements of the containers children for the X direction. |
| */ |
| private SizeRequirements[] xChildren; |
| |
| /** |
| * The size requirements of the containers children for the Y direction. |
| */ |
| private SizeRequirements[] yChildren; |
| |
| /** |
| * The size requirements of the container to be laid out for the X direction. |
| */ |
| private SizeRequirements xTotal; |
| |
| /** |
| * The size requirements of the container to be laid out for the Y direction. |
| */ |
| private SizeRequirements yTotal; |
| |
| /** |
| * The offsets of the child components in the X direction. |
| */ |
| private int[] offsetsX; |
| |
| /** |
| * The offsets of the child components in the Y direction. |
| */ |
| private int[] offsetsY; |
| |
| /** |
| * The spans of the child components in the X direction. |
| */ |
| private int[] spansX; |
| |
| /** |
| * The spans of the child components in the Y direction. |
| */ |
| private int[] spansY; |
| |
| /** |
| * Constructs a <code>BoxLayout</code> object. |
| * |
| * @param container The container that needs to be laid out. |
| * @param way The orientation of the components. |
| * |
| * @exception AWTError If way has an invalid value. |
| */ |
| public BoxLayout(Container container, int way) |
| { |
| if (way != X_AXIS && way != Y_AXIS && way != LINE_AXIS && way != PAGE_AXIS) |
| throw new AWTError("Invalid axis"); |
| |
| int width = 0; |
| int height = 0; |
| this.container = container; |
| this.way = way; |
| } |
| |
| /** |
| * Adds a component to the layout. Not used in BoxLayout. |
| * |
| * @param name The name of the component to add. |
| * @param component the component to add to the layout. |
| */ |
| public void addLayoutComponent(String name, Component component) |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * Removes a component from the layout. Not used in BoxLayout. |
| * |
| * @param component The component to remove from the layout. |
| */ |
| public void removeLayoutComponent(Component component) |
| { |
| // Nothing to do here. |
| } |
| |
| private boolean isHorizontalIn(Container parent) |
| { |
| ComponentOrientation orientation = parent.getComponentOrientation(); |
| return this.way == X_AXIS |
| || (this.way == LINE_AXIS |
| && orientation.isHorizontal()) |
| || (this.way == PAGE_AXIS |
| && (!orientation.isHorizontal())); |
| } |
| |
| |
| |
| /** |
| * Returns the preferred size of the layout. |
| * |
| * @param parent The container that needs to be laid out. |
| * |
| * @return The dimension of the layout. |
| */ |
| public Dimension preferredLayoutSize(Container parent) |
| { |
| synchronized (container.getTreeLock()) |
| { |
| if (container != parent) |
| throw new AWTError("BoxLayout can't be shared"); |
| |
| checkTotalRequirements(); |
| Insets i = container.getInsets(); |
| return new Dimension(xTotal.preferred + i.left + i.right, |
| yTotal.preferred + i.top + i.bottom); |
| } |
| } |
| |
| /** |
| * Returns the minimum size of the layout. |
| * |
| * @param parent The container that needs to be laid out. |
| * |
| * @return The dimension of the layout. |
| */ |
| public Dimension minimumLayoutSize(Container parent) |
| { |
| synchronized (container.getTreeLock()) |
| { |
| if (container != parent) |
| throw new AWTError("BoxLayout can't be shared"); |
| |
| checkTotalRequirements(); |
| Insets i = container.getInsets(); |
| return new Dimension(xTotal.minimum + i.left + i.right, |
| yTotal.minimum + i.top + i.bottom); |
| } |
| } |
| |
| /** |
| * Lays out the specified container using this layout. |
| * |
| * @param parent The container that needs to be laid out. |
| */ |
| public void layoutContainer(Container parent) |
| { |
| synchronized (container.getTreeLock()) |
| { |
| if (container != parent) |
| throw new AWTError("BoxLayout can't be shared"); |
| |
| checkLayout(); |
| Component[] children = container.getComponents(); |
| Insets in = container.getInsets(); |
| for (int i = 0; i < children.length; i++) |
| children[i].setBounds(offsetsX[i] + in.left, offsetsY[i] + in.top, |
| spansX[i], spansY[i]); |
| } |
| } |
| |
| /** |
| * Adds a component to the layout. Not used in BoxLayout |
| * |
| * @param child The component to add to the layout. |
| * @param constraints The constraints for the component in the layout. |
| */ |
| public void addLayoutComponent(Component child, Object constraints) |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * Returns the alignment along the X axis for the container. |
| * |
| * @param parent The container that needs to be laid out. |
| * |
| * @return The alignment. |
| */ |
| public float getLayoutAlignmentX(Container parent) |
| { |
| synchronized (container.getTreeLock()) |
| { |
| if (container != parent) |
| throw new AWTError("BoxLayout can't be shared"); |
| |
| checkTotalRequirements(); |
| return xTotal.alignment; |
| } |
| } |
| |
| /** |
| * Returns the alignment along the Y axis for the container. |
| * |
| * @param parent The container that needs to be laid out. |
| * |
| * @return The alignment. |
| */ |
| public float getLayoutAlignmentY(Container parent) |
| { |
| synchronized (container.getTreeLock()) |
| { |
| if (container != parent) |
| throw new AWTError("BoxLayout can't be shared"); |
| |
| checkTotalRequirements(); |
| return yTotal.alignment; |
| } |
| } |
| |
| /** |
| * Invalidates the layout. |
| * |
| * @param parent The container that needs to be laid out. |
| */ |
| public void invalidateLayout(Container parent) |
| { |
| if (container != parent) |
| throw new AWTError("BoxLayout can't be shared"); |
| |
| synchronized (container.getTreeLock()) |
| { |
| xChildren = null; |
| yChildren = null; |
| xTotal = null; |
| yTotal = null; |
| offsetsX = null; |
| offsetsY = null; |
| spansX = null; |
| spansY = null; |
| } |
| } |
| |
| /** |
| * Returns the maximum size of the layout gived the components |
| * in the given container. |
| * |
| * @param parent The container that needs to be laid out. |
| * |
| * @return The dimension of the layout. |
| */ |
| public Dimension maximumLayoutSize(Container parent) |
| { |
| synchronized (container.getTreeLock()) |
| { |
| if (container != parent) |
| throw new AWTError("BoxLayout can't be shared"); |
| |
| checkTotalRequirements(); |
| Insets i = container.getInsets(); |
| int xDim = xTotal.maximum + i.left + i.right; |
| int yDim = yTotal.maximum + i.top + i.bottom; |
| |
| // Check for overflow |
| if (xDim < xTotal.maximum) |
| xDim = Integer.MAX_VALUE; |
| if (yDim < yTotal.maximum) |
| yDim = Integer.MAX_VALUE; |
| return new Dimension(xDim, yDim); |
| } |
| } |
| |
| /** |
| * Makes sure that the xTotal and yTotal fields are set up correctly. A call |
| * to {@link #invalidateLayout} sets these fields to null and they have to be |
| * recomputed. |
| */ |
| private void checkTotalRequirements() |
| { |
| if (xTotal == null || yTotal == null) |
| { |
| checkRequirements(); |
| if (isHorizontalIn(container)) |
| { |
| xTotal = SizeRequirements.getTiledSizeRequirements(xChildren); |
| yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren); |
| } |
| else |
| { |
| xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren); |
| yTotal = SizeRequirements.getTiledSizeRequirements(yChildren); |
| } |
| } |
| } |
| |
| /** |
| * Makes sure that the xChildren and yChildren fields are correctly set up. |
| * A call to {@link #invalidateLayout(Container)} sets these fields to null, |
| * so they have to be set up again. |
| */ |
| private void checkRequirements() |
| { |
| if (xChildren == null || yChildren == null) |
| { |
| Component[] children = container.getComponents(); |
| xChildren = new SizeRequirements[children.length]; |
| yChildren = new SizeRequirements[children.length]; |
| for (int i = 0; i < children.length; i++) |
| { |
| if (! children[i].isVisible()) |
| { |
| xChildren[i] = new SizeRequirements(); |
| yChildren[i] = new SizeRequirements(); |
| } |
| else |
| { |
| xChildren[i] = |
| new SizeRequirements(children[i].getMinimumSize().width, |
| children[i].getPreferredSize().width, |
| children[i].getMaximumSize().width, |
| children[i].getAlignmentX()); |
| yChildren[i] = |
| new SizeRequirements(children[i].getMinimumSize().height, |
| children[i].getPreferredSize().height, |
| children[i].getMaximumSize().height, |
| children[i].getAlignmentY()); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Makes sure that the offsetsX, offsetsY, spansX and spansY fields are set |
| * up correctly. A call to {@link #invalidateLayout} sets these fields |
| * to null and they have to be recomputed. |
| */ |
| private void checkLayout() |
| { |
| if (offsetsX == null || offsetsY == null || spansX == null |
| || spansY == null) |
| { |
| checkRequirements(); |
| checkTotalRequirements(); |
| int len = container.getComponents().length; |
| offsetsX = new int[len]; |
| offsetsY = new int[len]; |
| spansX = new int[len]; |
| spansY = new int[len]; |
| |
| Insets in = container.getInsets(); |
| int width = container.getWidth() - in.left - in.right; |
| int height = container.getHeight() - in.top - in.bottom; |
| |
| if (isHorizontalIn(container)) |
| { |
| SizeRequirements.calculateTiledPositions(width, |
| xTotal, xChildren, |
| offsetsX, spansX); |
| SizeRequirements.calculateAlignedPositions(height, |
| yTotal, yChildren, |
| offsetsY, spansY); |
| } |
| else |
| { |
| SizeRequirements.calculateAlignedPositions(width, |
| xTotal, xChildren, |
| offsetsX, spansX); |
| SizeRequirements.calculateTiledPositions(height, |
| yTotal, yChildren, |
| offsetsY, spansY); |
| } |
| } |
| } |
| } |