WordComposer.java revision 443c360d0afdbab091994244f045f4756feaf2b4
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/* 2443c360d0afdbab091994244f045f4756feaf2b4Jean-Baptiste Queru * Copyright (C) 2008 The Android Open Source Project 3923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * 4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of 6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at 7923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * 8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * 10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under 14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License. 15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 17923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpackage com.android.inputmethod.latin; 18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport java.util.ArrayList; 20923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport java.util.List; 21923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 22923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 23923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * A place to store the currently composing word with information such as adjacent key codes as well 24923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpublic class WordComposer { 26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 27923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * The list of unicode values for each keystroke (including surrounding keys) 28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 293263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani private ArrayList<int[]> mCodes; 30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 32923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * The word chosen from the candidate list, until it is committed. 33923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 34923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private String mPreferredWord; 35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 36923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private StringBuilder mTypedWord; 374a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 384a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani private int mCapsCount; 391c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 401c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani private boolean mAutoCapitalized; 41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 42923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 43923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Whether the user chose to capitalize the word. 44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 45923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project private boolean mIsCapitalized; 46923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 47923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project WordComposer() { 48923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCodes = new ArrayList<int[]>(12); 49923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mTypedWord = new StringBuilder(20); 50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 51923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 52923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 53923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Clear out the keys registered so far. 54923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 55923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void reset() { 56923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCodes.clear(); 57923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mIsCapitalized = false; 58923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPreferredWord = null; 59923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mTypedWord.setLength(0); 604a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani mCapsCount = 0; 61923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 62923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 63923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 64923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Number of keystrokes in the composing word. 65923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @return the number of keystrokes 66923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 67923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public int size() { 68923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mCodes.size(); 69923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 70923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 71923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 72923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Returns the codes at a particular position in the word. 73923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param index the position in the word 74923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @return the unicode for the pressed and surrounding keys 75923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 76923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public int[] getCodesAt(int index) { 77923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mCodes.get(index); 78923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 79923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 80923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 81923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Add a new keystroke, with codes[0] containing the pressed key's unicode and the rest of 82923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the array containing unicode for adjacent keys, sorted by reducing probability/proximity. 83923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param codes the array of unicode values 84923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 85923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void add(int primaryCode, int[] codes) { 86923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mTypedWord.append((char) primaryCode); 87231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani correctPrimaryJuxtapos(primaryCode, codes); 88923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCodes.add(codes); 894a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani if (Character.isUpperCase((char) primaryCode)) mCapsCount++; 90923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 91923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 92923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 93231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani * Swaps the first and second values in the codes array if the primary code is not the first 94231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani * value in the array but the second. This happens when the preferred key is not the key that 95231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani * the user released the finger on. 96231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani * @param primaryCode the preferred character 97231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani * @param codes array of codes based on distance from touch point 98231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani */ 99231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani private void correctPrimaryJuxtapos(int primaryCode, int[] codes) { 100231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani if (codes.length < 2) return; 101231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani if (codes[0] > 0 && codes[1] > 0 && codes[0] != primaryCode && codes[1] == primaryCode) { 102231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani codes[1] = codes[0]; 103231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani codes[0] = primaryCode; 104231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani } 105231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani } 106231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani 107231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani /** 108923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Delete the last keystroke as a result of hitting backspace. 109923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 110923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void deleteLast() { 111923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCodes.remove(mCodes.size() - 1); 1124a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani final int lastPos = mTypedWord.length() - 1; 1134a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani char last = mTypedWord.charAt(lastPos); 1144a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani mTypedWord.deleteCharAt(lastPos); 1154a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani if (Character.isUpperCase(last)) mCapsCount--; 116923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 117923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 118923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 119923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Returns the word as it was typed, without any correction applied. 120923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @return the word that was typed so far 121923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 122923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public CharSequence getTypedWord() { 123923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project int wordSize = mCodes.size(); 124923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project if (wordSize == 0) { 125923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return null; 126923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 127923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project// StringBuffer sb = new StringBuffer(wordSize); 128923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project// for (int i = 0; i < wordSize; i++) { 129923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project// char c = (char) mCodes.get(i)[0]; 130923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project// if (i == 0 && mIsCapitalized) { 131923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project// c = Character.toUpperCase(c); 132923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project// } 133923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project// sb.append(c); 134923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project// } 135923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project// return sb; 136923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mTypedWord; 137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 138923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 139923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void setCapitalized(boolean capitalized) { 140923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mIsCapitalized = capitalized; 141923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 142923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 143923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 144923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Whether or not the user typed a capital letter as the first letter in the word 145923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @return capitalization preference 146923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 147923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public boolean isCapitalized() { 148923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mIsCapitalized; 149923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 150923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 151923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 152923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Stores the user's selected word, before it is actually committed to the text field. 153923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param preferred 154923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 155923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void setPreferredWord(String preferred) { 156923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mPreferredWord = preferred; 157923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 158923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 159923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 160923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Return the word chosen by the user, or the typed word if no other word was chosen. 161923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @return the preferred word 162923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 163923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public CharSequence getPreferredWord() { 164923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mPreferredWord != null ? mPreferredWord : getTypedWord(); 165923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 1664a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 1674a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani /** 1684a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani * Returns true if more than one character is upper case, otherwise returns false. 1694a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani */ 1704a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani public boolean isMostlyCaps() { 1714a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani return mCapsCount > 1; 1724a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani } 1731c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 1741c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani /** 1751c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani * Saves the reason why the word is capitalized - whether it was automatic or 1761c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani * due to the user hitting shift in the middle of a sentence. 1771c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani * @param auto whether it was an automatic capitalization due to start of sentence 1781c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani */ 1791c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani public void setAutoCapitalized(boolean auto) { 1801c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani mAutoCapitalized = auto; 1811c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 1821c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 1831c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani /** 1841c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani * Returns whether the word was automatically capitalized. 1851c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani * @return whether the word was automatically capitalized 1861c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani */ 1871c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani public boolean isAutoCapitalized() { 1881c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani return mAutoCapitalized; 1891c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 190923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 191