/* class FlowLayout * * Copyright (C) 2001 R M Pitman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package charva.awt; import java.util.Enumeration; import java.util.Vector; /** * A concrete implementation of LayoutManager that lays out its * components left-to-right. */ public class FlowLayout implements LayoutManager { /** Default constructor. Sets alignment to CENTER, hgap to 1, * and vgap to 0. */ public FlowLayout() { this(CENTER, 1, 0); } /** * Use this constructor when you want to set the alignment and the * horizontal and vertical gaps. */ public FlowLayout(int align_, int hgap_, int vgap_) { _align = align_; _hgap = hgap_; _vgap = vgap_; } /** Sets the alignment for this layout. Allowable values are * FlowLayout.LEFT, FlowLayout.CENTER and FlowLayout.RIGHT. */ public void setAlignment(int align_) { _align = align_; } /** Gets the alignment for this layout. */ public int getAlignment() { return _align; } /** * Calculate the minimum-size rectangle that can enclose all the * components in the given container. */ public Dimension minimumSize(Container container_) { int width = 0; int height = 0; Component[] components = container_.getComponents(); for (int i=0; i<components.length; i++) { Dimension d = components[i].minimumSize(); /* Make allowance for the gap between this component and the * previous component. */ if (i!= 0) width += _hgap; width += d.width; if (d.height > height) height = d.height; } /* Take into account the border frame (if any). */ Insets insets = container_.getInsets(); height += insets.top + insets.bottom; width += insets.left + insets.right; return new Dimension(width, height); } /** * Lay out the components according to the specified alignment, hgap * and vgap. * This is called when the size of the container has already been * calculated. * It lays out the components in a row, one at a time, until it * determines that there is not enough space left in the row. * Then it moves to the next row. If there is not enough vertical * space in the container to lay out all of the components, it * removes the remaining components from the container; they don't * appear at all. */ public void doLayout(Container container_) { Insets insets = container_.getInsets(); int availableWidth = container_.getSize().width - insets.left - insets.right; int widthLeft = availableWidth; int heightLeft = container_.getSize().height - insets.top - insets.bottom; int voffset = insets.top; Component[] components = container_.getComponents(); Vector<Component> localvector = new Vector<Component>(); for (int i=0; i<components.length; i++) { Component c = components[i]; /* Get the contained container to lay itself out at its * preferred size, if it is not already laid out. */ if (c instanceof Container) { Container cont = (Container) c; if (cont.isValid() == false) { cont.setSize(cont.minimumSize()); cont.doLayout(); } } /* Determine the width required to lay out the current * component (including the gap between this component and * the previous component). */ int requiredWidth = c.getSize().width; if (i != 0) requiredWidth += _hgap; if (requiredWidth > widthLeft) { int rowHeight = 0; if (localvector.size() != 0) { rowHeight = layoutRow(container_, localvector, widthLeft, heightLeft, voffset); localvector.removeAllElements(); } voffset += rowHeight + _vgap; widthLeft = availableWidth; heightLeft -= rowHeight + _vgap; } widthLeft -= requiredWidth; // Build up a temporary list of components for this row. localvector.add(c); } layoutRow(container_, localvector, widthLeft, heightLeft, voffset); } /** private function to layout a single row of components. * @return The height of the laid-out row. */ private int layoutRow(Container container_, Vector<Component> components_, int widthleft_, int heightleft_, int voffset_) { int hoffset = 0; int rowHeight = 0; Insets insets = container_.getInsets(); switch (_align) { case LEFT: hoffset = insets.left; break; case CENTER: hoffset = insets.left + widthleft_/2; break; case RIGHT: hoffset = insets.left + widthleft_; break; } Enumeration<Component> e = components_.elements(); while (e.hasMoreElements()) { Component c = (Component) e.nextElement(); if (c.getSize().height > rowHeight) rowHeight = c.getSize().height; if (rowHeight > heightleft_) { container_.remove(c); // we have run out of space continue; } c.setLocation(hoffset, voffset_); hoffset += c.getSize().width + _hgap; } return rowHeight; } //==================================================================== // INSTANCE VARIABLES /** Alignment of components (LEFT, RIGHT or CENTER) */ private int _align = CENTER; /** Horizontal gap between components */ private int _hgap = 1; /** Vertical gap between components */ private int _vgap = 0; public static final int LEFT = 1; public static final int CENTER = 2; public static final int RIGHT = 3; }