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