aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/keyboard/internal/GestureTracker.java
blob: 0f14dcef4b53e84cc062e3077d8217683c7e3b51 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed 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 com.android.inputmethod.keyboard.internal;

import android.util.Log;

import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardActionListener;
import com.android.inputmethod.keyboard.PointerTracker;
import com.android.inputmethod.latin.InputPointers;
import com.android.inputmethod.latin.SuggestedWords;

// TODO: Remove this class by consolidating with PointerTracker
public class GestureTracker {
    private static final String TAG = GestureTracker.class.getSimpleName();
    private static final boolean DEBUG_LISTENER = false;

    // TODO: There should be an option to turn on/off the gesture input.
    private static final boolean GESTURE_ON = true;

    private static final GestureTracker sInstance = new GestureTracker();

    private static final int MIN_RECOGNITION_TIME = 100;

    private boolean mIsAlphabetKeyboard;
    private boolean mIsPossibleGesture = false;
    private boolean mInGesture = false;

    private KeyboardActionListener mListener;
    private SuggestedWords mSuggestions;

    private int mLastRecognitionPointSize = 0;
    private long mLastRecognitionTime = 0;

    public static void init(KeyboardActionListener listner) {
        sInstance.mListener = listner;
    }

    public static GestureTracker getInstance() {
        return sInstance;
    }

    private GestureTracker() {
    }

    public void setKeyboard(Keyboard keyboard) {
        mIsAlphabetKeyboard = keyboard.mId.isAlphabetKeyboard();
    }

    private void startBatchInput() {
        if (DEBUG_LISTENER) {
            Log.d(TAG, "onStartBatchInput");
        }
        mInGesture = true;
        mListener.onStartBatchInput();
        mSuggestions = null;
    }

    // TODO: The corresponding startBatchInput() is a private method. Reorganize the code.
    public void endBatchInput() {
        if (isInGesture() && mSuggestions != null && mSuggestions.size() > 0) {
            final CharSequence text = mSuggestions.getWord(0);
            if (DEBUG_LISTENER) {
                Log.d(TAG, "onEndBatchInput: text=" + text);
            }
            mListener.onEndBatchInput(text);
        }
        mInGesture = false;
        clearBatchInputPoints();
    }

    public void abortBatchInput() {
        mIsPossibleGesture = false;
        mInGesture = false;
    }

    public boolean isInGesture() {
        return mInGesture;
    }

    public void onDownEvent(PointerTracker tracker, int x, int y, long eventTime, Key key) {
        mIsPossibleGesture = false;
        // A gesture should start only from the letter key.
        if (GESTURE_ON && mIsAlphabetKeyboard && key != null && Keyboard.isLetterCode(key.mCode)) {
            mIsPossibleGesture = true;
            tracker.getGestureStroke().addPoint(x, y, 0, false);
        }
    }

    public void onMoveEvent(PointerTracker tracker, int x, int y, long eventTime,
            boolean isHistorical, Key key) {
        final int gestureTime = (int)(eventTime - tracker.getDownTime());
        if (GESTURE_ON && mIsPossibleGesture) {
            final GestureStroke stroke = tracker.getGestureStroke();
            stroke.addPoint(x, y, gestureTime, isHistorical);
            if (!isInGesture() && stroke.isStartOfAGesture(gestureTime)) {
                startBatchInput();
            }
        }

        if (key != null && isInGesture()) {
            final InputPointers batchPoints = PointerTracker.getIncrementalBatchPoints();
            if (updateBatchInputRecognitionState(eventTime, batchPoints.getPointerSize())) {
                if (DEBUG_LISTENER) {
                    Log.d(TAG, "onUpdateBatchInput: batchPoints=" + batchPoints.getPointerSize());
                }
                mSuggestions = mListener.onUpdateBatchInput(batchPoints);
            }
        }
    }

    public void onUpEvent(PointerTracker tracker, int x, int y, long eventTime) {
        if (isInGesture()) {
            final InputPointers batchPoints = PointerTracker.getAllBatchPoints();
            if (DEBUG_LISTENER) {
                Log.d(TAG, "onUpdateBatchInput: batchPoints=" + batchPoints.getPointerSize());
            }
            mSuggestions = mListener.onUpdateBatchInput(batchPoints);
        }
    }

    private void clearBatchInputPoints() {
        PointerTracker.clearBatchInputPoints();
        mLastRecognitionPointSize = 0;
        mLastRecognitionTime = 0;
    }

    private boolean updateBatchInputRecognitionState(long eventTime, int size) {
        if (size > mLastRecognitionPointSize
                && eventTime > mLastRecognitionTime + MIN_RECOGNITION_TIME) {
            mLastRecognitionPointSize = size;
            mLastRecognitionTime = eventTime;
            return true;
        }
        return false;
    }
}