Home | History | Annotate | Download | only in documentsui
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.documentsui;
     18 
     19 import android.graphics.Point;
     20 import android.support.v7.widget.RecyclerView;
     21 import android.view.KeyEvent;
     22 import android.view.MotionEvent;
     23 import android.view.View;
     24 
     25 /**
     26  * Utility code for dealing with MotionEvents.
     27  */
     28 public final class Events {
     29 
     30     /**
     31      * Returns true if event was triggered by a mouse.
     32      */
     33     public static boolean isMouseEvent(MotionEvent e) {
     34         return isMouseType(e.getToolType(0));
     35     }
     36 
     37     /**
     38      * Returns true if event was triggered by a finger or stylus touch.
     39      */
     40     public static boolean isTouchEvent(MotionEvent e) {
     41         return isTouchType(e.getToolType(0));
     42     }
     43 
     44     /**
     45      * Returns true if event was triggered by a mouse.
     46      */
     47     public static boolean isMouseType(int toolType) {
     48         return toolType == MotionEvent.TOOL_TYPE_MOUSE;
     49     }
     50 
     51     /**
     52      * Returns true if event was triggered by a finger or stylus touch.
     53      */
     54     public static boolean isTouchType(int toolType) {
     55         return toolType == MotionEvent.TOOL_TYPE_FINGER
     56                 || toolType == MotionEvent.TOOL_TYPE_STYLUS;
     57     }
     58 
     59     /**
     60      * Returns true if event was triggered by a finger or stylus touch.
     61      */
     62     public static boolean isActionDown(MotionEvent e) {
     63         return e.getActionMasked() == MotionEvent.ACTION_DOWN;
     64     }
     65 
     66     /**
     67      * Returns true if event was triggered by a finger or stylus touch.
     68      */
     69     public static boolean isActionUp(MotionEvent e) {
     70         return e.getActionMasked() == MotionEvent.ACTION_UP;
     71     }
     72 
     73     /**
     74      * Returns true if the shift is pressed.
     75      */
     76     public boolean isShiftPressed(MotionEvent e) {
     77         return hasShiftBit(e.getMetaState());
     78     }
     79 
     80     /**
     81      * Whether or not the given keyCode represents a navigation keystroke (e.g. up, down, home).
     82      *
     83      * @param keyCode
     84      * @return
     85      */
     86     public static boolean isNavigationKeyCode(int keyCode) {
     87         switch (keyCode) {
     88             case KeyEvent.KEYCODE_DPAD_UP:
     89             case KeyEvent.KEYCODE_DPAD_DOWN:
     90             case KeyEvent.KEYCODE_DPAD_LEFT:
     91             case KeyEvent.KEYCODE_DPAD_RIGHT:
     92             case KeyEvent.KEYCODE_MOVE_HOME:
     93             case KeyEvent.KEYCODE_MOVE_END:
     94             case KeyEvent.KEYCODE_PAGE_UP:
     95             case KeyEvent.KEYCODE_PAGE_DOWN:
     96                 return true;
     97             default:
     98                 return false;
     99         }
    100     }
    101 
    102 
    103     /**
    104      * Returns true if the "SHIFT" bit is set.
    105      */
    106     public static boolean hasShiftBit(int metaState) {
    107         return (metaState & KeyEvent.META_SHIFT_ON) != 0;
    108     }
    109 
    110     /**
    111      * A facade over MotionEvent primarily designed to permit for unit testing
    112      * of related code.
    113      */
    114     public interface InputEvent {
    115         boolean isMouseEvent();
    116         boolean isPrimaryButtonPressed();
    117         boolean isSecondaryButtonPressed();
    118         boolean isShiftKeyDown();
    119 
    120         /** Returns true if the action is the initial press of a mouse or touch. */
    121         boolean isActionDown();
    122 
    123         /** Returns true if the action is the final release of a mouse or touch. */
    124         boolean isActionUp();
    125 
    126         Point getOrigin();
    127 
    128         /** Returns true if the there is an item under the finger/cursor. */
    129         boolean isOverItem();
    130 
    131         /** Returns the adapter position of the item under the finger/cursor. */
    132         int getItemPosition();
    133     }
    134 
    135     public static final class MotionInputEvent implements InputEvent {
    136         private final MotionEvent mEvent;
    137         private final int mPosition;
    138 
    139         public MotionInputEvent(MotionEvent event, RecyclerView view) {
    140             mEvent = event;
    141 
    142             // Consider determining position lazily as an optimization.
    143             View child = view.findChildViewUnder(mEvent.getX(), mEvent.getY());
    144             mPosition = (child!= null)
    145                     ? view.getChildAdapterPosition(child)
    146                     : RecyclerView.NO_POSITION;
    147         }
    148 
    149         @Override
    150         public boolean isMouseEvent() {
    151             return Events.isMouseEvent(mEvent);
    152         }
    153 
    154         @Override
    155         public boolean isPrimaryButtonPressed() {
    156             return mEvent.isButtonPressed(MotionEvent.BUTTON_PRIMARY);
    157         }
    158 
    159         @Override
    160         public boolean isSecondaryButtonPressed() {
    161             return mEvent.isButtonPressed(MotionEvent.BUTTON_SECONDARY);
    162         }
    163 
    164         @Override
    165         public boolean isShiftKeyDown() {
    166             return Events.hasShiftBit(mEvent.getMetaState());
    167         }
    168 
    169         @Override
    170         public boolean isActionDown() {
    171             return mEvent.getActionMasked() == MotionEvent.ACTION_DOWN;
    172         }
    173 
    174         @Override
    175         public boolean isActionUp() {
    176             return mEvent.getActionMasked() == MotionEvent.ACTION_UP;
    177         }
    178 
    179         @Override
    180         public Point getOrigin() {
    181             return new Point((int) mEvent.getX(), (int) mEvent.getY());
    182         }
    183 
    184         @Override
    185         public boolean isOverItem() {
    186             return getItemPosition() != RecyclerView.NO_POSITION;
    187         }
    188 
    189         @Override
    190         public int getItemPosition() {
    191             return mPosition;
    192         }
    193 
    194         @Override
    195         public String toString() {
    196             return new StringBuilder()
    197                     .append("MotionInputEvent {")
    198                     .append("isMouseEvent=").append(isMouseEvent())
    199                     .append(" isPrimaryButtonPressed=").append(isPrimaryButtonPressed())
    200                     .append(" isSecondaryButtonPressed=").append(isSecondaryButtonPressed())
    201                     .append(" isShiftKeyDown=").append(isShiftKeyDown())
    202                     .append(" isActionDown=").append(isActionDown())
    203                     .append(" isActionUp=").append(isActionUp())
    204                     .append(" getOrigin=").append(getOrigin())
    205                     .append(" isOverItem=").append(isOverItem())
    206                     .append(" getItemPosition=").append(getItemPosition())
    207                     .append("}")
    208                     .toString();
    209         }
    210     }
    211 }
    212