import java.awt.*;

// This appears in Core Web Programming from
// Prentice Hall Publishers, and may be freely used
// or adapted. 1997 Marty Hall, hall@apl.jhu.edu.

/**
 * A layout manager that distributes all components
 * evenly across the width of the Container, with an
 * optional spacing in between each.
 * <P>
 * Its effect is very similar to GridLayout with 1 row
 * and 0 columns.
 * <P>
 * No warranty of any kind is provided.
 * Permission is granted to use and/or modify for
 * any purpose.
 * <P>
 * 1997 Marty Hall:
 * <UL>
 *    <LI><A href="http://www.apl.jhu.edu/~hall/java/">
 *        Java Programming Resources.</A>
 *    <LI><A href="http://www.apl.jhu.edu/~hall/WWW/">
 *        WWW Developer's Resources.</A>
 *    <LI><A href="mailto:hall@apl.jhu.edu">
 *        Email.</A>
 *    <LI><A href="http://www.apl.jhu.edu/~hall/">
 *        Home Page.</A> 
 * </UL>
 *
 * @author Marty Hall (hall@apl.jhu.edu)
 * @version 1.0 (1997)
 */

public class RowLayout implements LayoutManager {
  private int hGap = 0, vGap = 0;

  //----------------------------------------------------
  /** Build a RowLayout with 0 pixel hGap and vGap */
  public RowLayout() {
  }

  /** Build a RowLayout with the specified
   *  horizontal and vertical gaps.
   *
   * @param hGap The horizontal space at the left and
   *             right of components.
   * @param vGap The vertical space above and below
   *             components.
   */
  public RowLayout(int hGap, int vGap) {
    this.hGap = hGap;
    this.vGap = vGap;
  }

  //----------------------------------------------------
  /** An empty method. */
  public void addLayoutComponent(String s, Component c) {
  }

  /** An empty method */
  public void removeLayoutComponent(Component c) {
  }

  //----------------------------------------------------
  /** This gives the preferred width/height of the window
   *  using this layout manager. The width is
   * calculated by finding the widest visible Component
   * and multiplying that width by the number of visible
   * Components, plus extra space between Components
   * (i.e. hGap between each, plus at the far left
   * and right of the row), plus the left and right
   * insets of the Container. The height is simply the
   * height of the tallest Component, plus twice the
   * vGap.
   *
   * @param cont The window using RowLayout.
   * @return A Dimension object giving the width
   *         and height.
   * @see #setVgap
   * @see #setHgap
   */
  public Dimension preferredLayoutSize(Container cont) {
    int count=0, totalWidth, totalHeight, maxWidth=0,
        maxHeight=0;
    Dimension componentSize;
    Component[] components = cont.getComponents();
    Component c;
    for(int i=0; i<components.length; i++) {
      c = components[i];
      if (c.isVisible()) {
        componentSize = c.getPreferredSize();
        maxWidth = Math.max(componentSize.width,
                            maxWidth);
        maxHeight = Math.max(componentSize.height,
                             maxHeight);
        count++;
      }
    }
    Insets margins = cont.getInsets();
    totalWidth = count*maxWidth + (count+1)*hGap +
                 margins.left + margins.right;
    totalHeight = maxHeight + 2*vGap +
                  margins.top + margins.bottom;
    return(new Dimension(totalWidth, totalHeight));
  }

  //----------------------------------------------------
  /** This is identical to preferredLayoutSize
   * @see #preferredLayoutSize
   */
  public Dimension minimumLayoutSize(Container cont) {
    return(preferredLayoutSize(cont));
  }

  //----------------------------------------------------
  /** This resizes all visible components to have
   *  the same width (1/Nth of the available space
   * after accounting for insets and hGap) and height
   * (the full available height after accounting for
   * insets and vGap).
   */
  public void layoutContainer(Container cont) {
    Insets margins = cont.getInsets();
    Component[] components = cont.getComponents();
    int left = margins.left + hGap,
        top = margins.top + vGap,
        count = countVisibleComponents(components),
        totalWidth = cont.getSize().width -
                     (count+1)*hGap -
                     margins.left - margins.right,
        totalHeight = cont.getSize().height - 2*vGap -
                      margins.top - margins.bottom,
        componentWidth = totalWidth/count,
        extra = totalWidth - componentWidth*count,
        width;
    Component c;
    for(int i=0; i<components.length; i++) {
      c = components[i];
      if (c.isVisible()) {
        if (extra>0) {
          width = componentWidth + 1;
          extra--;
        } else
          width = componentWidth;
        c.setBounds(left, top, width, totalHeight);
        left = left + width + hGap;
      }
    }
  }
  
  //----------------------------------------------------
  /** The horizontal gap as specified in the constructor
   *  or by setHgap.
   * @see #setHgap
   */
  public int getHgap() {
    return(hGap);
  }

  /** Sets the horizontal gap between components.
   * @param hGap The horizontal gap in pixels.
   * @see #getHgap
   */
  public void setHgap(int hGap) {
    this.hGap = hGap;
  }

  //----------------------------------------------------
  /** The vertical gap as specified in the constructor
   *  or by setVgap.
   * @see #setVgap
   */
  public int getVgap() {
    return(vGap);
  }

  /** Sets the vertical gap between components.
   * @param vGap The vertical gap in pixels.
   * @see #getVgap
   */
  public void setVgap(int vGap) {
    this.vGap = vGap;
  }

  //----------------------------------------------------

  private int countVisibleComponents(Component[] comps) {
    int count=0;
    for(int i=0; i<comps.length; i++)
      if(comps[i].isVisible())
        count++;
    return(count);
  }
}

