/* DefaultKeyboardFocusManager.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., 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.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

// FIXME: finish documentation
public class DefaultKeyboardFocusManager extends KeyboardFocusManager
{
  /**
   * This class models a request to delay the dispatch of events that
   * arrive after a certain time, until a certain component becomes
   * the focus owner.
   */
  private class EventDelayRequest implements Comparable
  {
    /** A {@link java.util.List} of {@link java.awt.event.KeyEvent}s
        that are being delayed, pending this request's {@link
        Component} receiving the keyboard focus. */
    private LinkedList enqueuedKeyEvents = new LinkedList ();

    /** An event timestamp.  All events that arrive after this time
        should be queued in the {@link #enqueuedKeyEvents} {@link
        java.util.List}. */
    public long timestamp;
    /** When this {@link Component} becomes focused, all events
        between this EventDelayRequest and the next one in will be
        dispatched from {@link #enqueuedKeyEvents}. */
    public Component focusedComp;

    /**
     * Construct a new EventDelayRequest.
     *
     * @param timestamp events that arrive after this time will be
     * delayed
     * @param focusedComp the Component that needs to receive focus
     * before events are dispatched
     */
    public EventDelayRequest (long timestamp, Component focusedComp)
    {
      this.timestamp = timestamp;
      this.focusedComp = focusedComp;
    }

    public int compareTo (Object o)
    {
      if (!(o instanceof EventDelayRequest))
        throw new ClassCastException ();

      EventDelayRequest request = (EventDelayRequest) o;

      if (request.timestamp < timestamp)
        return -1;
      else if (request.timestamp == timestamp)
        return 0;
      else
        return 1;
    }

    public boolean equals (Object o)
    {
      if (!(o instanceof EventDelayRequest) || o == null)
        return false;

      EventDelayRequest request = (EventDelayRequest) o;

      return (request.timestamp == timestamp
              && request.focusedComp == focusedComp);
    }

    public void enqueueEvent (KeyEvent e)
    {
      KeyEvent last = (KeyEvent) enqueuedKeyEvents.getLast ();
      if (last != null && e.getWhen () < last.getWhen ())
        throw new RuntimeException ("KeyEvents enqueued out-of-order");

      if (e.getWhen () <= timestamp)
        throw new RuntimeException ("KeyEvents enqueued before starting timestamp");

      enqueuedKeyEvents.add (e);
    }

    public void dispatchEvents ()
    {
      int size = enqueuedKeyEvents.size ();
      for (int i = 0; i < size; i++)
        {
          KeyEvent e = (KeyEvent) enqueuedKeyEvents.remove (0);
          dispatchKeyEvent (e);
        }
    }

    public void discardEvents ()
    {
      enqueuedKeyEvents.clear ();
    }
  }

  /** The {@link java.util.SortedSet} of current {@link
      #EventDelayRequest}s. */
  private SortedSet delayRequests = new TreeSet ();

  public DefaultKeyboardFocusManager ()
  {
  }

  public boolean dispatchEvent (AWTEvent e)
  {
    if (e instanceof WindowEvent)
      {
        Window target = (Window) e.getSource ();

        if (e.id == WindowEvent.WINDOW_ACTIVATED)
          setGlobalActiveWindow (target);
        else if (e.id == WindowEvent.WINDOW_GAINED_FOCUS)
          setGlobalFocusedWindow (target);
        else if (e.id != WindowEvent.WINDOW_LOST_FOCUS
                 && e.id != WindowEvent.WINDOW_DEACTIVATED)
          return false;

        redispatchEvent(target, e);
        return true;
      }
    else if (e instanceof FocusEvent)
      {
        Component target = (Component) e.getSource ();

        if (e.id == FocusEvent.FOCUS_GAINED)
          {
            if (! (target instanceof Window))
              {
                if (((FocusEvent) e).isTemporary ())
                  setGlobalFocusOwner (target);
                else
                  setGlobalPermanentFocusOwner (target);
              }

            // Keep track of this window's focus owner.

            // Find the target Component's top-level ancestor.
            Container parent = target.getParent ();

            while (parent != null
                   && !(parent instanceof Window))
              parent = parent.getParent ();

            Window toplevel = parent == null ?
              (Window) target : (Window) parent;

            Component focusOwner = getFocusOwner ();
            if (focusOwner != null
                && ! (focusOwner instanceof Window))
              toplevel.setFocusOwner (focusOwner);
          }
        else if (e.id == FocusEvent.FOCUS_LOST)
          {
            if (((FocusEvent) e).isTemporary ())
              setGlobalFocusOwner (null);
            else
              setGlobalPermanentFocusOwner (null);
          }

        redispatchEvent(target, e);

        return true;
      }
    else if (e instanceof KeyEvent)
      {
        // Loop through all registered KeyEventDispatchers, giving
        // each a chance to handle this event.
        Iterator i = getKeyEventDispatchers().iterator();

        while (i.hasNext ())
          {
            KeyEventDispatcher dispatcher = (KeyEventDispatcher) i.next ();
            if (dispatcher.dispatchKeyEvent ((KeyEvent) e))
              return true;
          }

        // processKeyEvent checks if this event represents a focus
        // traversal key stroke.
        Component focusOwner = getGlobalPermanentFocusOwner ();

        if (focusOwner != null)
          processKeyEvent (focusOwner, (KeyEvent) e);

        if (e.isConsumed ())
          return true;

        if (enqueueKeyEvent ((KeyEvent) e))
          // This event was enqueued for dispatch at a later time.
          return true;
        else
          // This event wasn't handled by any of the registered
          // KeyEventDispatchers, and wasn't enqueued for dispatch
          // later, so send it to the default dispatcher.
          return dispatchKeyEvent ((KeyEvent) e);
      }

    return false;
  }

  private boolean enqueueKeyEvent (KeyEvent e)
  {
    Iterator i = delayRequests.iterator ();
    boolean oneEnqueued = false;
    while (i.hasNext ())
      {
        EventDelayRequest request = (EventDelayRequest) i.next ();
        if (e.getWhen () > request.timestamp)
          {
            request.enqueueEvent (e);
            oneEnqueued = true;
          }
      }
    return oneEnqueued;
  }

  public boolean dispatchKeyEvent (KeyEvent e)
  {
    Component focusOwner = getGlobalPermanentFocusOwner ();

    if (focusOwner != null)
      redispatchEvent(focusOwner, e);

    // Loop through all registered KeyEventPostProcessors, giving
    // each a chance to process this event.
    Iterator i = getKeyEventPostProcessors().iterator();

    while (i.hasNext ())
      {
        KeyEventPostProcessor processor = (KeyEventPostProcessor) i.next ();
        if (processor.postProcessKeyEvent ((KeyEvent) e))
          return true;
      }

    // The event hasn't been consumed yet.  Check if it is an
    // MenuShortcut.
    if (postProcessKeyEvent (e))
      return true;

    // Always return true.
    return true;
  }

  public boolean postProcessKeyEvent (KeyEvent e)
  {
    // Check if this event represents a menu shortcut.

    // MenuShortcuts are activated by Ctrl- KeyEvents, only on KEY_PRESSED.
    int modifiers = e.getModifiersEx ();
    if (e.getID() == KeyEvent.KEY_PRESSED
        && (modifiers & KeyEvent.CTRL_DOWN_MASK) != 0)
      {
        Window focusedWindow = getGlobalFocusedWindow ();
        if (focusedWindow instanceof Frame)
          {
            MenuBar menubar = ((Frame) focusedWindow).getMenuBar ();

            if (menubar != null)
              {
                // If there's a menubar, loop through all menu items,
                // checking whether each one has a shortcut, and if
                // so, whether this key event should activate it.
                int numMenus = menubar.getMenuCount ();

                for (int i = 0; i < numMenus; i++)
                  {
                    Menu menu = menubar.getMenu (i);
                    int numItems = menu.getItemCount ();

                    for (int j = 0; j < numItems; j++)
                      {
                        MenuItem item = menu.getItem (j);
                        MenuShortcut shortcut = item.getShortcut ();

                        if (item.isEnabled() && shortcut != null)
                          {
                            // Dispatch a new ActionEvent if:
                            //
                            //     a) this is a Shift- KeyEvent, and the
                            //        shortcut requires the Shift modifier
                            //
                            // or, b) this is not a Shift- KeyEvent, and the
                            //        shortcut does not require the Shift
                            //        modifier.
                            if (shortcut.getKey () == e.getKeyCode ()
                                && ((shortcut.usesShiftModifier ()
                                     && (modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0)
                                    || (! shortcut.usesShiftModifier ()
                                        && (modifiers & KeyEvent.SHIFT_DOWN_MASK) == 0)))
                              {
                                item.dispatchEvent (new ActionEvent (item,
                                                                     ActionEvent.ACTION_PERFORMED,
                                                                     item.getActionCommand (),
                                                                     modifiers));
                                // The event was dispatched.
                                return true;
                              }
                          }
                      }
                  }
              }
          }
      }
    return false;
  }

  public void processKeyEvent (Component comp, KeyEvent e)
  {
    AWTKeyStroke eventKeystroke = AWTKeyStroke.getAWTKeyStrokeForEvent (e);
    // For every focus traversal keystroke, we need to also consume
    // the other two key event types for the same key (e.g. if
    // KEY_PRESSED TAB is a focus traversal keystroke, we also need to
    // consume KEY_RELEASED and KEY_TYPED TAB key events).
    AWTKeyStroke oppositeKeystroke = AWTKeyStroke.getAWTKeyStroke (e.getKeyCode (),
                                                                   e.getModifiersEx (),
                                                                   !(e.id == KeyEvent.KEY_RELEASED));

    Set forwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
    Set backwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
    Set upKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
    Set downKeystrokes = null;
    if (comp instanceof Container)
      downKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);

    if (forwardKeystrokes.contains (eventKeystroke))
      {
        focusNextComponent (comp);
        e.consume ();
      }
    else if (backwardKeystrokes.contains (eventKeystroke))
      {
        focusPreviousComponent (comp);
        e.consume ();
      }
    else if (upKeystrokes.contains (eventKeystroke))
      {
        upFocusCycle (comp);
        e.consume ();
      }
    else if (comp instanceof Container
             && downKeystrokes.contains (eventKeystroke))
      {
        downFocusCycle ((Container) comp);
        e.consume ();
      }
    else if (forwardKeystrokes.contains (oppositeKeystroke)
             || backwardKeystrokes.contains (oppositeKeystroke)
             || upKeystrokes.contains (oppositeKeystroke)
             || (comp instanceof Container &&
                 downKeystrokes.contains (oppositeKeystroke)))
      e.consume ();
  }

  protected void enqueueKeyEvents (long after, Component untilFocused)
  {
    delayRequests.add (new EventDelayRequest (after, untilFocused));
  }

  protected void dequeueKeyEvents (long after, Component untilFocused)
  {
    // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.

    // Remove the KeyEvent with the oldest timestamp, which should be
    // the first element in the SortedSet.
    if (after < 0)
      {
        int size = delayRequests.size ();
        if (size > 0)
          delayRequests.remove (delayRequests.first ());
      }
    else
      {
        EventDelayRequest template = new EventDelayRequest (after, untilFocused);
        if (delayRequests.contains (template))
          {
            EventDelayRequest actual = (EventDelayRequest) delayRequests.tailSet (template).first ();
            delayRequests.remove (actual);
            actual.dispatchEvents ();
          }
      }
  }

  protected void discardKeyEvents (Component comp)
  {
    // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.

    Iterator i = delayRequests.iterator ();

    while (i.hasNext ())
      {
        EventDelayRequest request = (EventDelayRequest) i.next ();

        if (request.focusedComp == comp
            || (comp instanceof Container
                && ((Container) comp).isAncestorOf (request.focusedComp)))
          request.discardEvents ();
      }
  }

  public void focusPreviousComponent (Component comp)
  {
    Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
    Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
    FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();

    Component previous = policy.getComponentBefore (focusCycleRoot, focusComp);
    if (previous != null)
      previous.requestFocusInWindow ();
  }

  public void focusNextComponent (Component comp)
  {
    Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
    Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();
    FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();

    Component next = policy.getComponentAfter (focusCycleRoot, focusComp);
    if (next != null)
      next.requestFocusInWindow ();
  }

  public void upFocusCycle (Component comp)
  {
    Component focusComp = (comp == null) ? getGlobalFocusOwner () : comp;
    Container focusCycleRoot = focusComp.getFocusCycleRootAncestor ();

    if (focusCycleRoot instanceof Window)
      {
        FocusTraversalPolicy policy = focusCycleRoot.getFocusTraversalPolicy ();
        Component defaultComponent = policy.getDefaultComponent (focusCycleRoot);
        if (defaultComponent != null)
          defaultComponent.requestFocusInWindow ();
      }
    else
      {
        Container parentFocusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor ();

        focusCycleRoot.requestFocusInWindow ();
        setGlobalCurrentFocusCycleRoot (parentFocusCycleRoot);
      }
  }

  public void downFocusCycle (Container cont)
  {
    if (cont == null)
      return;

    if (cont.isFocusCycleRoot (cont))
      {
        FocusTraversalPolicy policy = cont.getFocusTraversalPolicy ();
        Component defaultComponent = policy.getDefaultComponent (cont);
        if (defaultComponent != null)
          defaultComponent.requestFocusInWindow ();        
        setGlobalCurrentFocusCycleRoot (cont);
      }
  }
} // class DefaultKeyboardFocusManager
