/ime/latinime/src/com/googlecode/eyesfree/inputmethod/latin/TextEntryState.java

http://eyes-free.googlecode.com/ · Java · 278 lines · 220 code · 35 blank · 23 comment · 48 complexity · 1b183993b22e8274da16ee5e15951613 MD5 · raw file

  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. package com.googlecode.eyesfree.inputmethod.latin;
  17. import android.content.Context;
  18. import android.inputmethodservice.Keyboard.Key;
  19. import android.text.format.DateFormat;
  20. import android.util.Log;
  21. import java.io.FileOutputStream;
  22. import java.io.IOException;
  23. import java.util.Calendar;
  24. public class TextEntryState {
  25. private static final boolean DBG = false;
  26. private static final String TAG = "TextEntryState";
  27. private static boolean LOGGING = false;
  28. private static int sBackspaceCount = 0;
  29. private static int sAutoSuggestCount = 0;
  30. private static int sAutoSuggestUndoneCount = 0;
  31. private static int sManualSuggestCount = 0;
  32. private static int sWordNotInDictionaryCount = 0;
  33. private static int sSessionCount = 0;
  34. private static int sTypedChars;
  35. private static int sActualChars;
  36. public enum State {
  37. UNKNOWN,
  38. START,
  39. IN_WORD,
  40. ACCEPTED_DEFAULT,
  41. PICKED_SUGGESTION,
  42. PUNCTUATION_AFTER_WORD,
  43. PUNCTUATION_AFTER_ACCEPTED,
  44. SPACE_AFTER_ACCEPTED,
  45. SPACE_AFTER_PICKED,
  46. UNDO_COMMIT,
  47. CORRECTING,
  48. PICKED_CORRECTION;
  49. }
  50. private static State sState = State.UNKNOWN;
  51. private static FileOutputStream sKeyLocationFile;
  52. private static FileOutputStream sUserActionFile;
  53. public static void newSession(Context context) {
  54. sSessionCount++;
  55. sAutoSuggestCount = 0;
  56. sBackspaceCount = 0;
  57. sAutoSuggestUndoneCount = 0;
  58. sManualSuggestCount = 0;
  59. sWordNotInDictionaryCount = 0;
  60. sTypedChars = 0;
  61. sActualChars = 0;
  62. sState = State.START;
  63. if (LOGGING) {
  64. try {
  65. sKeyLocationFile = context.openFileOutput("key.txt", Context.MODE_APPEND);
  66. sUserActionFile = context.openFileOutput("action.txt", Context.MODE_APPEND);
  67. } catch (IOException ioe) {
  68. Log.e("TextEntryState", "Couldn't open file for output: " + ioe);
  69. }
  70. }
  71. }
  72. public static void endSession() {
  73. if (sKeyLocationFile == null) {
  74. return;
  75. }
  76. try {
  77. sKeyLocationFile.close();
  78. // Write to log file
  79. // Write timestamp, settings,
  80. String out = DateFormat.format("MM:dd hh:mm:ss", Calendar.getInstance().getTime())
  81. .toString()
  82. + " BS: " + sBackspaceCount
  83. + " auto: " + sAutoSuggestCount
  84. + " manual: " + sManualSuggestCount
  85. + " typed: " + sWordNotInDictionaryCount
  86. + " undone: " + sAutoSuggestUndoneCount
  87. + " saved: " + ((float) (sActualChars - sTypedChars) / sActualChars)
  88. + "\n";
  89. sUserActionFile.write(out.getBytes());
  90. sUserActionFile.close();
  91. sKeyLocationFile = null;
  92. sUserActionFile = null;
  93. } catch (IOException ioe) {
  94. }
  95. }
  96. public static void acceptedDefault(CharSequence typedWord, CharSequence actualWord) {
  97. if (typedWord == null) return;
  98. if (!typedWord.equals(actualWord)) {
  99. sAutoSuggestCount++;
  100. }
  101. sTypedChars += typedWord.length();
  102. sActualChars += actualWord.length();
  103. sState = State.ACCEPTED_DEFAULT;
  104. LatinImeLogger.logOnAutoSuggestion(typedWord.toString(), actualWord.toString());
  105. displayState();
  106. }
  107. // State.ACCEPTED_DEFAULT will be changed to other sub-states
  108. // (see "case ACCEPTED_DEFAULT" in typedCharacter() below),
  109. // and should be restored back to State.ACCEPTED_DEFAULT after processing for each sub-state.
  110. public static void backToAcceptedDefault(CharSequence typedWord) {
  111. if (typedWord == null) return;
  112. switch (sState) {
  113. case SPACE_AFTER_ACCEPTED:
  114. case PUNCTUATION_AFTER_ACCEPTED:
  115. case IN_WORD:
  116. sState = State.ACCEPTED_DEFAULT;
  117. break;
  118. }
  119. displayState();
  120. }
  121. public static void acceptedTyped(CharSequence typedWord) {
  122. sWordNotInDictionaryCount++;
  123. sState = State.PICKED_SUGGESTION;
  124. displayState();
  125. }
  126. public static void acceptedSuggestion(CharSequence typedWord, CharSequence actualWord) {
  127. sManualSuggestCount++;
  128. State oldState = sState;
  129. if (typedWord.equals(actualWord)) {
  130. acceptedTyped(typedWord);
  131. }
  132. if (oldState == State.CORRECTING || oldState == State.PICKED_CORRECTION) {
  133. sState = State.PICKED_CORRECTION;
  134. } else {
  135. sState = State.PICKED_SUGGESTION;
  136. }
  137. displayState();
  138. }
  139. public static void selectedForCorrection() {
  140. sState = State.CORRECTING;
  141. displayState();
  142. }
  143. public static void typedCharacter(char c, boolean isSeparator) {
  144. boolean isSpace = c == ' ';
  145. switch (sState) {
  146. case IN_WORD:
  147. if (isSpace || isSeparator) {
  148. sState = State.START;
  149. } else {
  150. // State hasn't changed.
  151. }
  152. break;
  153. case ACCEPTED_DEFAULT:
  154. case SPACE_AFTER_PICKED:
  155. if (isSpace) {
  156. sState = State.SPACE_AFTER_ACCEPTED;
  157. } else if (isSeparator) {
  158. sState = State.PUNCTUATION_AFTER_ACCEPTED;
  159. } else {
  160. sState = State.IN_WORD;
  161. }
  162. break;
  163. case PICKED_SUGGESTION:
  164. case PICKED_CORRECTION:
  165. if (isSpace) {
  166. sState = State.SPACE_AFTER_PICKED;
  167. } else if (isSeparator) {
  168. // Swap
  169. sState = State.PUNCTUATION_AFTER_ACCEPTED;
  170. } else {
  171. sState = State.IN_WORD;
  172. }
  173. break;
  174. case START:
  175. case UNKNOWN:
  176. case SPACE_AFTER_ACCEPTED:
  177. case PUNCTUATION_AFTER_ACCEPTED:
  178. case PUNCTUATION_AFTER_WORD:
  179. if (!isSpace && !isSeparator) {
  180. sState = State.IN_WORD;
  181. } else {
  182. sState = State.START;
  183. }
  184. break;
  185. case UNDO_COMMIT:
  186. if (isSpace || isSeparator) {
  187. sState = State.ACCEPTED_DEFAULT;
  188. } else {
  189. sState = State.IN_WORD;
  190. }
  191. break;
  192. case CORRECTING:
  193. sState = State.START;
  194. break;
  195. }
  196. displayState();
  197. }
  198. public static void backspace() {
  199. if (sState == State.ACCEPTED_DEFAULT) {
  200. sState = State.UNDO_COMMIT;
  201. sAutoSuggestUndoneCount++;
  202. LatinImeLogger.logOnAutoSuggestionCanceled();
  203. } else if (sState == State.UNDO_COMMIT) {
  204. sState = State.IN_WORD;
  205. }
  206. sBackspaceCount++;
  207. displayState();
  208. }
  209. public static void reset() {
  210. sState = State.START;
  211. displayState();
  212. }
  213. public static State getState() {
  214. if (DBG) {
  215. Log.d(TAG, "Returning state = " + sState);
  216. }
  217. return sState;
  218. }
  219. public static boolean isCorrecting() {
  220. return sState == State.CORRECTING || sState == State.PICKED_CORRECTION;
  221. }
  222. public static void keyPressedAt(Key key, int x, int y) {
  223. if (LOGGING && sKeyLocationFile != null && key.codes[0] >= 32) {
  224. String out =
  225. "KEY: " + (char) key.codes[0]
  226. + " X: " + x
  227. + " Y: " + y
  228. + " MX: " + (key.x + key.width / 2)
  229. + " MY: " + (key.y + key.height / 2)
  230. + "\n";
  231. try {
  232. sKeyLocationFile.write(out.getBytes());
  233. } catch (IOException ioe) {
  234. // TODO: May run out of space
  235. }
  236. }
  237. }
  238. private static void displayState() {
  239. if (DBG) {
  240. Log.d(TAG, "State = " + sState);
  241. }
  242. }
  243. }