TextEntryState.java revision ab0ee37f52b87756c6d91aecd508fda821aeb4b6
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package com.android.inputmethod.latin;
18
19import android.util.Log;
20
21public class TextEntryState {
22    private static final String TAG = TextEntryState.class.getSimpleName();
23    private static final boolean DEBUG = false;
24
25    private static final int UNKNOWN = 0;
26    private static final int START = 1;
27    private static final int IN_WORD = 2;
28    private static final int ACCEPTED_DEFAULT = 3;
29    private static final int PICKED_SUGGESTION = 4;
30    private static final int PUNCTUATION_AFTER_WORD = 5;
31    private static final int PUNCTUATION_AFTER_ACCEPTED = 6;
32    private static final int SPACE_AFTER_ACCEPTED = 7;
33    private static final int SPACE_AFTER_PICKED = 8;
34    private static final int UNDO_COMMIT = 9;
35    private static final int RECORRECTING = 10;
36    private static final int PICKED_RECORRECTION = 11;
37
38    private static int sState = UNKNOWN;
39    private static int sPreviousState = UNKNOWN;
40
41    private static void setState(final int newState) {
42        sPreviousState = sState;
43        sState = newState;
44    }
45
46    public static void acceptedDefault(CharSequence typedWord, CharSequence actualWord) {
47        if (typedWord == null) return;
48        setState(ACCEPTED_DEFAULT);
49        LatinImeLogger.logOnAutoSuggestion(typedWord.toString(), actualWord.toString());
50        if (DEBUG)
51            displayState("acceptedDefault", "typedWord", typedWord, "actualWord", actualWord);
52    }
53
54    // State.ACCEPTED_DEFAULT will be changed to other sub-states
55    // (see "case ACCEPTED_DEFAULT" in typedCharacter() below),
56    // and should be restored back to State.ACCEPTED_DEFAULT after processing for each sub-state.
57    public static void backToAcceptedDefault(CharSequence typedWord) {
58        if (typedWord == null) return;
59        switch (sState) {
60        case SPACE_AFTER_ACCEPTED:
61        case PUNCTUATION_AFTER_ACCEPTED:
62        case IN_WORD:
63            setState(ACCEPTED_DEFAULT);
64            break;
65        default:
66            break;
67        }
68        if (DEBUG) displayState("backToAcceptedDefault", "typedWord", typedWord);
69    }
70
71    public static void acceptedTyped(CharSequence typedWord) {
72        setState(PICKED_SUGGESTION);
73        if (DEBUG) displayState("acceptedTyped", "typedWord", typedWord);
74    }
75
76    public static void acceptedSuggestion(CharSequence typedWord, CharSequence actualWord) {
77        if (sState == RECORRECTING || sState == PICKED_RECORRECTION) {
78            setState(PICKED_RECORRECTION);
79        } else {
80            setState(PICKED_SUGGESTION);
81        }
82        if (DEBUG)
83            displayState("acceptedSuggestion", "typedWord", typedWord, "actualWord", actualWord);
84    }
85
86    public static void selectedForRecorrection() {
87        setState(RECORRECTING);
88        if (DEBUG) displayState("selectedForRecorrection");
89    }
90
91    public static void onAbortRecorrection() {
92        if (sState == RECORRECTING || sState == PICKED_RECORRECTION) {
93            setState(START);
94        }
95        if (DEBUG) displayState("onAbortRecorrection");
96    }
97
98    public static void typedCharacter(char c, boolean isSeparator) {
99        final boolean isSpace = (c == ' ');
100        switch (sState) {
101        case IN_WORD:
102            if (isSpace || isSeparator) {
103                setState(START);
104            } else {
105                // State hasn't changed.
106            }
107            break;
108        case ACCEPTED_DEFAULT:
109        case SPACE_AFTER_PICKED:
110        case PUNCTUATION_AFTER_ACCEPTED:
111            if (isSpace) {
112                setState(SPACE_AFTER_ACCEPTED);
113            } else if (isSeparator) {
114                // Swap
115                setState(PUNCTUATION_AFTER_ACCEPTED);
116            } else {
117                setState(IN_WORD);
118            }
119            break;
120        case PICKED_SUGGESTION:
121        case PICKED_RECORRECTION:
122            if (isSpace) {
123                setState(SPACE_AFTER_PICKED);
124            } else if (isSeparator) {
125                // Swap
126                setState(PUNCTUATION_AFTER_ACCEPTED);
127            } else {
128                setState(IN_WORD);
129            }
130            break;
131        case START:
132        case UNKNOWN:
133        case SPACE_AFTER_ACCEPTED:
134        case PUNCTUATION_AFTER_WORD:
135            if (!isSpace && !isSeparator) {
136                setState(IN_WORD);
137            } else {
138                setState(START);
139            }
140            break;
141        case UNDO_COMMIT:
142            if (isSpace || isSeparator) {
143                setState(ACCEPTED_DEFAULT);
144            } else {
145                setState(IN_WORD);
146            }
147            break;
148        case RECORRECTING:
149            setState(START);
150            break;
151        }
152        if (DEBUG) displayState("typedCharacter", "char", c, "isSeparator", isSeparator);
153    }
154
155    public static void backspace() {
156        if (sState == ACCEPTED_DEFAULT) {
157            setState(UNDO_COMMIT);
158            LatinImeLogger.logOnAutoSuggestionCanceled();
159        } else if (sState == UNDO_COMMIT) {
160            setState(IN_WORD);
161        }
162        if (DEBUG) displayState("backspace");
163    }
164
165    public static void reset() {
166        setState(START);
167        if (DEBUG) displayState("reset");
168    }
169
170    public static boolean isAcceptedDefault() {
171        return sState == ACCEPTED_DEFAULT;
172    }
173
174    public static boolean isSpaceAfterPicked() {
175        return sState == SPACE_AFTER_PICKED;
176    }
177
178    public static boolean isUndoCommit() {
179        return sState == UNDO_COMMIT;
180    }
181
182    public static boolean isPunctuationAfterAccepted() {
183        return sState == PUNCTUATION_AFTER_ACCEPTED;
184    }
185
186    public static boolean isRecorrecting() {
187        return sState == RECORRECTING || sState == PICKED_RECORRECTION;
188    }
189
190    public static String getState() {
191        return stateName(sState);
192    }
193
194    private static String stateName(int state) {
195        switch (state) {
196        case START: return "START";
197        case IN_WORD: return "IN_WORD";
198        case ACCEPTED_DEFAULT: return "ACCEPTED_DEFAULT";
199        case PICKED_SUGGESTION: return "PICKED_SUGGESTION";
200        case PUNCTUATION_AFTER_WORD: return "PUNCTUATION_AFTER_WORD";
201        case PUNCTUATION_AFTER_ACCEPTED: return "PUNCTUATION_AFTER_ACCEPTED";
202        case SPACE_AFTER_ACCEPTED: return "SPACE_AFTER_ACCEPTED";
203        case SPACE_AFTER_PICKED: return "SPACE_AFTER_PICKED";
204        case UNDO_COMMIT: return "UNDO_COMMIT";
205        case RECORRECTING: return "RECORRECTING";
206        case PICKED_RECORRECTION: return "PICKED_RECORRECTION";
207        default: return "UNKNOWN";
208        }
209    }
210
211    private static void displayState(String title, Object ... args) {
212        final StringBuilder sb = new StringBuilder(title);
213        sb.append(':');
214        for (int i = 0; i < args.length; i += 2) {
215            sb.append(' ');
216            sb.append(args[i]);
217            sb.append('=');
218            sb.append(args[i+1].toString());
219        }
220        sb.append(" state=");
221        sb.append(stateName(sState));
222        sb.append(" previous=");
223        sb.append(stateName(sPreviousState));
224        Log.d(TAG, sb.toString());
225    }
226}
227