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:
Walter Korman
2001-12-12 16:55:06 +00:00
parent 3af0d8b1ee
commit 0432219e99
3 changed files with 407 additions and 0 deletions
@@ -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;
}