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