/* CardLayout.java -- Card-based layout engine
   Copyright (C) 1999, 2000, 2002, 2003, 2004  Free Software Foundation

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 java.awt;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 * This class implements a card-based layout scheme.  Each included
 * component is treated as a card.  Only one card can be shown at a
 * time.  This class includes methods for changing which card is
 * shown.
 *
 * @author Tom Tromey (tromey@redhat.com)
 * @author Aaron M. Renn (arenn@urbanophile.com)
 */
public class CardLayout implements LayoutManager2, Serializable
{
  private static final long serialVersionUID = -4328196481005934313L;

  /**
   * Initializes a new instance of <code>CardLayout</code> with horizontal
   * and vertical gaps of 0.
   */
  public CardLayout ()
  {
    this (0, 0);
  }

  /**
   * Create a new <code>CardLayout</code> object with the specified
   * horizontal and vertical gaps.
   *
   * @param hgap The horizontal gap
   * @param vgap The vertical gap
   */
  public CardLayout (int hgap, int vgap)
  {
    this.hgap = hgap;
    this.vgap = vgap;
    this.tab = new Hashtable ();
  }

  /**
   * Add a new component to the layout.  The constraint must be a
   * string which is used to name the component.  This string can
   * later be used to refer to the particular component.
   *
   * @param comp The component to add
   * @param constraints The name by which the component can later be called
   *
   * @exception IllegalArgumentException If `constraints' is not a
   * <code>String</code>
   */
  public void addLayoutComponent (Component comp, Object constraints)
  {
    if (! (constraints instanceof String))
      throw new IllegalArgumentException ("Object " + constraints
                                          + " is not a string");
    addLayoutComponent ((String) constraints, comp);
  }

  /**
   * Add a new component to the layout.  The name can be used later
   * to refer to the component.
   *
   * @param name The name by which the component can later be called
   * @param comp The component to add
   *
   * @deprecated This method is deprecated in favor of
   * <code>addLayoutComponent(Component, Object)</code>.
   */
  public void addLayoutComponent (String name, Component comp)
  {
    tab.put (name, comp);
    // First component added is the default component.
    comp.setVisible(tab.size() == 1);
  }

  /**
   * Cause the first component in the container to be displayed.
   *
   * @param parent The parent container, not <code>null</code>.
   */
  public void first (Container parent)
  {
    gotoComponent (parent, FIRST);
  }

  /**
   * Return this layout manager's horizontal gap.
   *
   * @return the horizontal gap
   */
  public int getHgap ()
  {
    return hgap;
  }

  /**
   * Return this layout manager's x alignment.  This method always
   * returns Component.CENTER_ALIGNMENT.
   *
   * @param parent Container using this layout manager instance
   *
   * @return the x-axis alignment
   */
  public float getLayoutAlignmentX (Container parent)
  {
    return Component.CENTER_ALIGNMENT;
  }

  /**
   * Returns this layout manager's y alignment.  This method always
   * returns Component.CENTER_ALIGNMENT.
   *
   * @param parent Container using this layout manager instance
   *
   * @return the y-axis alignment
   */
  public float getLayoutAlignmentY (Container parent)
  {
    return Component.CENTER_ALIGNMENT;
  }

  /**
   * Return this layout manager's vertical gap.
   *
   * @return the vertical gap
   */
  public int getVgap ()
  {
    return vgap;
  }

  /**
   * Invalidate this layout manager's state.
   */
  public void invalidateLayout (Container target)
  {
    // Do nothing.
  }

  /**
   * Cause the last component in the container to be displayed.
   *
   * @param parent The parent container, not <code>null</code>.
   */
  public void last (Container parent)
  {
    gotoComponent (parent, LAST);
  }

  /**
   * Lays out the container.  This is done by resizing the child components
   * to be the same size as the parent, less insets and gaps.
   *
   * @param parent The parent container.
   */
  public void layoutContainer (Container parent)
  {
    synchronized (parent.getTreeLock ())
      {
        int width = parent.width;
        int height = parent.height;

        Insets ins = parent.getInsets ();

        int num = parent.ncomponents;
        Component[] comps = parent.component;

        int x = ins.left + hgap;
        int y = ins.top + vgap;
        width = width - 2 * hgap - ins.left - ins.right;
        height = height - 2 * vgap - ins.top - ins.bottom;

        for (int i = 0; i < num; ++i)
          comps[i].setBounds (x, y, width, height);
      }
  }

  /**
   * Get the maximum layout size of the container.
   *
   * @param target The parent container
   *
   * @return the maximum layout size
   */
  public Dimension maximumLayoutSize (Container target)
  {
    if (target == null || target.ncomponents == 0)
      return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
    // The JCL says that this returns Integer.MAX_VALUE for both
    // dimensions.  But that just seems wrong to me.
    return getSize (target, MAX);
  }

  /**
   * Get the minimum layout size of the container.
   *
   * @param target The parent container
   *
   * @return the minimum layout size
   */
  public Dimension minimumLayoutSize (Container target)
  {
    return getSize (target, MIN);
  }

  /**
   * Cause the next component in the container to be displayed.  If
   * this current card is the  last one in the deck, the first
   * component is displayed.
   *
   * @param parent The parent container, not <code>null</code>.
   */
  public void next (Container parent)
  {
    gotoComponent (parent, NEXT);
  }

  /**
   * Get the preferred layout size of the container.
   *
   * @param parent The parent container
   *
   * @return the preferred layout size
   */
  public Dimension preferredLayoutSize (Container parent)
  {
    return getSize (parent, PREF);
  }

  /**
   * Cause the previous component in the container to be displayed.
   * If this current card is the first one in the deck, the last
   * component is displayed.
   *
   * @param parent The parent container, not <code>null</code>.
   */
  public void previous (Container parent)
  {
    gotoComponent (parent, PREV);
  }

  /**
   * Remove the indicated component from this layout manager.
   *
   * @param comp The component to remove
   */
  public void removeLayoutComponent (Component comp)
  {
    Enumeration e = tab.keys ();
    while (e.hasMoreElements ())
      {
        Object key = e.nextElement ();
        if (tab.get (key) == comp)
          {
            tab.remove (key);
            Container parent = comp.getParent();
            next(parent);
            break;
          }
      }
  }

  /**
   * Set this layout manager's horizontal gap.
   *
   * @param hgap The new gap
   */
  public void setHgap (int hgap)
  {
    this.hgap = hgap;
  }

  /**
   * Set this layout manager's vertical gap.
   *
   * @param vgap The new gap
   */
  public void setVgap (int vgap)
  {
    this.vgap = vgap;
  }

  /**
   * Cause the named component to be shown.  If the component name is
   * unknown or <code>null</code>, this method does nothing.
   *
   * @param parent The parent container, not <code>null</code>.
   * @param name The name of the component to show
   */
  public void show (Container parent, String name)
  {
    if (name == null)
      return;

    if (parent.getLayout() != this)
      throw new IllegalArgumentException("parent's layout is not this CardLayout");

    Object target = tab.get (name);
    if (target != null)
      {
        int num = parent.ncomponents;
        // This is more efficient than calling getComponents().
        Component[] comps = parent.component;
        for (int i = 0; i < num; ++i)
          {
            if (comps[i].isVisible())
              {
                if (target == comps[i])
                  return;
                comps[i].setVisible (false);
              }
          }
        ((Component) target).setVisible (true);
        parent.validate();
      }
  }

  /**
   * Returns a string representation of this layout manager.
   *
   * @return A string representation of this object.
   */
  public String toString ()
  {
    return getClass ().getName () + "[hgap=" + hgap + ",vgap=" + vgap + "]";
  }

  /**
   * This implements first(), last(), next(), and previous().
   *
   * @param parent The parent container
   * @param what The type of goto: FIRST, LAST, NEXT or PREV
   *
   * @throws IllegalArgumentException if parent has not this
   * CardLayout set as its layout.
   */
  private void gotoComponent (Container parent, int what)
  {
    if (parent.getLayout() != this)
      throw new IllegalArgumentException("parent's layout is not this CardLayout");

    synchronized (parent.getTreeLock ())
      {
        int num = parent.ncomponents;
        // This is more efficient than calling getComponents().
        Component[] comps = parent.component;

        if (num == 1)
          {
            comps[0].setVisible(true);
            return;
          }

        int choice = -1;

        if (what == FIRST)
          choice = 0;
        else if (what == LAST)
          choice = num - 1;

        for (int i = 0; i < num; ++i)
          {
            if (comps[i].isVisible ())
              {
                if (choice == i)
                  {
                    // Do nothing if we're already looking at the right
                    // component.
                    return;
                  }
                else if (what == PREV)
                  {
                    choice = i - 1;
                    if (choice < 0)
                      choice = num - 1;
                  }
                else if (what == NEXT)
                  {
                    choice = i + 1;
                    if (choice == num)
                      choice = 0;
                  }
                comps[i].setVisible (false);

                if (choice >= 0)
                  break;
              } else
                {
                  comps[i].setVisible(true);
                }
          }

        if (choice >= 0 && choice < num)
          comps[choice].setVisible (true);
      }
  }

  // Compute the size according to WHAT.
  private Dimension getSize (Container parent, int what)
  {
    synchronized (parent.getTreeLock ())
      {
        int w = 0, h = 0, num = parent.ncomponents;
        Component[] comps = parent.component;

        for (int i = 0; i < num; ++i)
          {
            Dimension d;

            if (what == MIN)
              d = comps[i].getMinimumSize ();
            else if (what == MAX)
              d = comps[i].getMaximumSize ();
            else
              d = comps[i].getPreferredSize ();

            w = Math.max (d.width, w);
            h = Math.max (d.height, h);
          }

        Insets i = parent.getInsets ();
        w += 2 * hgap + i.right + i.left;
        h += 2 * vgap + i.bottom + i.top;

        // Handle overflow.
        if (w < 0)
          w = Integer.MAX_VALUE;
        if (h < 0)
          h = Integer.MAX_VALUE;

        return new Dimension (w, h);
      }
  }

  /**
   * @serial Horizontal gap value.
   */
  private int hgap;

  /**
   * @serial Vertical gap value.
   */
  private int vgap;

  /**
   * @serial Table of named components.
   */
  private Hashtable tab;

  // These constants are used by the private gotoComponent method.
  private static final int FIRST = 0;
  private static final int LAST = 1;
  private static final int NEXT = 2;
  private static final int PREV = 3;

  // These constants are used by the private getSize method.
  private static final int MIN = 0;
  private static final int MAX = 1;
  private static final int PREF = 2;
}
