/* KeyboardManager.java --
   Copyright (C) 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., 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.applet.Applet;
import java.awt.Component;
import java.awt.Container;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.WeakHashMap;

/**
 * This class maintains a mapping from top-level containers to a
 * Hashtable.  The Hashtable maps KeyStrokes to Components to be used when
 * Components register keyboard actions with the condition
 * JComponent.WHEN_IN_FOCUSED_WINDOW.
 *
 * @author Anthony Balkissoon abalkiss at redhat dot com
 *
 */
class KeyboardManager
{
  /** Shared instance of KeyboardManager **/
  static KeyboardManager manager = new KeyboardManager();

  /**
   * A mapping between top level containers and Hashtables that
   * map KeyStrokes to Components.
   */
  WeakHashMap topLevelLookup = new WeakHashMap();

  /**
   * A mapping between top level containers and Vectors of JMenuBars
   * used to allow all the JMenuBars within a top level container
   * a chance to consume key events.
   */
  Hashtable menuBarLookup = new Hashtable();
  /**
   * Returns the shared instance of KeyboardManager.
   * @return the shared instance of KeybaordManager.
   */
  public static KeyboardManager getManager()
  {
    return manager;
  }
  /**
   * Returns the top-level ancestor for the given JComponent.
   * @param c the JComponent whose top-level ancestor we want
   * @return the top-level ancestor for the given JComponent.
   */
  static Container findTopLevel (Component c)
  {
    Container topLevel = (c instanceof Container) ? (Container) c
                                                 : c.getParent();
    while (topLevel != null &&
           !(topLevel instanceof Window) &&
           !(topLevel instanceof Applet) &&
           !(topLevel instanceof JInternalFrame))
      topLevel = topLevel.getParent();
    return topLevel;
  }

  /**
   * Returns the Hashtable that maps KeyStrokes to Components, for
   * the specified top-level container c.  If no Hashtable exists
   * we create and register it here and return the newly created
   * Hashtable.
   *
   * @param c the top-level container whose Hashtable we want
   * @return the Hashtable mapping KeyStrokes to Components for the
   * specified top-level container
   */
  Hashtable getHashtableForTopLevel (Container c)
  {
    Hashtable keyToComponent = (Hashtable)topLevelLookup.get(c);
    if (keyToComponent == null)
      {
        keyToComponent = new Hashtable();
        topLevelLookup.put(c, keyToComponent);
      }
    return keyToComponent;
  }

  /**
   * Registers a KeyStroke with a Component.  This does not register
   * the KeyStroke to a specific Action.  When searching for a
   * WHEN_IN_FOCUSED_WINDOW binding we will first go up to the focused
   * top-level Container, then get the Hashtable that maps KeyStrokes
   * to components for that particular top-level Container, then
   * call processKeyBindings on that component with the condition
   * JComponent.WHEN_IN_FOCUSED_WINDOW.
   * @param comp the JComponent associated with the KeyStroke
   * @param key the KeyStroke
   */
  public void registerBinding(JComponent comp, KeyStroke key)
  {
    // This method associates a KeyStroke with a particular JComponent
    // When the KeyStroke occurs, if this component's top-level ancestor
    // has focus (one of its children is the focused Component) then
    // comp.processKeyBindings will be called with condition
    // JComponent.WHEN_IN_FOCUSED_WINDOW.

    // Look for the JComponent's top-level parent and return if it is null
    Container topLevel = findTopLevel(comp);
    if (topLevel == null)
      return;

    // Now get the Hashtable for this top-level container
    Hashtable keyToComponent = getHashtableForTopLevel(topLevel);

    // And add the new binding to this Hashtable
    // FIXME: should allow more than one JComponent to be associated
    // with a KeyStroke, in case one of them is disabled
    keyToComponent.put(key, comp);
  }

  public void clearBindingsForComp(JComponent comp)
  {
    // This method clears all the WHEN_IN_FOCUSED_WINDOW bindings associated
    // with <code>comp</code>.  This is used for a terribly ineffcient
    // strategy in which JComponent.updateComponentInputMap simply clears
    // all bindings associated with its component and then reloads all the
    // bindings from the updated ComponentInputMap.  This is only a preliminary
    // strategy and should be improved upon once the WHEN_IN_FOCUSED_WINDOW
    // bindings work.

    // Find the top-level ancestor

    Container topLevel = findTopLevel(comp);
    if (topLevel == null)
      return;
    // And now get its Hashtable
    Hashtable keyToComponent = getHashtableForTopLevel(topLevel);

    Enumeration keys = keyToComponent.keys();
    Object temp;

    // Iterate through the keys and remove any key whose value is comp
    while (keys.hasMoreElements())
      {
        temp = keys.nextElement();
        if (comp == (JComponent)keyToComponent.get(temp))
          keyToComponent.remove(temp);
      }
  }

  /**
   * This method registers all the bindings in the given ComponentInputMap.
   * Rather than call registerBinding on all the keys, we do the work here
   * so that we don't duplicate finding the top-level container and
   * getting its Hashtable.
   *
   * @param map the ComponentInputMap whose bindings we want to register
   */
  public void registerEntireMap (ComponentInputMap map)
  {
    if (map == null)
      return;
    JComponent comp = map.getComponent();
    KeyStroke[] keys = map.allKeys();
    if (keys == null)
      return;
    // Find the top-level container associated with this ComponentInputMap
    Container topLevel = findTopLevel(comp);
    if (topLevel == null)
      return;

    // Register the KeyStrokes in the top-level container's Hashtable
    Hashtable keyToComponent = getHashtableForTopLevel(topLevel);
    for (int i = 0; i < keys.length; i++)
      keyToComponent.put(keys[i], comp);
  }

  public boolean processKeyStroke (Component comp, KeyStroke key, KeyEvent e)
  {
    boolean pressed = e.getID() == KeyEvent.KEY_PRESSED;

    // Look for the top-level ancestor
    Container topLevel = findTopLevel(comp);
    if (topLevel == null)
      return false;
    // Now get the Hashtable for that top-level container
    Hashtable keyToComponent = getHashtableForTopLevel(topLevel);
    Enumeration keys = keyToComponent.keys();
    JComponent target = (JComponent)keyToComponent.get(key);
    if (target != null && target.processKeyBinding
        (key, e, JComponent.WHEN_IN_FOCUSED_WINDOW, pressed))
      return true;

    // Have to give all the JMenuBars a chance to consume the event
    Vector menuBars = getVectorForTopLevel(topLevel);
    for (int i = 0; i < menuBars.size(); i++)
      if (((JMenuBar)menuBars.elementAt(i)).processKeyBinding(key, e, JComponent.WHEN_IN_FOCUSED_WINDOW, pressed))
        return true;
    return false;
  }

  /**
   * Returns the Vector of JMenuBars associated with the top-level
   * @param c the top-level container whose JMenuBar Vector we want
   * @return the Vector of JMenuBars for this top level container
   */
  Vector getVectorForTopLevel(Container c)
  {
    Vector result = (Vector) menuBarLookup.get(c);
    if (result == null)
      {
        result = new Vector();
        menuBarLookup.put (c, result);
      }
    return result;
  }

  /**
   * In processKeyStroke, KeyManager must give all JMenuBars in the
   * focused top-level container a chance to process the event.  So,
   * JMenuBars must be registered in KeyManager and associated with a
   * top-level container.  That's what this method is for.
   * @param menuBar the JMenuBar to register
   */
  public void registerJMenuBar (JMenuBar menuBar)
  {
    Container topLevel = findTopLevel(menuBar);
    Vector menuBars = getVectorForTopLevel(topLevel);
    if (!menuBars.contains(menuBar))
      menuBars.add(menuBar);
  }

  /**
   * Unregisters a JMenuBar from its top-level container.  This is
   * called before the JMenuBar is actually removed from the container
   * so findTopLevel will still find us the correct top-level container.
   * @param menuBar the JMenuBar to unregister.
   */
  public void unregisterJMenuBar (JMenuBar menuBar)
  {
    Container topLevel = findTopLevel(menuBar);
    Vector menuBars = getVectorForTopLevel(topLevel);
    if (menuBars.contains(menuBar))
      menuBars.remove(menuBar);
  }
}
