/* JLayeredPane.java -- 
   Copyright (C) 2002, 2004 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.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Hashtable;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;

/**
 * A container that adds depth to the usual <code>Container</code> semantics.
 * Each child component of a <code>Layered Pane</code> is placed within one
 * of several layers. <code>JLayeredPane</code> defines a set of standard
 * layers. The pre-defined sets are (in the order from button to top):
 *
 *  <dl>
 *    <dt>{@link #DEFAULT_LAYER}</dt>
 *    <dd>The layer where most of the normal components are placed. This
 *      is the bottommost layer.</dd>
 *
 *    <dt>{@link #PALETTE_LAYER}</dt>
 *    <dd>Palette windows are placed in this layer.</dd>
 *
 *    <dt>{@link #MODAL_LAYER}</dt>
 *    <dd>The layer where internal modal dialog windows are placed.</dd>
 *
 *    <dt>{@link #POPUP_LAYER}</dt>
 *    <dd>The layer for popup menus</dd>
 *
 *    <dt>{@link #DRAG_LAYER}</dt>
 *    <dd>Components that are beeing dragged are temporarily placed in
 *       this layer.</dd>
 *  </dl>
 *
 * <p>A child is in exactly one of these layers at any time, though there may
 * be other layers if someone creates them.</p>
 *
 * <p>You can add a component to a specific layer using the
 * {@link Container#add(Component, Object)} method. I.e.
 * <code>layeredPane.add(comp, JLayeredPane.MODAL_LAYER)</code> will add the
 * component <code>comp</code> to the modal layer of <code>layeredPane</code>.
 * </p>
 *
 * <p>To change the layer of a component that is already a child of
 * a <code>JLayeredPane</code>, use the {@link #setLayer(Component, int)} 
 * method.</p>
 *
 * <p>The purpose of this class is to translate this view of "layers" into a
 * contiguous array of components: the one held in our ancestor,
 * {@link java.awt.Container}.</p>
 *
 * <p>There is a precise set of words we will use to refer to numbers within
 * this class:</p>
 * 
 * <dl>
 * <dt>Component Index:</dt> 
 * <dd>An offset into the <code>component</code> array held in our ancestor,
 * {@link java.awt.Container}, from <code>[0 .. component.length)</code>. The drawing
 * rule with indices is that 0 is drawn last.</dd>
 *
 * <dt>Layer Number:</dt>
 * <dd>A general <code>int</code> specifying a layer within this component.  Negative
 * numbers are drawn first, then layer 0, then positive numbered layers, in
 * ascending order.</dd>
 *
 * <dt>Position:</dt> 
 * <dd>An offset into a layer's "logical drawing order". Layer position 0
 * is drawn last. Layer position -1 is a synonym for the first layer
 * position (the logical "bottom").</dd>
 * </dl>
 *
 * <p><b>Note:</b> the layer numbering order is the <em>reverse</em> of the
 * component indexing and position order</p>
 *
 * @author Graydon Hoare (graydon@redhat.com)
 * @author Roman Kennke (kennke@aicas.com)
 */
public class JLayeredPane extends JComponent implements Accessible
{
  
  /**
   * Provides accessibility support for <code>JLayeredPane</code>.
   */
  protected class AccessibleJLayeredPane extends AccessibleJComponent
  {
    /**
     * Creates a new instance of <code>AccessibleJLayeredPane</code>.
     */
    protected AccessibleJLayeredPane()
    {
      // Nothing to do here.
    }

    /**
     * Returns the accessble role of <code>JLayeredPane</code>,
     * {@link AccessibleRole#LAYERED_PANE}. 
     */
    public AccessibleRole getAccessibleRole()
    {
      return AccessibleRole.LAYERED_PANE;
    }
  }

  private static final long serialVersionUID = 5534920399324590459L;
  
  public static final String LAYER_PROPERTY = "layeredContainerLayer";

  public static final Integer FRAME_CONTENT_LAYER = new Integer(-30000);

  public static final Integer DEFAULT_LAYER = new Integer(0);
  public static final Integer PALETTE_LAYER = new Integer(100);
  public static final Integer MODAL_LAYER   = new Integer(200);
  public static final Integer POPUP_LAYER   = new Integer(300);
  public static final Integer DRAG_LAYER    = new Integer(400);

  private Hashtable componentToLayer;   // Component -> Layer Number (Integer)

  public JLayeredPane()
  {
    componentToLayer = new Hashtable();
    setLayout(null);
  }

  /** 
   * Looks up the layer a child component is currently assigned to.
   *
   * If <code>c</code> is an instance of {@link JComponent}, then the layer
   * is fetched from the client property with the key {@link #LAYER_PROPERTY}.
   * Otherwise it is looked up in an internal hashtable that maps
   * non-JComponent components to layers. If the components cannot be found
   * in either way, the {@link #DEFAULT_LAYER} is returned.
   *
   * @param c the component to look up.
   *
   * @return the layer the component is currently assigned to; if the component
   *         is not in this layered pane, then 0 (DEFAULT_LAYER) is returned
   */
  public int getLayer(Component c)
  {
    Integer layerObj;
    if (c instanceof JComponent)
      {
        JComponent jc = (JComponent) c;
        layerObj = (Integer) jc.getClientProperty(LAYER_PROPERTY);
      }
    else
      layerObj = (Integer) componentToLayer.get(c);

    if (layerObj == null)
      layerObj = DEFAULT_LAYER;

    return layerObj.intValue();
  }

  /**
   * Looks up the layer in the client property with the key
   * {@link #LAYER_PROPERTY} of <code>comp</code>. If no such property can be
   * found, we return <code>0</code> ({@link #DEFAULT_LAYER}).
   * 
   * @param comp the component for which the layer is looked up
   *
   * @return the layer of <code>comp</code> as stored in the corresponding
   *         client property, or <code>0</code> if there is no such property
   */
  public static int getLayer(JComponent comp)
  {
    Integer layerObj = (Integer) comp.getClientProperty(LAYER_PROPERTY);
    if (layerObj == null)
      layerObj = DEFAULT_LAYER;
    return layerObj.intValue();
  }

  /**
   * Returns the first JLayeredPane that contains the Component
   * <code>comp</code> or <code>null</code> if <code>comp</code> is
   * not contained in a JLayeredPane.
   *
   * @param comp the component for which we are searching the JLayeredPane
   *     ancestor
   *
   * @return the first JLayeredPane that contains the Component
   *     <code>comp</code> or <code>null</code> if <code>comp</code> is
   *     not contained in a JLayeredPane
   */
  public static JLayeredPane getLayeredPaneAbove(Component comp)
  {
    JLayeredPane lp = (JLayeredPane) SwingUtilities.getAncestorOfClass
      (JLayeredPane.class, comp);
    return lp;
  }

  /**
   * Return the greatest layer number currently in use, in this container.
   * This number may legally be positive <em>or</em> negative.
   *
   * @return the highest layer number
   *
   * @see #lowestLayer()
   */
  public int highestLayer()
  {
    Component[] components = getComponents();
    int highest;
    if (components.length == 0)
      highest = 0;
    else
      {
        highest = Integer.MIN_VALUE;
        for (int i = 0; i < components.length; i++)
          highest = Math.max(highest, getLayer(components[i]));
      }
    return highest;
  }

  /**
   * Return the least layer number currently in use, in this container.
   * This number may legally be positive <em>or</em> negative.
   *
   * @return the least layer number
   *
   * @see #highestLayer()
   */
  public int lowestLayer()
  {
    Component[] components = getComponents();
    int lowest;
    if (components.length == 0)
      lowest = 0;
    else
      {
        lowest = Integer.MAX_VALUE;
        for (int i = 0; i < components.length; i++)
          lowest = Math.max(lowest, getLayer(components[i]));
      }
    return lowest;
  }

  /**
   * Moves a component to the "front" of its layer. The "front" is a
   * synonym for position 0, which is also the last position drawn in each
   * layer, so is usually the component which occludes the most other
   * components in its layer.
   *
   * @param c the component to move to the front of its layer
   *
   * @see #moveToBack
   */
  public void moveToFront(Component c)
  {
    setPosition (c, 0);
  }

  /**
   * <p>Moves a component to the "back" of its layer. The "back" is a
   * synonym for position N-1 (also known as position -1), where N is the
   * size of the layer.</p>
   *
   * <p>The "back" of a layer is the first position drawn, so the component at
   * the "back" is usually the component which is occluded by the most
   * other components in its layer.</p>
   *
   * @param c the component to move to the back of its layer.
   *
   * @see #moveToFront
   */
  public void moveToBack(Component c)
  {
    setPosition (c, -1);
  }

  /**
   * Return the position of a component within its layer. Positions are assigned
   * from the "front" (position 0) to the "back" (position N-1), and drawn from 
   * the back towards the front.
   *
   * @param c the component to get the position of
   *
   * @return the position of <code>c</code> within its layer or -1 if
   *         <code>c</code> is not a child of this layered pane
   *
   * @see #setPosition
   */
  public int getPosition(Component c)
  {
    int pos = -1;
    int index = getIndexOf(c);
    if (index >= 0)
      {
        pos = 0;
        int layer = getLayer(c);
        for (int i = index - 1; i >= 0; --i)
          {
            if (layer == getLayer(getComponent(i)))
              pos++;
            else
              break;
          }
      }
    return pos;
  }

  /**
   * Change the position of a component within its layer. Positions are assigned
   * from the "front" (position 0) to the "back" (position N-1), and drawn from 
   * the back towards the front.
   *
   * @param c the component to change the position of
   * @param position the position to assign the component to
   *
   * @see #getPosition
   */
  public void setPosition(Component c, int position)
  {
    setLayer(c, getLayer(c), position);
  }
    
  /**
   * Return an array of all components within a layer of this
   * container. Components are ordered front-to-back, with the "front"
   * element (which draws last) at position 0 of the returned array.
   *
   * @param layer the layer to return components from
   *
   * @return the components in the layer
   */
  public Component[] getComponentsInLayer(int layer)
  {
    Component[] inLayer = new Component[getComponentCountInLayer(layer)];
    Component[] components = getComponents();
    int j = 0;
    for (int i = 0; i < components.length; ++i)
      {
        if (layer == getLayer(components[i]))
          {
            inLayer[j] = components[i];
            j++;
          }
      }
    return inLayer;
  }

  /**
   * Return the number of components within a layer of this
   * container.
   *
   * @param layer the layer count components in
   *
   * @return the number of components in the layer
   */
  public int getComponentCountInLayer(int layer)
  {
    Component[] components = getComponents();
    int count = 0;
    for (int i = components.length - 1; i >= 0; --i)
      {
        if (getLayer(components[i]) == layer)
          count++;
      }
    return count;
  }

  /**
   * Return a hashtable mapping child components of this container to
   * Integer objects representing the component's layer assignments.
   */
  protected Hashtable getComponentToLayer()
  {
    return componentToLayer;
  }

  /**
   * Return the index of a component within the underlying (contiguous)
   * array of children. This is a "raw" number which does not represent the
   * child's position in a layer, but rather its position in the logical
   * drawing order of all children of the container.
   *
   * @param c the component to look up.
   *
   * @return the external index of the component or <code>-1</code> if
   *         <code>c</code> is not a child of this layered pane 
   */
  public int getIndexOf(Component c) 
  {
    return getComponentZOrder(c);
  }

  /**
   * Return an Integer object which holds the same int value as the
   * parameter. This is strictly an optimization to minimize the number of
   * identical Integer objects which we allocate.
   *
   * @param layer the layer number as an int.
   *
   * @return the layer number as an Integer, possibly shared.
   */
  protected Integer getObjectForLayer(int layer)
  {
    switch (layer)
	    {
	    case -30000:
        return FRAME_CONTENT_LAYER;

	    case 0:
        return DEFAULT_LAYER;

	    case 100:
        return PALETTE_LAYER;

	    case 200:
        return MODAL_LAYER;

	    case 300:
        return POPUP_LAYER;

	    case 400:
        return DRAG_LAYER;

	    default:
        break;
	    }

    return new Integer(layer);
  }

  /**
   * Computes an index at which to request the superclass {@link
   * java.awt.Container} inserts a component, given an abstract layer and
   * position number.
   *
   * @param layer the layer in which to insert a component.
   * @param position the position in the layer at which to insert a component.
   *
   * @return the index at which to insert the component.
   */
  protected int insertIndexForLayer(int layer, int position)
  {
    return insertIndexForLayer(null, layer, position);
  }

  /**
   * Similar to {@link #insertIndexForLayer(int, int)}, only that it takes a
   * component parameter, which should be ignored in the search. This is
   * necessary to support {@link #setLayer(Component, int, int)} which uses
   * Container.setComponentZOrder(), which doesn't remove the component.
   *
   * @param comp the component to ignore
   * @param layer the layer
   * @param position the position
   *
   * @return the insertion index
   */
  private int insertIndexForLayer(Component comp, int layer, int position)
  {
    // Create the component list to search through.
    ArrayList l = new ArrayList();
    int count = getComponentCount();
    for (int i = 0; i < count; i++)
      {
        Component c = getComponent(i);
        if (c != comp)
          l.add(c);
      }

    count = l.size();
    int layerStart = -1;
    int layerEnd = -1;
    for (int i = 0; i < count; i++)
      {
        int layerOfComponent = getLayer((Component) l.get(i));
        if (layerStart == -1 && layerOfComponent == layer)
          layerStart = i;
        if (layerOfComponent < layer)
          {
            // We are beyond the layer that we are looking for. Update the
            // layerStart and layerEnd and exit the loop.
            if (i == 0)
              {
                layerStart = 0;
                layerEnd = 0;
              }
            else
              layerEnd = i;
            break;
          }
      }

    // No layer found. The requested layer is lower than any existing layer,
    // put the component at the end.
    int insertIndex;
    if (layerStart == -1 && layerEnd == -1)
      {
        insertIndex = count;
      }
    else
      {
        // Corner cases.
        if (layerStart != -1 && layerEnd == -1)
          layerEnd = count;
        if (layerStart == -1 && layerEnd != -1)
          layerStart = layerEnd;

        // Adding to the bottom of a layer returns the end index
        // in the layer.
        if (position == -1)
          insertIndex = layerEnd;
        else
          {
            // Insert into a layer.
            if (position > -1 && layerStart + position <= layerEnd)
              insertIndex = layerStart + position;
            else
              insertIndex = layerEnd;
          }
      }
    return insertIndex;
  }

  /**
   * Removes a child from this container. The child is specified by
   * index. After removal, the child no longer occupies a layer.
   *
   * @param index the index of the child component to remove.
   */
  public void remove(int index)
  {
    Component c = getComponent(index);
    if (! (c instanceof JComponent))
      componentToLayer.remove(c);
    super.remove(index);
  }

  /**
   * Removes all components from this container.
   *
   * @since 1.5
   */
  public void removeAll()
  {
	componentToLayer.clear();
	super.removeAll();
  }

  /**
   * <p>Set the layer property for a component, within this container. The
   * component will be implicitly mapped to the bottom-most position in the
   * layer, but only if added <em>after</em> calling this method.</p>
   *
   * <p>Read that carefully: this method should be called <em>before</em> the
   * component is added to the container.</p>
   *
   * @param c the component to set the layer property for.
   * @param layer the layer number to assign to the component.
   */
  public void setLayer(Component c, int layer)
  {
    setLayer(c, layer, -1);
  }

  /**
   * Set the layer and position of a component, within this container.
   *
   * @param c the child component to set the layer property for.
   * @param layer the layer number to assign to the component.
   * @param position the position number to assign to the component.
   */
  public void setLayer(Component c, int layer, int position)
  {
    Integer layerObj = getObjectForLayer(layer);

    // Nothing to do if neither the layer nor the position is
    // changed.
    if (layer != getLayer(c) || position != getPosition(c))
      {
        // Store the layer either in the JComponent or in the hashtable
        if (c instanceof JComponent)
          {
            JComponent jc = (JComponent) c;
            jc.putClientProperty(LAYER_PROPERTY, layerObj);
          }
        else
          componentToLayer.put (c, layerObj);

        // Update the component in the Z order of the Container.
        Container parent = c.getParent();
        if (parent == this)
          {
            int index = insertIndexForLayer(c, layer, position);
            setComponentZOrder(c, index);
          }
      }
    repaint(c.getX(), c.getY(), c.getWidth(), c.getHeight());
  }

  /**
   * Overrides the default implementation from {@link java.awt.Container}
   * such that <code>layerConstraint</code> is interpreted as an {@link
   * Integer}, specifying the layer to which the component will be added
   * (at the bottom position).
   *
   * The argument <code>index</code> specifies the position within the layer
   * at which the component should be added, where <code>0</code> is the top
   * position greater values specify positions below that and <code>-1</code>
   * specifies the bottom position.
   *
   * @param comp the component to add
   * @param layerConstraint an integer specifying the layer to add the
   *        component to
   * @param index the position within the layer
   */
  protected void addImpl(Component comp, Object layerConstraint, int index) 
  {
    int layer;
    if (layerConstraint != null && layerConstraint instanceof Integer)
      {
        layer = ((Integer) layerConstraint).intValue();
        setLayer(comp, layer);
      }
    else
      layer = getLayer(comp);

    int newIdx = insertIndexForLayer(layer, index);
    super.addImpl(comp, layerConstraint, newIdx);
    comp.validate();
    comp.repaint();
  }

  /**
   * Sets the layer property for a JComponent.
   *
   * @param component the component for which to set the layer
   * @param layer the layer property to set
   */
  public static void putLayer(JComponent component, int layer)
  {
    component.putClientProperty(LAYER_PROPERTY, new Integer(layer));
  }

  /**
   * Returns the accessible context for this <code>JLayeredPane</code>.
   *
   * @return the accessible context for this <code>JLayeredPane</code>
   */
  public AccessibleContext getAccessibleContext()
  {
    if (accessibleContext == null)
      accessibleContext = new AccessibleJLayeredPane();
    return accessibleContext;
  }

  /**
   * This method is overridden order to provide a reasonable painting
   * mechanism for <code>JLayeredPane</code>. This is necessary since
   * <code>JLayeredPane</code>'s do not have an own UI delegate.
   *
   * Basically this method clears the background for the
   * <code>JLayeredPane</code> and then calls <code>super.paint(g)</code>.
   *
   * @param g the graphics context to use
   */
  public void paint(Graphics g)
  {
    if (isOpaque())
      {
        Color oldColor = g.getColor();
        Rectangle clip = g.getClipBounds();
        g.setColor(getBackground());
        g.fillRect(clip.x, clip.y, clip.width, clip.height);
        g.setColor(oldColor);
      }
    super.paint(g);
  }

  /**
   * Returns <code>false</code> if components in this layered pane can overlap,
   * otherwise <code>true</code>.
   *
   * @return <code>false</code> if components in this layered pane can overlap,
   *         otherwise <code>true</code>
   */
  public boolean isOptimizedDrawingEnabled()
  {
    int numChildren = getComponentCount();
    boolean result = true;
    for (int i = 0; i < numChildren; ++i)
      {
    	Component c1 = getComponent(i);
    	if (! c1.isVisible())
          continue;
    	Rectangle r1 = c1.getBounds();
    	if (r1.isEmpty())
          continue;

    	for (int j = i + 1; j < numChildren; ++j)
          {
            Component c2 = getComponent(j);
            if (! c2.isVisible())
              continue;
            Rectangle r2 = c2.getBounds();
            if (r2.isEmpty())
              continue;
            if (r1.intersects(r2))
              {
                result = false;
                break;
              }
            if (result == false)
              break;
          }
      }
    return result;
  }
}
