Package bs

Source Code of bs.InputManager

package bs;

import java.awt.AWTException;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.SwingUtilities;
import javax.swing.Timer;

/**
* The InputManager manages input of key and mouse events.
* <p>
* Het gegoochel met de release timers is nodig vanwege een bug in de key events
* op Linux. Bij ingedrukt houden van een toets stuurt het systeem telkens naast
* de verwachte keyPressed ook een keyReleased event. Het blijkt dat het
* released event het pressed event voorafgaat, en wel 0-5 millisec. De kern van
* de workaround is dan om na een released event te wachten op een eventueel
* volgend pressed event. Als dit pressed event niet komt binnen enkele
* milliseconden dan nemen we het released event serieus.
* <p>
* Deze class implementeert deze oplossing als volgt. De keyReleased handler
* start een timer voor een specifieke toets, met een actionhandler voor als de
* timer afgaat. De keyPressed handler stopt de timer, mits deze bestaat voor de
* betreffende toets. Dit zorgt er dan voor dat de timer de actionhandler niet
* activeert, waarmee het vorige onterechte released event genegeerd wordt.
*/
public class InputManager implements KeyListener, MouseListener,
    MouseMotionListener, MouseWheelListener {
  /**
   * An invisible cursor.
   */
  public static final Cursor INVISIBLE_CURSOR = Toolkit.getDefaultToolkit()
      .createCustomCursor(Toolkit.getDefaultToolkit().getImage(""),
          new Point(0, 0), "invisible");

  // mouse codes
  public static final int MOUSE_MOVE_LEFT = 0;
  public static final int MOUSE_MOVE_RIGHT = 1;
  public static final int MOUSE_MOVE_UP = 2;
  public static final int MOUSE_MOVE_DOWN = 3;
  public static final int MOUSE_WHEEL_UP = 4;
  public static final int MOUSE_WHEEL_DOWN = 5;
  public static final int MOUSE_BUTTON_1 = 6;
  public static final int MOUSE_BUTTON_2 = 7;
  public static final int MOUSE_BUTTON_3 = 8;

  private static final int NUM_MOUSE_CODES = 9;

  // key codes are defined in java.awt.KeyEvent.
  // most of the codes (except for some rare ones like
  // "alt graph") are less than 600.
  private static final int NUM_KEY_CODES = 600;

  private PressAndHoldKeyGameAction[] keyActions = new PressAndHoldKeyGameAction[NUM_KEY_CODES];
  private PressKeyGameAction[] pressActions = new PressKeyGameAction[NUM_KEY_CODES];
  private GameAction[] mouseActions = new GameAction[NUM_MOUSE_CODES];

  private Timer[] releaseTimers = new Timer[NUM_KEY_CODES];

  private Point mouseLocation;
  private Point centerLocation;
  private Component comp;
  private Robot robot;
  private boolean isRecentering;

  /**
   * Creates a new InputManager that listens to input from the specified
   * component.
   */
  public InputManager(Component comp) {
    this.comp = comp;
    mouseLocation = new Point();
    centerLocation = new Point();

    // register key and mouse listeners
    comp.addKeyListener(this);
    comp.addMouseListener(this);
    comp.addMouseMotionListener(this);
    comp.addMouseWheelListener(this);

    // allow input of the TAB key and other keys normally
    // used for focus traversal
    comp.setFocusTraversalKeysEnabled(false);
  }

  /**
   * Sets the cursor on this InputManager's input component.
   */
  public void setCursor(Cursor cursor) {
    comp.setCursor(cursor);
  }

  /**
   * Sets whether relative mouse mode is on or not. For relative mouse mode,
   * the mouse is "locked" in the center of the screen, and only the changed
   * in mouse movement is measured. In normal mode, the mouse is free to move
   * about the screen.
   */
  public void setRelativeMouseMode(boolean mode) {
    if (mode == isRelativeMouseMode()) {
      return;
    }

    if (mode) {
      try {
        robot = new Robot();
        recenterMouse();
      } catch (AWTException ex) {
        // couldn't create robot!
        robot = null;
      }
    } else {
      robot = null;
    }
  }

  /**
   * Returns whether or not relative mouse mode is on.
   */
  public boolean isRelativeMouseMode() {
    return (robot != null);
  }

  /**
   * Maps a GameAction to a specific key. The key codes are defined in
   * java.awt.KeyEvent. If the key already has a GameAction mapped to it, the
   * new GameAction overwrites it.
   */
  public void mapToKey(PressAndHoldKeyGameAction gameAction, final int keyCode) {
    keyActions[keyCode] = gameAction;

    Timer releaseTimer = new Timer(10, createReleaseActionListener(keyCode));
    releaseTimer.setRepeats(false);
    releaseTimers[keyCode] = releaseTimer;
  }

  public void mapToPress(PressKeyGameAction gameAction, final int keyCode) {
    pressActions[keyCode] = gameAction;
  }

  /**
   * Maps a GameAction to a specific mouse action. The mouse codes are defined
   * here in InputManager (MOUSE_MOVE_LEFT, MOUSE_BUTTON_1, etc). If the mouse
   * action already has a GameAction mapped to it, the new GameAction
   * overwrites it.
   */
  public void mapToMouse(GameAction gameAction, int mouseCode) {
    mouseActions[mouseCode] = gameAction;
  }

  /**
   * Resets all GameActions so they appear like they haven't been pressed.
   */
  public void resetAllGameActions() {
    for (int i = 0; i < keyActions.length; i++) {
      if (keyActions[i] != null) {
        keyActions[i].reset();
      }
    }

    for (int i = 0; i < mouseActions.length; i++) {
      if (mouseActions[i] != null) {
        mouseActions[i].reset();
      }
    }
  }

  /**
   * Gets the name of a key code.
   */
  public static String getKeyName(int keyCode) {
    return KeyEvent.getKeyText(keyCode);
  }

  /**
   * Gets the name of a mouse code.
   */
  public static String getMouseName(int mouseCode) {
    switch (mouseCode) {
    case MOUSE_MOVE_LEFT:
      return "Mouse Left";
    case MOUSE_MOVE_RIGHT:
      return "Mouse Right";
    case MOUSE_MOVE_UP:
      return "Mouse Up";
    case MOUSE_MOVE_DOWN:
      return "Mouse Down";
    case MOUSE_WHEEL_UP:
      return "Mouse Wheel Up";
    case MOUSE_WHEEL_DOWN:
      return "Mouse Wheel Down";
    case MOUSE_BUTTON_1:
      return "Mouse Button 1";
    case MOUSE_BUTTON_2:
      return "Mouse Button 2";
    case MOUSE_BUTTON_3:
      return "Mouse Button 3";
    default:
      return "Unknown mouse code " + mouseCode;
    }
  }

  /**
   * Gets the x position of the mouse.
   */
  public int getMouseX() {
    return mouseLocation.x;
  }

  /**
   * Gets the y position of the mouse.
   */
  public int getMouseY() {
    return mouseLocation.y;
  }

  /**
   * Uses the Robot class to try to position the mouse in the center of the
   * screen.
   * <p>
   * Note that use of the Robot class may not be available on all platforms.
   */
  private synchronized void recenterMouse() {
    if (robot != null && comp.isShowing()) {
      centerLocation.x = comp.getWidth() / 2;
      centerLocation.y = comp.getHeight() / 2;
      SwingUtilities.convertPointToScreen(centerLocation, comp);
      isRecentering = true;
      robot.mouseMove(centerLocation.x, centerLocation.y);
    }
  }

  private PressAndHoldKeyGameAction getKeyAction(int keyCode) {
    if (keyCode < keyActions.length) {
      return keyActions[keyCode];
    } else {
      return null;
    }
  }

  private PressKeyGameAction getPressAction(int keyCode) {
    if (keyCode < pressActions.length) {
      return pressActions[keyCode];
    } else {
      return null;
    }
  }

  private Timer getReleaseTimer(int keyCode) {
    if (keyCode < releaseTimers.length) {
      return releaseTimers[keyCode];
    } else {
      return null;
    }
  }

  /**
   * Gets the mouse code for the button specified in this MouseEvent.
   */
  public static int getMouseButtonCode(MouseEvent e) {
    switch (e.getButton()) {
    case MouseEvent.BUTTON1:
      return MOUSE_BUTTON_1;
    case MouseEvent.BUTTON2:
      return MOUSE_BUTTON_2;
    case MouseEvent.BUTTON3:
      return MOUSE_BUTTON_3;
    default:
      return -1;
    }
  }

  private GameAction getMouseButtonAction(MouseEvent e) {
    int mouseCode = getMouseButtonCode(e);
    if (mouseCode != -1) {
      return mouseActions[mouseCode];
    } else {
      return null;
    }
  }

  private ActionListener createReleaseActionListener(final int keyCode) {
    return new ActionListener() {
      public void actionPerformed(ActionEvent arg0) {
        releaseKey(keyCode);
      }
    };
  }

  private void releaseKey(int keyCode) {
    PressAndHoldKeyGameAction gameAction = getKeyAction(keyCode);
    if (gameAction != null && gameAction.isPressed()) {
      gameAction.release(System.currentTimeMillis());
    }
  }

  public void keyPressed(KeyEvent e) {
    // Press and hold actions
    PressAndHoldKeyGameAction gameAction = getKeyAction(e.getKeyCode());
    if (gameAction != null && !gameAction.isPressed()) {
      gameAction.press(System.currentTimeMillis());
    }

    Timer releaseTimer = getReleaseTimer(e.getKeyCode());
    if (releaseTimer != null) {
      releaseTimer.stop();
    }

    // Press actions
    PressKeyGameAction pressAction=getPressAction(e.getKeyCode());
    if(pressAction!=null){
      pressAction.press();
    }
   
    e.consume();
  }

  public void keyReleased(KeyEvent e) {
    Timer releaseTimer = getReleaseTimer(e.getKeyCode());
    if (releaseTimer != null) {
      releaseTimer.start();
    }
    e.consume();
  }

  public void keyTyped(KeyEvent e) {
    e.consume();
  }

  public void mousePressed(MouseEvent e) {
    GameAction gameAction = getMouseButtonAction(e);
    if (gameAction != null) {
      gameAction.press();
    }

  }

  public void mouseReleased(MouseEvent e) {
    GameAction gameAction = getMouseButtonAction(e);
    if (gameAction != null) {
      gameAction.release();
    }
  }

  public void mouseClicked(MouseEvent e) {
    // do nothing
  }

  public void mouseEntered(MouseEvent e) {
    mouseMoved(e);
  }

  public void mouseExited(MouseEvent e) {
    mouseMoved(e);
  }

  // from the MouseMotionListener interface
  public void mouseDragged(MouseEvent e) {
    mouseMoved(e);
  }

  public synchronized void mouseMoved(MouseEvent e) {
    // this event is from re-centering the mouse - ignore it
    if (isRecentering && centerLocation.x == e.getX()
        && centerLocation.y == e.getY()) {
      isRecentering = false;
    } else {
      int dx = e.getX() - mouseLocation.x;
      int dy = e.getY() - mouseLocation.y;
      mouseHelper(MOUSE_MOVE_LEFT, MOUSE_MOVE_RIGHT, dx);
      mouseHelper(MOUSE_MOVE_UP, MOUSE_MOVE_DOWN, dy);
      if (isRelativeMouseMode()) {
        recenterMouse();
      }
    }

    mouseLocation.x = e.getX();
    mouseLocation.y = e.getY();

  }

  public void mouseWheelMoved(MouseWheelEvent e) {
    mouseHelper(MOUSE_WHEEL_UP, MOUSE_WHEEL_DOWN, e.getWheelRotation());
  }

  private void mouseHelper(int codeNeg, int codePos, int amount) {
    GameAction gameAction;
    if (amount < 0) {
      gameAction = mouseActions[codeNeg];
    } else {
      gameAction = mouseActions[codePos];
    }
    if (gameAction != null) {
      gameAction.press(Math.abs(amount));
      gameAction.release();
    }
  }

}
TOP

Related Classes of bs.InputManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.