1 /* 2 * Copyright (C) 2008-2009 Google Inc. 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 17 package com.android.inputmethod.latin; 18 19 import java.util.ArrayList; 20 import java.util.List; 21 22 /** 23 * A place to store the currently composing word with information such as adjacent key codes as well 24 */ 25 public class WordComposer { 26 /** 27 * The list of unicode values for each keystroke (including surrounding keys) 28 */ 29 private ArrayList<int[]> mCodes; 30 31 /** 32 * The word chosen from the candidate list, until it is committed. 33 */ 34 private String mPreferredWord; 35 36 private StringBuilder mTypedWord; 37 38 private int mCapsCount; 39 40 private boolean mAutoCapitalized; 41 42 /** 43 * Whether the user chose to capitalize the word. 44 */ 45 private boolean mIsCapitalized; 46 47 WordComposer() { 48 mCodes = new ArrayList<int[]>(12); 49 mTypedWord = new StringBuilder(20); 50 } 51 52 /** 53 * Clear out the keys registered so far. 54 */ 55 public void reset() { 56 mCodes.clear(); 57 mIsCapitalized = false; 58 mPreferredWord = null; 59 mTypedWord.setLength(0); 60 mCapsCount = 0; 61 } 62 63 /** 64 * Number of keystrokes in the composing word. 65 * @return the number of keystrokes 66 */ 67 public int size() { 68 return mCodes.size(); 69 } 70 71 /** 72 * Returns the codes at a particular position in the word. 73 * @param index the position in the word 74 * @return the unicode for the pressed and surrounding keys 75 */ 76 public int[] getCodesAt(int index) { 77 return mCodes.get(index); 78 } 79 80 /** 81 * Add a new keystroke, with codes[0] containing the pressed key's unicode and the rest of 82 * the array containing unicode for adjacent keys, sorted by reducing probability/proximity. 83 * @param codes the array of unicode values 84 */ 85 public void add(int primaryCode, int[] codes) { 86 mTypedWord.append((char) primaryCode); 87 correctPrimaryJuxtapos(primaryCode, codes); 88 mCodes.add(codes); 89 if (Character.isUpperCase((char) primaryCode)) mCapsCount++; 90 } 91 92 /** 93 * Swaps the first and second values in the codes array if the primary code is not the first 94 * value in the array but the second. This happens when the preferred key is not the key that 95 * the user released the finger on. 96 * @param primaryCode the preferred character 97 * @param codes array of codes based on distance from touch point 98 */ 99 private void correctPrimaryJuxtapos(int primaryCode, int[] codes) { 100 if (codes.length < 2) return; 101 if (codes[0] > 0 && codes[1] > 0 && codes[0] != primaryCode && codes[1] == primaryCode) { 102 codes[1] = codes[0]; 103 codes[0] = primaryCode; 104 } 105 } 106 107 /** 108 * Delete the last keystroke as a result of hitting backspace. 109 */ 110 public void deleteLast() { 111 mCodes.remove(mCodes.size() - 1); 112 final int lastPos = mTypedWord.length() - 1; 113 char last = mTypedWord.charAt(lastPos); 114 mTypedWord.deleteCharAt(lastPos); 115 if (Character.isUpperCase(last)) mCapsCount--; 116 } 117 118 /** 119 * Returns the word as it was typed, without any correction applied. 120 * @return the word that was typed so far 121 */ 122 public CharSequence getTypedWord() { 123 int wordSize = mCodes.size(); 124 if (wordSize == 0) { 125 return null; 126 } 127 // StringBuffer sb = new StringBuffer(wordSize); 128 // for (int i = 0; i < wordSize; i++) { 129 // char c = (char) mCodes.get(i)[0]; 130 // if (i == 0 && mIsCapitalized) { 131 // c = Character.toUpperCase(c); 132 // } 133 // sb.append(c); 134 // } 135 // return sb; 136 return mTypedWord; 137 } 138 139 public void setCapitalized(boolean capitalized) { 140 mIsCapitalized = capitalized; 141 } 142 143 /** 144 * Whether or not the user typed a capital letter as the first letter in the word 145 * @return capitalization preference 146 */ 147 public boolean isCapitalized() { 148 return mIsCapitalized; 149 } 150 151 /** 152 * Stores the user's selected word, before it is actually committed to the text field. 153 * @param preferred 154 */ 155 public void setPreferredWord(String preferred) { 156 mPreferredWord = preferred; 157 } 158 159 /** 160 * Return the word chosen by the user, or the typed word if no other word was chosen. 161 * @return the preferred word 162 */ 163 public CharSequence getPreferredWord() { 164 return mPreferredWord != null ? mPreferredWord : getTypedWord(); 165 } 166 167 /** 168 * Returns true if more than one character is upper case, otherwise returns false. 169 */ 170 public boolean isMostlyCaps() { 171 return mCapsCount > 1; 172 } 173 174 /** 175 * Saves the reason why the word is capitalized - whether it was automatic or 176 * due to the user hitting shift in the middle of a sentence. 177 * @param auto whether it was an automatic capitalization due to start of sentence 178 */ 179 public void setAutoCapitalized(boolean auto) { 180 mAutoCapitalized = auto; 181 } 182 183 /** 184 * Returns whether the word was automatically capitalized. 185 * @return whether the word was automatically capitalized 186 */ 187 public boolean isAutoCapitalized() { 188 return mAutoCapitalized; 189 } 190 } 191