/* 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., 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.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 ();
    }
  }

  /**
   * This flag indicates for which focus traversal key release event we
   * possibly wait, before letting any more KEY_TYPED events through.
   */
  private AWTKeyStroke waitForKeyStroke = null;

  /** 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);
            FocusTraversalPolicy p = target.getFocusTraversalPolicy();
            Component toFocus = p.getInitialComponent(target);
            if (toFocus != null)
              toFocus.requestFocusInWindow();
          }
        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)
      {
        FocusEvent fe = (FocusEvent) e;
        Component target = fe.getComponent ();

        boolean retval = false;
        if (e.id == FocusEvent.FOCUS_GAINED)
          {
            retval = handleFocusGained(fe);
          }
        else if (e.id == FocusEvent.FOCUS_LOST)
          {
            retval = handleFocusLost(fe);
          }
        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;
  }

  /**
   * Handles FOCUS_GAINED events in {@link #dispatchEvent(AWTEvent)}.
   *
   * @param fe the focus event
   */
  private boolean handleFocusGained(FocusEvent fe)
  {
    Component target = fe.getComponent ();

    // If old focus owner != new focus owner, notify old focus
    // owner that it has lost focus.
    Component oldFocusOwner = getGlobalFocusOwner();
    if (oldFocusOwner != null && oldFocusOwner != target)
      {
        FocusEvent lost = new FocusEvent(oldFocusOwner,
                                         FocusEvent.FOCUS_LOST,
                                         fe.isTemporary(), target);
        oldFocusOwner.dispatchEvent(lost);
      }

     setGlobalFocusOwner (target);
     if (target != getGlobalFocusOwner())
       {
         // Focus transfer was rejected, like when the target is not
         // focusable.
         dequeueKeyEvents(-1, target);
         // FIXME: Restore focus somehow.
       }
     else
       {
         if (! fe.isTemporary())
           {
             setGlobalPermanentFocusOwner (target);
             if (target != getGlobalPermanentFocusOwner())
               {
                 // Focus transfer was rejected, like when the target is not
                 // focusable.
                 dequeueKeyEvents(-1, target);
                 // FIXME: Restore focus somehow.
               }
             else
               {
                 redispatchEvent(target, fe);
               }
           }
       }

     return true;
  }

  /**
   * Handles FOCUS_LOST events for {@link #dispatchEvent(AWTEvent)}.
   *
   * @param fe the focus event
   *
   * @return if the event has been handled
   */
  private boolean handleFocusLost(FocusEvent fe)
  {
    Component currentFocus = getGlobalFocusOwner();
    if (currentFocus != fe.getOppositeComponent())
      {
        setGlobalFocusOwner(null);
        if (getGlobalFocusOwner() != null)
          {
            // TODO: Is this possible? If so, then we should try to restore
            // the focus.
          }
        else
          {
            if (! fe.isTemporary())
              {
                setGlobalPermanentFocusOwner(null);
                if (getGlobalPermanentFocusOwner() != null)
                  {
                    // TODO: Is this possible? If so, then we should try to
                    // restore the focus.
                  }
                else
                  {
                    fe.setSource(currentFocus);
                    redispatchEvent(currentFocus, fe);
                  }
              }
          }
      }
    return true;
  }

  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 = getFocusOwner();
    if (focusOwner == null)
      focusOwner = getFocusedWindow();
    
    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 (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).
    // consuming KEY_RELEASED is easy, because their keyCodes matches
    // the KEY_PRESSED event. Consuming the intermediate KEY_TYPED is
    // very difficult because their is no clean way that we can know
    // which KEY_TYPED belongs to a focusTraversalKey and which not.
    // To address this problem we swallow every KEY_TYPE between the
    // KEY_PRESSED event that matches a focusTraversalKey and the
    // corresponding KEY_RELEASED.
    AWTKeyStroke oppositeKeystroke = AWTKeyStroke.getAWTKeyStroke (e.getKeyCode (),
                                                                   e.getModifiersEx (),
                                                                   !(e.id == KeyEvent.KEY_RELEASED));

    // Here we check if we are currently waiting for a KEY_RELEASED and
    // swallow all KeyEvents that are to be delivered in between. This
    // should only be the KEY_TYPED events that correspond to the
    // focusTraversalKey's KEY_PRESSED event
    if (waitForKeyStroke != null)
      {
        if (eventKeystroke.equals(waitForKeyStroke))
          // release this lock
          waitForKeyStroke = null;

        // as long as we are waiting for the KEY_RELEASED, we swallow every
        // KeyEvent, including the KEY_RELEASED
        e.consume();
        return;
      }

    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))
      {
        waitForKeyStroke = oppositeKeystroke;        
        focusNextComponent (comp);
        e.consume ();
      }
    else if (backwardKeystrokes.contains (eventKeystroke))
      {
        waitForKeyStroke = oppositeKeystroke;        
        focusPreviousComponent (comp);
        e.consume ();
      }
    else if (upKeystrokes.contains (eventKeystroke))
      {
        waitForKeyStroke = oppositeKeystroke;        
        upFocusCycle (comp);
        e.consume ();
      }
    else if (comp instanceof Container
             && downKeystrokes.contains (eventKeystroke))
      {
        waitForKeyStroke = oppositeKeystroke;        
        downFocusCycle ((Container) comp);
        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)
  {
    if (comp != null)
      comp.transferFocusBackward();
  }

  public void focusNextComponent (Component comp)
  {
    if (comp != null)
      comp.transferFocus();
  }

  public void upFocusCycle (Component comp)
  {
    if (comp != null)
      comp.transferFocusUpCycle();
  }

  public void downFocusCycle (Container cont)
  {
    if (cont != null)
      cont.transferFocusDownCycle();
  }
} // class DefaultKeyboardFocusManager
