/*
 * @(#)KeyPressReleaseListener.java    2.5.0   21 July 2006
 *
 * Copyright 2006
 * College of Computer and Information Science
 * Northeastern University
 * Boston, MA  02115
 *
 * The Java Power Tools software may be used for educational
 * purposes as long as this copyright notice is retained intact
 * at the top of all source files.
 *
 * To discuss possible commercial use of this software, 
 * contact Richard Rasala at Northeastern University, 
 * College of Computer and Information Science,
 * 617-373-2462 or rasala@ccs.neu.edu.
 *
 * The Java Power Tools software has been designed and built
 * in collaboration with Viera Proulx and Jeff Raab.
 *
 * Should this software be modified, the words "Modified from 
 * Original" must be included as a comment below this notice.
 *
 * All publication rights are retained.  This software or its 
 * documentation may not be published in any media either
 * in whole or in part without explicit permission.
 *
 * This software was created with support from Northeastern 
 * University and from NSF grant DUE-9950829.
 */

package edu.neu.ccs.gui;

import edu.neu.ccs.quick.*;
import edu.neu.ccs.util.*;

import java.awt.event.*;

/**
 * <p>The class <code>KeyPressReleaseListener</code>
 * implements a <code>KeyListener</code> that tracks
 * the pressed-released state of keyboard keys.  It
 * is possible to track all key codes from the Java
 * class <code>KeyEvent</code> or to supply a list
 * of which particular key codes to track.</p>
 * 
 * <p>This class makes a best effort to track multiple
 * simultaneous key press situations.  We know however
 * that in some cases the hardware does not deliver
 * the required information to Java if "too many" keys
 * are pressed.  Let us explain.</p>
 * 
 * <p>We have run experiments using a laptop with an
 * external USB keyboard attached.  Here are some of
 * the problems encountered.</p>
 * 
 * <ul>
 *   <li>Some key combinations entered using the
 *       laptop keyboard are detected but the same
 *       key combinations entered from the external
 *       keyboard are not detected.</li>
 *   <li>In tests for the 36 keys 0-9 and A-Z, we have
 *       found that up to 6 keys pressed at once on
 *       the laptop keyboard can be detected but if a
 *       7th key is pressed then it is not detected
 *       until one of the first 6 keys is released.</li>
 *   <li>In the same test using the external keyboard,
 *       the situation is much worse.  If 6 keys are
 *       pressed then Java receives events that signal
 *       that all keys are released.  This is a very
 *       disconcerting bug.</li>
 * </ul>
 * 
 * <p>The bottom line is that software cannot process
 * what the hardware and operating system refuse to
 * deliver as proper and timely events.</p>
 * 
 * <p>Despite these significant issues, we felt that
 * <code>KeyPressReleaseListener</code> is a valuable
 * class for certain student software projects so we
 * have decided to include it in JPT as is.</p>
 *
 * @author  Richard Rasala
 * @version 2.5.0
 * @since   2.5.0
 */
public class KeyPressReleaseListener
    implements KeyListener
{
    /** The structure to maintain the pressed-released state. */
    private BooleanStateArray bsa = null;
    
    
    /**
     * Initializes the internal state structure with all
     * key codes from the KeyEvent class.
     */
    public KeyPressReleaseListener() {
        this(StaticFields.getPublicStaticIntFieldValues(KeyEvent.class));
    }
    
    
    /**
     * Initializes the internal state structure with the
     * given list of key codes which should be a subset
     * of the KeyEvent class key codes.
     * 
     * @param list the list of key codes to track
     */
    public KeyPressReleaseListener(int[] list) {
        bsa = new BooleanStateArray(list);
    }
    
    
    /**
     * Stores the event key code state as true.
     * 
     * @param e the KeyEvent sent to this listener
     */
    public void keyPressed(KeyEvent e) {
        bsa.setState(e.getKeyCode(), true);
    }
    
    
    /**
     * Stores the event key code state as false.
     * 
     * @param e the KeyEvent sent to this listener
     */
    public void keyReleased(KeyEvent e) {
        bsa.setState(e.getKeyCode(), false);
    }
    
    
    /** Does nothing. */
    public void keyTyped(KeyEvent e) {}
    
    
    /**
     * <p>Returns the boolean state of the given key
     * where true = pressed and false = released.</p>
     * 
     * <p>Returns false if the key was not given in
     * the list provided to the constructor
     * since that key is not being tracked.</p>
     * 
     * @param keycode the keycode whose pressed-released
     *    state is being queried
     */
    public boolean getState(int keycode) {
        return bsa.getState(keycode);
    }
    
}
