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