Home | History | Annotate | Download | only in keyboard
      1 /*
      2  * Copyright (C) 2010 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.inputmethod.keyboard;
     18 
     19 import com.android.inputmethod.latin.Constants;
     20 
     21 
     22 public class KeyDetector {
     23     private final int mKeyHysteresisDistanceSquared;
     24     private final int mKeyHysteresisDistanceForSlidingModifierSquared;
     25 
     26     private Keyboard mKeyboard;
     27     private int mCorrectionX;
     28     private int mCorrectionY;
     29 
     30     /**
     31      * This class handles key detection.
     32      *
     33      * @param keyHysteresisDistance if the pointer movement distance is smaller than this, the
     34      * movement will not be handled as meaningful movement. The unit is pixel.
     35      */
     36     public KeyDetector(float keyHysteresisDistance) {
     37         this(keyHysteresisDistance, keyHysteresisDistance);
     38     }
     39 
     40     /**
     41      * This class handles key detection.
     42      *
     43      * @param keyHysteresisDistance if the pointer movement distance is smaller than this, the
     44      * movement will not be handled as meaningful movement. The unit is pixel.
     45      * @param keyHysteresisDistanceForSlidingModifier the same parameter for sliding input that
     46      * starts from a modifier key such as shift and symbols key.
     47      */
     48     public KeyDetector(float keyHysteresisDistance, float keyHysteresisDistanceForSlidingModifier) {
     49         mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
     50         mKeyHysteresisDistanceForSlidingModifierSquared = (int)(
     51                 keyHysteresisDistanceForSlidingModifier * keyHysteresisDistanceForSlidingModifier);
     52     }
     53 
     54     public void setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
     55         if (keyboard == null) {
     56             throw new NullPointerException();
     57         }
     58         mCorrectionX = (int)correctionX;
     59         mCorrectionY = (int)correctionY;
     60         mKeyboard = keyboard;
     61     }
     62 
     63     public int getKeyHysteresisDistanceSquared(boolean isSlidingFromModifier) {
     64         return isSlidingFromModifier
     65                 ? mKeyHysteresisDistanceForSlidingModifierSquared : mKeyHysteresisDistanceSquared;
     66     }
     67 
     68     public int getTouchX(int x) {
     69         return x + mCorrectionX;
     70     }
     71 
     72     // TODO: Remove vertical correction.
     73     public int getTouchY(int y) {
     74         return y + mCorrectionY;
     75     }
     76 
     77     public Keyboard getKeyboard() {
     78         if (mKeyboard == null) {
     79             throw new IllegalStateException("keyboard isn't set");
     80         }
     81         return mKeyboard;
     82     }
     83 
     84     public boolean alwaysAllowsSlidingInput() {
     85         return false;
     86     }
     87 
     88     /**
     89      * Detect the key whose hitbox the touch point is in.
     90      *
     91      * @param x The x-coordinate of a touch point
     92      * @param y The y-coordinate of a touch point
     93      * @return the key that the touch point hits.
     94      */
     95     public Key detectHitKey(int x, int y) {
     96         final int touchX = getTouchX(x);
     97         final int touchY = getTouchY(y);
     98 
     99         int minDistance = Integer.MAX_VALUE;
    100         Key primaryKey = null;
    101         for (final Key key: mKeyboard.getNearestKeys(touchX, touchY)) {
    102             // An edge key always has its enlarged hitbox to respond to an event that occurred in
    103             // the empty area around the key. (@see Key#markAsLeftEdge(KeyboardParams)} etc.)
    104             if (!key.isOnKey(touchX, touchY)) {
    105                 continue;
    106             }
    107             final int distance = key.squaredDistanceToEdge(touchX, touchY);
    108             if (distance > minDistance) {
    109                 continue;
    110             }
    111             // To take care of hitbox overlaps, we compare key's code here too.
    112             if (primaryKey == null || distance < minDistance
    113                     || key.getCode() > primaryKey.getCode()) {
    114                 minDistance = distance;
    115                 primaryKey = key;
    116             }
    117         }
    118         return primaryKey;
    119     }
    120 
    121     public static String printableCode(Key key) {
    122         return key != null ? Constants.printableCode(key.getCode()) : "none";
    123     }
    124 
    125     public static String printableCodes(int[] codes) {
    126         final StringBuilder sb = new StringBuilder();
    127         boolean addDelimiter = false;
    128         for (final int code : codes) {
    129             if (code == Constants.NOT_A_CODE) break;
    130             if (addDelimiter) sb.append(", ");
    131             sb.append(Constants.printableCode(code));
    132             addDelimiter = true;
    133         }
    134         return "[" + sb + "]";
    135     }
    136 }
    137