Added row at top of board to show floating block entry and killing piece
placement. Went back to not allowing the player to be killed by shaft pieces. Initial work on improved keyboard input. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@755 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// $Id: KeyTranslator.java,v 1.1 2001/12/12 16:55:06 shaper Exp $
|
||||
|
||||
package com.threerings.yohoho.puzzle.util;
|
||||
|
||||
/**
|
||||
* The key translator interface provides a means whereby the keyboard
|
||||
* manager can map a key code to the logical {@link
|
||||
* com.samskivert.swing.Controller} action command that it represents.
|
||||
*/
|
||||
public interface KeyTranslator
|
||||
{
|
||||
/**
|
||||
* Returns whether there is an action command for the key
|
||||
* corresponding to the given keycode. The translator may have a
|
||||
* mapping for an action command for a key press or a key release of
|
||||
* the key, or both.
|
||||
*/
|
||||
public boolean hasCommand (int keyCode);
|
||||
|
||||
/**
|
||||
* Returns the action command string associated with a key press of
|
||||
* the key corresponding to the given key code, or <code>null</code>
|
||||
* if there is no associated command.
|
||||
*/
|
||||
public String getPressCommand (int keyCode);
|
||||
|
||||
/**
|
||||
* Returns the action command string associated with a key release of
|
||||
* the key corresponding to the given key code, or <code>null</code>
|
||||
* if there is no associated command.
|
||||
*/
|
||||
public String getReleaseCommand (int keyCode);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// $Id: KeyTranslatorImpl.java,v 1.1 2001/12/12 16:55:06 shaper Exp $
|
||||
|
||||
package com.threerings.yohoho.puzzle.util;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
|
||||
/**
|
||||
* A simple implementation of the {@link KeyTranslator} interface that
|
||||
* provides facilities for mapping key codes to action command strings for
|
||||
* use by the {@link KeyboardManager}.
|
||||
*/
|
||||
public class KeyTranslatorImpl implements KeyTranslator
|
||||
{
|
||||
/**
|
||||
* Adds a mapping from key press to action command string.
|
||||
*/
|
||||
public void addPressCommand (int keyCode, String command)
|
||||
{
|
||||
_press.put(keyCode, command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a mapping from key release to action command string.
|
||||
*/
|
||||
public void addReleaseCommand (int keyCode, String command)
|
||||
{
|
||||
_release.put(keyCode, command);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public boolean hasCommand (int keyCode)
|
||||
{
|
||||
return (_press.get(keyCode) != null ||
|
||||
_release.get(keyCode) != null);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public String getPressCommand (int keyCode)
|
||||
{
|
||||
return (String)_press.get(keyCode);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public String getReleaseCommand (int keyCode)
|
||||
{
|
||||
return (String)_release.get(keyCode);
|
||||
}
|
||||
|
||||
/** The mapping for key presses from key codes to action commands. */
|
||||
protected HashIntMap _press = new HashIntMap();
|
||||
|
||||
/** The mapping for key releases from key codes to action commands. */
|
||||
protected HashIntMap _release = new HashIntMap();
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
//
|
||||
// $Id: KeyboardManager.java,v 1.1 2001/12/12 16:55:06 shaper Exp $
|
||||
|
||||
package com.threerings.yohoho.puzzle.util;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.swing.Controller;
|
||||
import com.samskivert.util.HashIntMap;
|
||||
import com.samskivert.util.Interval;
|
||||
import com.samskivert.util.IntervalManager;
|
||||
|
||||
import com.threerings.yohoho.Log;
|
||||
|
||||
/**
|
||||
* The keyboard manager observes keyboard actions on a particular
|
||||
* component and posts commands associated with the key presses to the
|
||||
* {@link Controller} hierarchy. It allows specifying the key repeat
|
||||
* rate, and will begin repeating a key immediately after it is held down
|
||||
* rather than depending on the system-specific key repeat delay/rate.
|
||||
*/
|
||||
public class KeyboardManager implements KeyListener
|
||||
{
|
||||
/**
|
||||
* Constructs a keyboard manager.
|
||||
*
|
||||
* @param target the component whose keyboard events are to be observed.
|
||||
* @param xlate the key translator used to map keyboard events to
|
||||
* controller action commands.
|
||||
*/
|
||||
public KeyboardManager (Component target, KeyTranslator xlate)
|
||||
{
|
||||
// save off references
|
||||
_target = target;
|
||||
_xlate = xlate;
|
||||
|
||||
// listen to key events
|
||||
target.addKeyListener(this);
|
||||
|
||||
// listen to focus events so that we can cease repeating if we
|
||||
// lose focus
|
||||
target.addFocusListener(new FocusAdapter() {
|
||||
public void focusLost (FocusEvent e) {
|
||||
releaseAllKeys();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the expected delay in milliseconds between each key
|
||||
* press/release event the keyboard manager should expect to receive
|
||||
* while a key is repeating.
|
||||
*/
|
||||
public void setRepeatDelay (long delay)
|
||||
{
|
||||
_repeatDelay = delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the delay in milliseconds between each repeat key action
|
||||
* command posted by the keyboard manager while a key is down.
|
||||
*/
|
||||
public void setPressDelay (long delay)
|
||||
{
|
||||
_pressDelay = delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all keys and ceases any hot repeating action that may be
|
||||
* going on.
|
||||
*/
|
||||
public void releaseAllKeys ()
|
||||
{
|
||||
Iterator iter = _keys.elements();
|
||||
while (iter.hasNext()) {
|
||||
((KeyInfo)iter.next()).release();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void keyPressed (KeyEvent e)
|
||||
{
|
||||
// logKey("keyPressed", e);
|
||||
|
||||
// get the action command associated with this key
|
||||
int keyCode = e.getKeyCode();
|
||||
if (_xlate.hasCommand(keyCode)) {
|
||||
// get the info object for this key, creating one if necessary
|
||||
KeyInfo info = (KeyInfo)_keys.get(keyCode);
|
||||
if (info == null) {
|
||||
info = new KeyInfo(keyCode);
|
||||
_keys.put(keyCode, info);
|
||||
}
|
||||
|
||||
// remember the last time this key was pressed
|
||||
info.setPressTime(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void keyReleased (KeyEvent e)
|
||||
{
|
||||
// logKey("keyReleased", e);
|
||||
|
||||
// get the info object for this key
|
||||
KeyInfo info = (KeyInfo)_keys.get(e.getKeyCode());
|
||||
if (info == null) {
|
||||
// Log.warning("Received key released event for a key that " +
|
||||
// "seems not to have been previously pressed " +
|
||||
// "[e=" + e + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// remember the last time we received a key release
|
||||
info.setReleaseTime(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void keyTyped (KeyEvent e)
|
||||
{
|
||||
// logKey("keyTyped", e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the given message and key.
|
||||
*/
|
||||
protected void logKey (String msg, KeyEvent e)
|
||||
{
|
||||
int keyCode = e.getKeyCode();
|
||||
Log.info(msg + " [key=" + KeyEvent.getKeyText(keyCode) + "].");
|
||||
}
|
||||
|
||||
protected class KeyInfo implements Interval
|
||||
{
|
||||
/**
|
||||
* Constructs a key info object for the given key code.
|
||||
*/
|
||||
public KeyInfo (int keyCode)
|
||||
{
|
||||
_keyCode = keyCode;
|
||||
_keyText = KeyEvent.getKeyText(_keyCode);
|
||||
_pressCommand = _xlate.getPressCommand(_keyCode);
|
||||
_releaseCommand = _xlate.getReleaseCommand(_keyCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last time the key was pressed.
|
||||
*/
|
||||
public synchronized void setPressTime (long time)
|
||||
{
|
||||
_lastPress = time;
|
||||
_lastRelease = time;
|
||||
|
||||
if (_iid == -1) {
|
||||
// register an interval to post the command associated
|
||||
// with the key press until the key is decidedly released
|
||||
_iid = IntervalManager.register(this, _pressDelay, null, true);
|
||||
|
||||
// post the initial key press command if applicable
|
||||
if (_pressCommand != null) {
|
||||
Controller.postAction(_target, _pressCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last time the key was released.
|
||||
*/
|
||||
public synchronized void setReleaseTime (long time)
|
||||
{
|
||||
_lastRelease = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the key if pressed and cancels any active key repeat
|
||||
* interval.
|
||||
*/
|
||||
public synchronized void release ()
|
||||
{
|
||||
Log.info("Releasing key [key=" + _keyText + "].");
|
||||
|
||||
// remove the sub-interval, if any
|
||||
if (_siid != -1) {
|
||||
IntervalManager.remove(_siid);
|
||||
_siid = -1;
|
||||
}
|
||||
|
||||
// remove the repeat interval
|
||||
if (_iid != -1) {
|
||||
IntervalManager.remove(_iid);
|
||||
_iid = -1;
|
||||
}
|
||||
|
||||
// post the key release command if applicable
|
||||
if (_releaseCommand != null) {
|
||||
Controller.postAction(_target, _releaseCommand);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public synchronized void intervalExpired (int id, Object arg)
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
long deltaRelease = now - _lastRelease;
|
||||
|
||||
// Log.info("intervalExpired [id=" + id +
|
||||
// ", key=" + _keyText +
|
||||
// ", deltaPress=" + (now - _lastPress) +
|
||||
// ", deltaRelease=" + deltaRelease + "].");
|
||||
|
||||
if (id == _iid) {
|
||||
// handle a normal interval where we either (a) create a
|
||||
// sub-interval if we can't yet determine definitively
|
||||
// whether the key is still down, (b) cease repeating if
|
||||
// we're certain the key is now up, or (c) repeat the key
|
||||
// command if we're certain the key is still down
|
||||
if (_lastRelease != _lastPress) {
|
||||
if (deltaRelease < _repeatDelay) {
|
||||
// register a one-shot sub-interval to
|
||||
// definitively check whether the key was released
|
||||
Log.info("Registering sub-interval to check key " +
|
||||
"release.");
|
||||
long delay = _repeatDelay - deltaRelease;
|
||||
_siid = IntervalManager.register(
|
||||
this, delay, null, false);
|
||||
|
||||
} else {
|
||||
// we know the key was released, so cease repeating
|
||||
release();
|
||||
}
|
||||
|
||||
} else if (_pressCommand != null) {
|
||||
// post the key press command again
|
||||
Log.info("Repeating command [cmd=" + _pressCommand + "].");
|
||||
Controller.postAction(_target, _pressCommand);
|
||||
}
|
||||
|
||||
} else if (id == _siid) {
|
||||
// clear out the non-recurring sub-interval identifier
|
||||
_siid = -1;
|
||||
|
||||
// provide the last word on whether the key was released
|
||||
if ((_lastRelease != _lastPress) &&
|
||||
deltaRelease >= _repeatDelay) {
|
||||
release();
|
||||
|
||||
} else if (_pressCommand != null) {
|
||||
// post the key command again
|
||||
Log.info("Repeating command [cmd=" + _pressCommand + "].");
|
||||
Controller.postAction(_target, _pressCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the key info object.
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
return "[key=" + _keyText + "]";
|
||||
}
|
||||
|
||||
/** The unique interval identifier for the sub-interval used to
|
||||
* handle the case where the main interval wakes up to repeat the
|
||||
* currently pressed key and the last key release event was
|
||||
* received more recently than the expected repeat delay. */
|
||||
protected int _siid = -1;
|
||||
|
||||
/** The unique interval identifier for the key repeat interval. */
|
||||
protected int _iid = -1;
|
||||
|
||||
/** The last time a key released event was received for this key. */
|
||||
protected long _lastRelease;
|
||||
|
||||
/** The last time a key pressed event was received for this key. */
|
||||
protected long _lastPress;
|
||||
|
||||
/** The press action command associated with this key. */
|
||||
protected String _pressCommand;
|
||||
|
||||
/** The release action command associated with this key. */
|
||||
protected String _releaseCommand;
|
||||
|
||||
/** A text representation of this key. */
|
||||
protected String _keyText;
|
||||
|
||||
/** The key code associated with this key info object. */
|
||||
protected int _keyCode;
|
||||
}
|
||||
|
||||
/** The default repeat delay. */
|
||||
protected static final long DEFAULT_REPEAT_DELAY = 50L;
|
||||
|
||||
/** The default key press delay. */
|
||||
protected static final long DEFAULT_PRESS_DELAY = 200L;
|
||||
|
||||
/** The expected approximate milliseconds between each key
|
||||
* release/press event while the key is being auto-repeated. */
|
||||
protected long _repeatDelay = DEFAULT_REPEAT_DELAY;
|
||||
|
||||
/** The milliseconds to sleep between sending repeat key commands. */
|
||||
protected long _pressDelay = DEFAULT_PRESS_DELAY;
|
||||
|
||||
/** A hashtable mapping key codes to {@link KeyInfo} objects. */
|
||||
protected HashIntMap _keys = new HashIntMap();
|
||||
|
||||
/** The component that receives keyboard events and that we associate
|
||||
* with posted controller commands. */
|
||||
protected Component _target;
|
||||
|
||||
/** The translator that maps keyboard events to controller commands. */
|
||||
protected KeyTranslator _xlate;
|
||||
}
|
||||
Reference in New Issue
Block a user