/* ContainerOrderFocusTraversalPolicy.java -- 
   Copyright (C) 2002, 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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;

/**
 * ContainerOrderFocusTraversalPolicy defines a focus traversal order
 * based on the order in which Components were packed in a Container.
 * This policy performs a pre-order traversal of the Component
 * hierarchy starting from a given focus cycle root.  Portions of the
 * hierarchy that are not visible and displayable are skipped.
 *
 * By default, this policy transfers focus down-cycle implicitly.
 * That is, if a forward traversal is requested on a focus cycle root
 * and the focus cycle root has focusable children, the focus will
 * automatically be transfered down to the lower focus cycle.
 *
 * The default implementation of accept accepts only Components that
 * are visible, displayable, enabled and focusable.  Derived classes
 * can override these acceptance criteria by overriding accept.
 *
 * @author Michael Koch
 * @author Thomas Fitzsimmons (fitzsim@redhat.com)
 * @since 1.4
 */
public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
  implements Serializable
{
  /**
   * Compatible to JDK 1.4+
   */
  static final long serialVersionUID = 486933713763926351L;

  /**
   * True if implicit down cycling is enabled.
   */
  private boolean implicitDownCycleTraversal = true;

  /**
   * Creates the <code>ContainerOrderFocusTraversalPolicy</code> object.
   */
  public ContainerOrderFocusTraversalPolicy ()
  {
    // Nothing to do here
  }

  /**
   * Returns the Component that should receive the focus after current.
   * root must be a focus cycle root of current.
   *
   * @param root a focus cycle root of current
   * @param current a (possibly indirect) child of root, or root itself
   *
   * @return the next Component in the focus traversal order for root,
   * or null if no acceptable Component exists.
   *
   * @exception IllegalArgumentException If root is not a focus cycle
   * root of current, or if either root or current is null.
   */
  public Component getComponentAfter (Container root, Component current)
  {
    if (root == null)
      throw new IllegalArgumentException ("focus cycle root is null");
    if (current == null)
      throw new IllegalArgumentException ("current component is null");

    if (!root.isFocusCycleRoot ())
      throw new IllegalArgumentException ("root is not a focus cycle root");

    Container ancestor = current.getFocusCycleRootAncestor ();
    Container prevAncestor = ancestor;
    while (ancestor != root)
      {
	ancestor = current.getFocusCycleRootAncestor ();
	if (ancestor == prevAncestor)
	  {
	    // We've reached the top focus cycle root ancestor.  Check
	    // if it is root.
	    if (ancestor != root)
	      throw new IllegalArgumentException ("the given container is not"
						  + " a focus cycle root of the"
						  + " current component");
	    else
	      break;
	  }
	prevAncestor = ancestor;
      }

    // FIXME: is this the right thing to do here? It moves the context
    // for traversal up one focus traversal cycle.  We'll need a test
    // for this.
    if ((Component) root == current)
      root = current.getFocusCycleRootAncestor ();

    // Check if we've reached the top of the component hierarchy.  If
    // so then we want to loop around to the first component in the
    // focus traversal cycle.
    if (current instanceof Window)
      return getFirstComponent ((Container) current);

    Container parent = current.getParent ();

    synchronized (parent.getTreeLock ())
      {
        Component[] components = parent.getComponents ();
        int componentIndex = 0;
        int numComponents = parent.getComponentCount ();

        // Find component's index.
        for (int i = 0; i < numComponents; i++)
          {
            if (components[i] == current)
              componentIndex = i;
          }

        // Search forward for the next acceptable component.
        for (int i = componentIndex + 1; i < numComponents; i++)
          {
            if (accept (components[i]))
              return components[i];

            if (components[i] instanceof Container)
              {
                Component result = getFirstComponent ((Container) components[i]);

                if (result != null
                    && implicitDownCycleTraversal)
                  return result;
              }
          }

        // No focusable components after current in its Container.  So go
        // to the next Component after current's Container (parent).
        Component result = getComponentAfter (root, parent);

        return result;
      }
  }

  /**
   * Returns the Component that should receive the focus before
   * <code>current</code>.  <code>root</code> must be a focus cycle
   * root of current.
   *
   * @param root a focus cycle root of current
   * @param current a (possibly indirect) child of root, or root itself
   *
   * @return the previous Component in the focus traversal order for
   * root, or null if no acceptable Component exists.
   *
   * @exception IllegalArgumentException If root is not a focus cycle
   * root of current, or if either root or current is null.
   */
  public Component getComponentBefore (Container root, Component current)
  {
    if (root == null)
      throw new IllegalArgumentException ("focus cycle root is null");
    if (current == null)
      throw new IllegalArgumentException ("current component is null");

    if (!root.isFocusCycleRoot ())
      throw new IllegalArgumentException ("root is not a focus cycle root");

    Container ancestor = current.getFocusCycleRootAncestor ();
    Container prevAncestor = ancestor;
    while (ancestor != root)
      {
	ancestor = current.getFocusCycleRootAncestor ();
	if (ancestor == prevAncestor)
	  {
	    // We've reached the top focus cycle root ancestor.  Check
	    // if it is root.
	    if (ancestor != root)
	      throw new IllegalArgumentException ("the given container is not"
						  + " a focus cycle root of the"
						  + " current component");
	    else
	      break;
	  }
	prevAncestor = ancestor;
      }

    // FIXME: is this the right thing to do here? It moves the context
    // for traversal up one focus traversal cycle.  We'll need a test
    // for this.
    if ((Component) root == current)
      root = current.getFocusCycleRootAncestor ();

    // Check if we've reached the top of the component hierarchy.  If
    // so then we want to loop around to the last component in the
    // focus traversal cycle.
    if (current instanceof Window)
      return getLastComponent ((Container) current);

    Container parent = current.getParent ();

    synchronized (parent.getTreeLock ())
      {
        Component[] components = parent.getComponents ();
        int componentIndex = 0;
        int numComponents = parent.getComponentCount ();

        // Find component's index.
        for (int i = 0; i < numComponents; i++)
          {
            if (components[i] == current)
              componentIndex = i;
          }

        // Search backward for the next acceptable component.
        for (int i = componentIndex - 1; i >= 0; i--)
          {
            if (accept (components[i]))
              return components[i];

            if (components[i] instanceof Container)
              {
                Component result = getLastComponent ((Container) components[i]);

                if (result != null)
                  return result;
              }
          }

        // No focusable components before current in its Container.  So go
        // to the previous Component before current's Container (parent).
        Component result = getComponentBefore (root, parent);

        return result;
      }
  }

  /**
   * Returns the first Component of root that should receive the focus.
   *
   * @param root a focus cycle root
   *
   * @return the first Component in the focus traversal order for
   * root, or null if no acceptable Component exists.
   *
   * @exception IllegalArgumentException If root is null.
   */
  public Component getFirstComponent(Container root)
  {
    if (root == null)
      throw new IllegalArgumentException ();

    if (!root.isVisible ()
        || !root.isDisplayable ())
      return null;

    if (accept (root))
      return root;

    Component[] componentArray = root.getComponents ();
    
    for (int i = 0; i < componentArray.length; i++)
      {
        Component component = componentArray [i];
	
	if (accept (component))
	  return component;

        if (component instanceof Container)
          {
            Component result = getFirstComponent ((Container) component);

            if (result != null)
              return result;
          }
      }

    return null;
  }

  /**
   * Returns the last Component of root that should receive the focus.
   *
   * @param root a focus cycle root
   *
   * @return the last Component in the focus traversal order for
   * root, or null if no acceptable Component exists.
   *
   * @exception IllegalArgumentException If root is null.
   */
  public Component getLastComponent (Container root)
  {
    if (root == null)
      throw new IllegalArgumentException ();

    if (!root.isVisible ()
        || !root.isDisplayable ())
      return null;

    if (accept (root))
      return root;

    Component[] componentArray = root.getComponents ();
    
    for (int i = componentArray.length - 1; i >= 0; i--)
      {
        Component component = componentArray [i];
	
	if (accept (component))
	  return component;

        if (component instanceof Container)
          {
            Component result = getLastComponent ((Container) component);

            if (result != null)
              return result;
          }
      }

    return null;
  }

  /**
   * Returns the default Component of root that should receive the focus.
   *
   * @param root a focus cycle root
   *
   * @return the default Component in the focus traversal order for
   * root, or null if no acceptable Component exists.
   *
   * @exception IllegalArgumentException If root is null.
   */
  public Component getDefaultComponent (Container root)
  {
    return getFirstComponent (root);
  }

  /**
   * Set whether or not implicit down cycling is enabled.  If it is,
   * then initiating a forward focus traversal operation onto a focus
   * cycle root, the focus will be implicitly transferred into the
   * root container's focus cycle.
   *
   * @param value the setting for implicit down cycling
   */
  public void setImplicitDownCycleTraversal (boolean value)
  {
    implicitDownCycleTraversal = value;
  }

  /**
   * Check whether or not implicit down cycling is enabled.  If it is,
   * then initiating a forward focus traversal operation onto a focus
   * cycle root, the focus will be implicitly transferred into the
   * root container's focus cycle.
   *
   * @return true if the focus will be transferred down-cycle
   * implicitly
   */
  public boolean getImplicitDownCycleTraversal ()
  {
    return implicitDownCycleTraversal;
  }

  /**
   * Check whether the given Component is an acceptable target for the
   * keyboard input focus.
   *
   * @param current the Component to check
   *
   * @return true if current is acceptable, false otherwise
   */
  protected boolean accept (Component current)
  {
    return (current.visible
            && current.isDisplayable ()
            && current.enabled
            && current.focusable);
  }
}
