Package org.waveprotocol.wave.client.common.util

Source Code of org.waveprotocol.wave.client.common.util.EventWrapper

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.waveprotocol.wave.client.common.util;

import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import org.waveprotocol.wave.client.common.util.UserAgent;

import java.util.HashMap;
import java.util.Map;

/**
* Wraps GWT's events class to give prettier access to event properties.
*
* NOTE(user): we expect a future version of GWT to do this directly on
* their Event class, at which point we can probably deprecate this
* wrapper
*
*/
@SuppressWarnings({ "serial" })
// TODO(danilatos,user): Remove this class, since a lot of this functionality
//     is exposed by GWT's new event system (i.e. NativeEvent).
public class EventWrapper {

  /**
   * The event we are wrapping
   */
  private final Event event;

  /**
   * Modifier values, greater than 16 bits, to add to the keypresses
   * to distinguish them. First shift
   */
  private final static int SHIFT = 1 << 17;

  /**
   * Alt
   */
  private final static int ALT = 1 << 18;

  /**
   * Ctrl
   */
  private final static int CTRL = 1 << 19;

  /**
   * Meta
   */
  private final static int META = 1 << 20;


  /** (Not defined in GWT's KeyCodes) */
  public final static int KEY_INSERT = 45;

  /**
   * Map of keypresses and modifiers to our KeyCombo enum values.
   * http://www.quirksmode.org/js/keys.html has some useful info about this.
   * TODO(danilatos): Implement an IntMap JSO and use that
   */
  private final static Map<Integer, KeyCombo> keyMap =
    new HashMap<Integer, KeyCombo>() {
    {
      // Tab
      put(9,            KeyCombo.TAB);
      put(9 + SHIFT,    KeyCombo.SHIFT_TAB);

      // Space bar
      put(32,                KeyCombo.SPACE);
      put(32 + SHIFT,        KeyCombo.SHIFT_SPACE);
      put(32 + CTRL,         KeyCombo.CTRL_SPACE);
      put(32 + SHIFT + CTRL, KeyCombo.CTRL_SHIFT_SPACE);

      // Escape
      put(KeyCodes.KEY_ESCAPE, KeyCombo.ESC);

      // Enter
      put(KeyCodes.KEY_ENTER, KeyCombo.ENTER);
      put(KeyCodes.KEY_ENTER + SHIFT, KeyCombo.SHIFT_ENTER);
      put(KeyCodes.KEY_ENTER + CTRL, KeyCombo.CTRL_ENTER);

      // Backspace
      put(KeyCodes.KEY_BACKSPACE, KeyCombo.BACKSPACE);
      put(KeyCodes.KEY_BACKSPACE + SHIFT, KeyCombo.SHIFT_BACKSPACE);

      // Delete
      put(KeyCodes.KEY_DELETE, KeyCombo.DELETE);
      put(KeyCodes.KEY_DELETE + SHIFT, KeyCombo.SHIFT_DELETE);

      // Insert
      put(KEY_INSERT, KeyCombo.INSERT);
      put(KEY_INSERT + SHIFT, KeyCombo.SHIFT_INSERT);
      put(KEY_INSERT + CTRL, KeyCombo.CTRL_INSERT);

      // Ctrl-equals
      put('=' + CTRL, KeyCombo.CTRL_EQUALS);

      // Ctrl-alpha combos
      put('B' + CTRL, KeyCombo.CTRL_B);
      put('D' + CTRL, KeyCombo.CTRL_D);
      put('F' + CTRL, KeyCombo.CTRL_F);
      put('I' + CTRL, KeyCombo.CTRL_I);
      put('G' + CTRL, KeyCombo.CTRL_G);
      put('H' + CTRL, KeyCombo.CTRL_H);
      put('K' + CTRL, KeyCombo.CTRL_K);
      put('O' + CTRL, KeyCombo.CTRL_O);
      put('U' + CTRL, KeyCombo.CTRL_U);
      put('W' + CTRL, KeyCombo.CTRL_W);
      put('A' + CTRL, KeyCombo.CTRL_A);
      put('R' + CTRL, KeyCombo.CTRL_R);
      put('E' + CTRL, KeyCombo.CTRL_E);
      put('L' + CTRL, KeyCombo.CTRL_L);

      put('L' + CTRL + SHIFT, KeyCombo.CTRL_SHIFT_L);

      put('F' + CTRL + ALT, KeyCombo.CTRL_ALT_F);
      put('D' + CTRL + ALT, KeyCombo.CTRL_ALT_D);
      put('G' + CTRL + ALT, KeyCombo.CTRL_ALT_G);
      put('S' + CTRL + ALT, KeyCombo.CTRL_ALT_S);

      // Canned responses
      put('!' + CTRL + SHIFT, KeyCombo.CTRL_SHIFT_1);
      put('1' + CTRL + SHIFT, KeyCombo.CTRL_SHIFT_1);
      put('@' + CTRL + SHIFT, KeyCombo.CTRL_SHIFT_2);
      put('2' + CTRL + SHIFT, KeyCombo.CTRL_SHIFT_2);
      put('#' + CTRL + SHIFT, KeyCombo.CTRL_SHIFT_3);
      put('3' + CTRL + SHIFT, KeyCombo.CTRL_SHIFT_3);
      put('%' + CTRL + SHIFT, KeyCombo.CTRL_SHIFT_5);
      put('5' + CTRL + SHIFT, KeyCombo.CTRL_SHIFT_5);

      // Allowable ORDER combos
      // ORDER is the Apple key on OS X and the Ctrl key in Windows and Linux.
      // It is the key modifier used to perform actions such as copy/paste,
      // save, print etc.
      // XXX(user): These override the CTRL/META combos! Fix it!
      {
        final int orderKey = UserAgent.isMac() ? META : CTRL;
        put('A' + orderKey, KeyCombo.ORDER_A);
        put('B' + orderKey, KeyCombo.ORDER_B);
        put('C' + orderKey, KeyCombo.ORDER_C);
        put('D' + orderKey, KeyCombo.ORDER_D);
        put('F' + orderKey, KeyCombo.ORDER_F);
        put('G' + orderKey, KeyCombo.ORDER_G);
        put('I' + orderKey, KeyCombo.ORDER_I);
        put('K' + orderKey, KeyCombo.ORDER_K);
        put('L' + orderKey, KeyCombo.ORDER_L);
        put('N' + orderKey, KeyCombo.ORDER_N);
        put('O' + orderKey, KeyCombo.ORDER_O);
        put('P' + orderKey, KeyCombo.ORDER_P);
        put('R' + orderKey, KeyCombo.ORDER_R);
        put('T' + orderKey, KeyCombo.ORDER_T);
        put('U' + orderKey, KeyCombo.ORDER_U);
        put('V' + orderKey, KeyCombo.ORDER_V);
        put('W' + orderKey, KeyCombo.ORDER_W);
        put('X' + orderKey, KeyCombo.ORDER_X);
        put('Z' + orderKey, KeyCombo.ORDER_Z);
        put('Q' + orderKey, KeyCombo.ORDER_Q);
        put('R' + orderKey + SHIFT, KeyCombo.ORDER_SHIFT_R);
        put('V' + orderKey + SHIFT, KeyCombo.ORDER_SHIFT_V);
        put('K' + orderKey + SHIFT, KeyCombo.ORDER_SHIFT_K);
        put('5' + orderKey + SHIFT, KeyCombo.ORDER_SHIFT_5);

        // Plaintext paste in Safari
        put('V' | orderKey | ALT | SHIFT, KeyCombo.ORDER_ALT_SHIFT_V);
      }

      // Key navigation
      put(KeyCodes.KEY_DOWN,        KeyCombo.DOWN);
      put(KeyCodes.KEY_UP,          KeyCombo.UP);
      put(KeyCodes.KEY_LEFT,        KeyCombo.LEFT);
      put(KeyCodes.KEY_RIGHT,       KeyCombo.RIGHT);
      put(KeyCodes.KEY_PAGEUP,      KeyCombo.PAGE_UP);
      put(KeyCodes.KEY_PAGEDOWN,    KeyCombo.PAGE_DOWN);
      put(KeyCodes.KEY_HOME,        KeyCombo.HOME);
      put(KeyCodes.KEY_END,         KeyCombo.END);

      // Safari key navigation
      // TODO(user): consider using deferred binding
      put(63233, KeyCombo.DOWN);
      put(63232, KeyCombo.UP);
      put(63234, KeyCombo.LEFT);
      put(63235, KeyCombo.RIGHT);
      put(63276, KeyCombo.PAGE_UP);
      put(63277, KeyCombo.PAGE_DOWN);
      put(63273, KeyCombo.HOME);
      put(63275, KeyCombo.END);

      // Meta combos
      put(KeyCodes.KEY_LEFT + META, KeyCombo.META_LEFT);
      put(KeyCodes.KEY_RIGHT + META, KeyCombo.META_RIGHT);
      put(KeyCodes.KEY_HOME + META, KeyCombo.META_HOME);
    }
  };

  /**
   * @return true is even is a submit
   */
  public boolean isSubmit() {
    return event != null && isKeyEvent() && getKeyCombo() == KeyCombo.SHIFT_ENTER;
  }

  /**
   * Constructor
   *
   * @param event
   */
  public EventWrapper(Event event) {
    this.event = event;
  }

  /**
   * @return True if alt key was pressed
   */
  public boolean getAltKey() {
    return DOM.eventGetAltKey(event);
  }

  /**
   * @return The mouse buttons that were depressed as a bit-field, defined
   *    by {@link Event#BUTTON_LEFT}, {@link Event#BUTTON_MIDDLE}, and
   *    {@link Event#BUTTON_RIGHT}
   */
  public int getButton() {
    return DOM.eventGetButton(event);
  }

  /**
   * @return {@link #getKeyCode()} cast to char
   */
  public char getCharCode() {
    return (char) getKeyCode();
  }

  /**
   * @return The mouse x-position within the browser window's client area.
   */
  public int getClientX() {
    return DOM.eventGetClientX(event);
  }

  /**
   * @return The mouse y-position within the browser window's client area.
   */
  public int getClientY() {
    return DOM.eventGetClientY(event);
  }

  /**
   * @return True if ctrl key was pressed
   */
  public boolean getCtrlKey() {
    return DOM.eventGetCtrlKey(event);
  }

  /**
   * @return The current event that is being fired. The current event is only
   * available within the lifetime of the onBrowserEvent function. Once the
   * onBrowserEvent method returns, the current event is reset to null.
   */
  public static EventWrapper getCurrentEvent() {
    Event current = DOM.eventGetCurrentEvent();
    return current != null ?
        new EventWrapper(DOM.eventGetCurrentEvent()) : null;
  }

  /**
   * @return The event's current target element. This is the element
   * whose listener fired last, not the element which fired the event
   * initially.
   */
  public Element getCurrentTarget() {
    return DOM.eventGetCurrentTarget(event);
  }

  /**
   * @return The event
   */
  public Event getEvent() {
    return event;
  }

  /**
   * @return The element from which the mouse pointer was moved
   *    (only valid for {@link Event#ONMOUSEOVER}).
   */
  public static Element getFromElement(Event event) {
    return DOM.eventGetFromElement(event);
  }

  /**
   * @return The key code associated with this event. For
   * {@link Event#ONKEYPRESS}, the Unicode value of the character generated.
   * For {@link Event#ONKEYDOWN} and {@link Event#ONKEYUP}, the code
   * associated with the physical key.
   */
  public int getKeyCode() {
    return getKeyCode(event);
  }

  /**
   * Wrapper for GWT's get[Key Char]Code() that conflates the two values. If
   * there is no keyCode present, it returns charCode instead. This matches the
   * values in {{@link #keyMap} above.
   */
  public static int getKeyCode(Event evt) {
    int keyCode = evt.getKeyCode();
    if (keyCode == 0) {
      keyCode = evt.getCharCode();
    }
    return keyCode;
  }

  /**
   * Semi-deprecated (will be deprecated once event signal has a mechanism for
   * fast switching).
   * @return An encoding of the event's keycode and modifiers
   */
  public KeyCombo getKeyCombo() {
    return getKeyCombo(getKeyCode(), getCtrlKey(), getShiftKey(), getAltKey(), getMetaKey());
  }

  public static KeyCombo getKeyCombo(SignalEvent signal) {
    return getKeyCombo(signal.getKeyCode(), signal.getCtrlKey(),
        signal.getShiftKey(), signal.getAltKey(), signal.getMetaKey());
  }

  /**
   * @return the key-combo representation of the key event.
   */
  public static KeyCombo getKeyCombo(Event evt) {
    return getKeyCombo(getKeyCode(evt), DOM.eventGetCtrlKey(evt),
        DOM.eventGetShiftKey(evt), DOM.eventGetAltKey(evt), DOM.eventGetMetaKey(evt));
  }

  private static KeyCombo getKeyCombo(int keyCode, boolean ctrl, boolean shift, boolean alt,
      boolean meta) {
    int gwtCode = keyCode;
    gwtCode +=
          (ctrl ? CTRL : 0)
        + (shift ? SHIFT : 0)
        + (alt ? ALT : 0) +
        + (meta ? META : 0);
    if (!keyMap.containsKey(gwtCode) && keyCode >= 'a' && keyCode <= 'z') {
      // HACK(danilatos): make it work cross-browser with the event signal updates.
      // get rid of this class soon.
      gwtCode += 'A' - 'a';
    }
    return keyMap.containsKey(gwtCode) ? keyMap.get(gwtCode) : KeyCombo.OTHER;
  }

  /**
   * Converts the parameters to {@link KeyCodes} events to a KeyCombo.
   *
   * @return the key-combo representation of the key event.
   */
  public static KeyCombo getKeyCombo(char keyCode, int modifiers) {
    int gwtCode = keyCode
        + (((modifiers & KeyCodes.KEY_CTRL) != 0) ? CTRL : 0)
        + (((modifiers & KeyCodes.KEY_SHIFT) != 0) ? SHIFT : 0)
        + (((modifiers & KeyCodes.KEY_ALT) != 0) ? ALT : 0);
    return keyMap.containsKey(gwtCode) ? keyMap.get(gwtCode) : KeyCombo.OTHER;
  }

  /**
   * @return True if the metakey was pressed
   */
  public boolean getMetaKey() {
    return DOM.eventGetMetaKey(event);
  }

  /**
   * @return The velocity of the mouse wheel associated with the event
   * along the Y axis.
   */
  public static int getMouseWheelVelocityY(Event event) {
    return DOM.eventGetMouseWheelVelocityY(event);
  }

  /**
   * @return True if this was an auto-repeat event
   */
  public boolean getRepeat() {
    return DOM.eventGetRepeat(event);
  }

  /**
   * @return The mouse x-position on the user's display
   */
  public int getScreenX() {
    return DOM.eventGetScreenX(event);
  }

  /**
   * @return The mouse y-position on the user's display
   */
  public int getScreenY() {
    return DOM.eventGetScreenY(event);
  }

  /**
   * @return True if the shift key was pressed
   */
  public boolean getShiftKey() {
    return DOM.eventGetShiftKey(event);
  }

  /**
   * @return The element that was the actual target of the event.
   */
  public Element getTarget() {
    return DOM.eventGetTarget(event);
  }

  /**
   * @return The element to which the mouse pointer was moved
   * (only valid for {@link Event#ONMOUSEOUT}).
   */
  public static Element getToElement(Event event) {
    return DOM.eventGetToElement(event);
  }

  /**
   * @return The event's type
   */
  public int getType() {
    return DOM.eventGetType(event);
  }

  /**
   * @return true if event type is a focus event
   */
  public boolean isFocusEvent() {
    return (getType() & Event.FOCUSEVENTS) != 0;
  }

  /**
   * @return true if event type is a key event
   */
  public boolean isKeyEvent() {
    return (getType() & Event.KEYEVENTS) != 0;
  }

  /**
   * @return true if event type is a mouse event
   */
  public boolean isMouseEvent() {
    return (getType() & Event.MOUSEEVENTS) != 0;
  }

  /**
   * @return The event's type string
   */
  public String getTypeString() {
    return DOM.eventGetTypeString(event);
  }

  /**
   * Prevents default for current event
   */
  public static void preventCurrentEventDefault() {
    getCurrentEvent().event.preventDefault();
  }

  /**
   * @return A string describing which modifier keys were pressed,
   *        and whether this was a repeat event,  e.g., " shift ctrl"
   */
  @SuppressWarnings("deprecation")
  public static String modifiers(Event event) {
    // repeat is deprecated, but useful for debugging
    return (event.getAltKey() ? " alt" : "")
    + (event.getShiftKey() ? " shift" : "")
    + (event.getCtrlKey() ? " ctrl" : "")
    + (event.getMetaKey() ? " meta" : "")
    + ((event.getTypeInt() == Event.ONKEYDOWN) && event.getRepeat() ? " repeat" : "");
  }

  /**
   * @return A string describing which mouse buttons were pressed,
   *        e.g., " left"
   */
  private static String mouseButtons(Event event) {
    if (event.getButton() == -1) {
      return "";
    } else {
      return ((event.getButton() & Event.BUTTON_LEFT) != 0 ? " left" : "")
          + ((event.getButton() & Event.BUTTON_MIDDLE) != 0 ? " middle" : "")
          + ((event.getButton() & Event.BUTTON_RIGHT) != 0 ? " right" : "");
    }
  }

  /**
   * @return String describing the event's key code, e.g.,
   *    " 64 'a'"
   */
  private static String key(Event event) {
    return " " + event.getKeyCode() + " '" + (char) event.getKeyCode() + "'";
  }

  /**
   * @return A string describing the client x,y position,
   *        e.g., " (100, 100)"
   */
  private static String mousePoint(Event event) {
    return " (" + event.getClientX() + ", " + event.getClientY() + ")";
  }

  @Override
  public String toString() {
    return asString(event);
  }

  public static String asString(Event event) {
    // Start with the event type string
    String string = DOM.eventGetTypeString(event);
    // Next type-specific fields
    switch (event.getTypeInt()) {
    case Event.ONKEYPRESS:
    case Event.ONKEYUP:
    case Event.ONKEYDOWN:
      string += key(event) + modifiers(event);
      break;
    case Event.ONCLICK:
    case Event.ONDBLCLICK:
    case Event.ONMOUSEMOVE:
      string += mousePoint(event) + modifiers(event);
      break;
    case Event.ONMOUSEDOWN:
    case Event.ONMOUSEUP:
      string += mousePoint(event) + mouseButtons(event) + modifiers(event);
      break;
    case Event.ONMOUSEOUT:
      string += mousePoint(event) + modifiers(event) + " to: " + getToElement(event);
      break;
    case Event.ONMOUSEOVER:
      string += mousePoint(event) + modifiers(event) + " from: " + getFromElement(event);
      break;
    case Event.ONMOUSEWHEEL:
      string += " " + getMouseWheelVelocityY(event) + mousePoint(event) + modifiers(event);
      break;
    case Event.ONFOCUS:
    case Event.ONBLUR:
    case Event.ONCHANGE:
    case Event.ONERROR:
    case Event.ONLOAD:
    case Event.ONLOSECAPTURE:
    case Event.ONSCROLL:
      break;
    }
    return string;
  }

  /**
   * In safari, there is X velocity and Y velocity.  GWT code return the combination of the 2.
   * This code only return the Y velocity.
   * @return The y velocity of the mouse event and only the y velocity.
   */
  public static int getMouseWheelVelocityYOnly(Event event) {
    if (!UserAgent.isSafari()) {
      return event.getMouseWheelVelocityY();
    } else {
      return nativeGetMouseWheelVelocityYOnly(event);
    }
  }

  private static native int nativeGetMouseWheelVelocityYOnly(Event evt) /*-{
    // wheelDeltaY is not standard and only available in newer safari
    if (evt.wheelDeltaY == undefined) {
      // The following line is copied from DOMImplSafari.getMouseWheelVelocityY
      return Math.round(-evt.wheelDelta / 40) || 0;
    } else {
      return Math.round(-evt.wheelDeltaY / 40) || 0;
    }
  }-*/;
TOP

Related Classes of org.waveprotocol.wave.client.common.util.EventWrapper

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.