diff --git a/assets/bg-utf8.txt b/assets/bg-utf8.txt index 2f3120ec..02d1ded0 100644 --- a/assets/bg-utf8.txt +++ b/assets/bg-utf8.txt @@ -230042,7 +230042,6 @@ домопритежателка домостроителство домоуправителите -донякогадоникъде дореволюционната дореволюционните дореволюционното diff --git a/assets/en-utf8.txt b/assets/en-utf8.txt index 5dad8233..a25a5698 100644 --- a/assets/en-utf8.txt +++ b/assets/en-utf8.txt @@ -15658,6 +15658,7 @@ lester lester's lestrade lestrade's +let's leta leta's letha @@ -93569,6 +93570,7 @@ isthmus's isthmuses istle it'd +it's it'll itacolumite italicization diff --git a/src/io/github/sspanak/tt9/ime/InputModeValidator.java b/src/io/github/sspanak/tt9/ime/InputModeValidator.java index c129587a..c12d502e 100644 --- a/src/io/github/sspanak/tt9/ime/InputModeValidator.java +++ b/src/io/github/sspanak/tt9/ime/InputModeValidator.java @@ -58,18 +58,12 @@ public class InputModeValidator { return newMode; } - public static int validateTextCase(T9Preferences prefs, int textCase, ArrayList allowedTextCases) { - if (allowedTextCases.size() > 0 && allowedTextCases.contains(textCase)) { - return textCase; + public static void validateTextCase(T9Preferences prefs, InputMode inputMode, int newTextCase) { + if (!inputMode.setTextCase(newTextCase)) { + inputMode.defaultTextCase(); + Logger.w("tt9/validateTextCase", "Invalid text case: " + newTextCase + " Enforcing: " + inputMode.getTextCase()); } - int newCase = allowedTextCases.size() > 0 ? allowedTextCases.get(0) : InputMode.CASE_LOWER; - prefs.saveTextCase(newCase); - - if (textCase != newCase) { - Logger.w("tt9/validateTextCase", "Invalid text case: " + textCase + " Enforcing: " + newCase); - } - - return newCase; + prefs.saveTextCase(inputMode.getTextCase()); } } diff --git a/src/io/github/sspanak/tt9/ime/TraditionalT9.java b/src/io/github/sspanak/tt9/ime/TraditionalT9.java index 79478d84..17ffde38 100644 --- a/src/io/github/sspanak/tt9/ime/TraditionalT9.java +++ b/src/io/github/sspanak/tt9/ime/TraditionalT9.java @@ -25,10 +25,6 @@ public class TraditionalT9 extends KeyPadHandler { private ArrayList allowedInputModes = new ArrayList<>(); private InputMode mInputMode; - // text case - private ArrayList allowedTextCases = new ArrayList<>(); - private int mTextCase = InputMode.CASE_LOWER; - // language protected ArrayList mEnabledLanguages; protected Language mLanguage; @@ -45,21 +41,20 @@ public class TraditionalT9 extends KeyPadHandler { private void loadPreferences() { mLanguage = LanguageCollection.getLanguage(prefs.getInputLanguage()); mEnabledLanguages = prefs.getEnabledLanguages(); + validateLanguages(); + mInputMode = InputMode.getInstance(prefs.getInputMode()); - mTextCase = prefs.getTextCase(); + mInputMode = InputModeValidator.validateMode(prefs, mInputMode, allowedInputModes); + + InputModeValidator.validateTextCase(prefs, mInputMode, prefs.getTextCase()); } + private void validateLanguages() { mEnabledLanguages = InputModeValidator.validateEnabledLanguages(prefs, mEnabledLanguages); mLanguage = InputModeValidator.validateLanguage(prefs, mLanguage, mEnabledLanguages); } - private void validatePreferences() { - validateLanguages(); - mInputMode = InputModeValidator.validateMode(prefs, mInputMode, allowedInputModes); - mTextCase = InputModeValidator.validateTextCase(prefs, mTextCase, allowedTextCases); - } - protected void onInit() { self = this; @@ -74,19 +69,14 @@ public class TraditionalT9 extends KeyPadHandler { protected void onRestart(EditorInfo inputField) { - determineNextTextCase(); - // determine the valid state for the current input field and preferences - determineAllowedInputModes(inputField); - determineAllowedTextCases(); mEnabledLanguages = prefs.getEnabledLanguages(); // in case we are back from Preferences screen, update the language list - - // enforce a valid initial state - validatePreferences(); - clearSuggestions(); + determineAllowedInputModes(inputField); + determineNextTextCase(); // Only in some modes. If they support it, let's overwrite the default. // build the UI - UI.updateStatusIcon(this, mLanguage, mInputMode, mTextCase); + clearSuggestions(); + UI.updateStatusIcon(this, mLanguage, mInputMode); softKeyHandler.show(); if (!isInputViewShown()) { showWindow(true); @@ -163,7 +153,7 @@ public class TraditionalT9 extends KeyPadHandler { protected boolean onLeft() { if (mInputMode.clearWordStem()) { - mInputMode.getSuggestionsAsync(handleSuggestionsAsync, mLanguage, getComposingText()); + mInputMode.loadSuggestions(handleSuggestionsAsync, mLanguage, getComposingText()); } else { jumpBeforeComposingText(); } @@ -175,7 +165,7 @@ public class TraditionalT9 extends KeyPadHandler { String filter = repeat ? mSuggestionView.getSuggestion(1) : getComposingText(); if (mInputMode.setWordStem(mLanguage, filter, repeat)) { - mInputMode.getSuggestionsAsync(handleSuggestionsAsync, mLanguage, filter); + mInputMode.loadSuggestions(handleSuggestionsAsync, mLanguage, filter); } else if (filter.length() == 0) { mInputMode.reset(); } @@ -333,14 +323,14 @@ public class TraditionalT9 extends KeyPadHandler { private void getSuggestions() { - if (!mInputMode.getSuggestionsAsync(handleSuggestionsAsync, mLanguage, mSuggestionView.getCurrentSuggestion())) { - handleSuggestions(mInputMode.getSuggestions()); + if (!mInputMode.loadSuggestions(handleSuggestionsAsync, mLanguage, mSuggestionView.getCurrentSuggestion())) { + handleSuggestions(); } } - private void handleSuggestions(ArrayList suggestions) { - setSuggestions(suggestions); + private void handleSuggestions() { + setSuggestions(mInputMode.getSuggestions(mLanguage)); // Put the first suggestion in the text field, // but cut it off to the length of the sequence (how many keys were pressed), @@ -353,21 +343,24 @@ public class TraditionalT9 extends KeyPadHandler { private final Handler handleSuggestionsAsync = new Handler(Looper.getMainLooper()) { @Override - public void handleMessage(Message msg) { - handleSuggestions(msg.getData().getStringArrayList("suggestions")); + public void handleMessage(Message m) { + handleSuggestions(); } }; private void setSuggestions(List suggestions) { + setSuggestions(suggestions, 0); + } + + private void setSuggestions(List suggestions, int selectedIndex) { if (mSuggestionView == null) { return; } boolean show = suggestions != null && suggestions.size() > 0; - mSuggestionView.setSuggestions(suggestions, 0); - mSuggestionView.changeCase(mTextCase, mLanguage.getLocale()); + mSuggestionView.setSuggestions(suggestions, selectedIndex); setCandidatesViewShown(show); } @@ -410,29 +403,27 @@ public class TraditionalT9 extends KeyPadHandler { } // when typing a word or viewing scrolling the suggestions, only change the case else if (!isSuggestionViewHidden()) { - determineAllowedTextCases(); + mInputMode.nextTextCase(); + ArrayList switchedSuggestions = mInputMode.getSuggestions(mLanguage); - int modeIndex = (allowedTextCases.indexOf(mTextCase) + 1) % allowedTextCases.size(); - mTextCase = allowedTextCases.get(modeIndex); - - mSuggestionView.changeCase(mTextCase, mLanguage.getLocale()); + setSuggestions(switchedSuggestions, mSuggestionView.getCurrentIndex()); setComposingText(getComposingText()); // no mistake, this forces the new text case } // make "abc" and "ABC" separate modes from user perspective - else if (mInputMode.isABC() && mTextCase == InputMode.CASE_LOWER) { - mTextCase = InputMode.CASE_UPPER; + else if (mInputMode.isABC() && mInputMode.getTextCase() == InputMode.CASE_LOWER) { + mInputMode.setTextCase(InputMode.CASE_UPPER); } else { int modeIndex = (allowedInputModes.indexOf(mInputMode.getId()) + 1) % allowedInputModes.size(); mInputMode = InputMode.getInstance(allowedInputModes.get(modeIndex)); - mTextCase = mInputMode.isPredictive() ? InputMode.CASE_CAPITALIZE : InputMode.CASE_LOWER; + mInputMode.defaultTextCase(); } // save the settings for the next time prefs.saveInputMode(mInputMode); - prefs.saveTextCase(mTextCase); + prefs.saveTextCase(mInputMode.getTextCase()); - UI.updateStatusIcon(this, mLanguage, mInputMode, mTextCase); + UI.updateStatusIcon(this, mLanguage, mInputMode); } @@ -453,7 +444,7 @@ public class TraditionalT9 extends KeyPadHandler { // save it for the next time prefs.saveInputLanguage(mLanguage.getId()); - UI.updateStatusIcon(this, mLanguage, mInputMode, mTextCase); + UI.updateStatusIcon(this, mLanguage, mInputMode); } @@ -490,20 +481,11 @@ public class TraditionalT9 extends KeyPadHandler { } - private void determineAllowedTextCases() { - allowedTextCases = mInputMode.getAllowedTextCases(); - // @todo: determine the text case of the input and validate using the allowed ones [ https://github.com/sspanak/tt9/issues/48 ] - } - - private void determineNextTextCase() { - int nextTextCase = mInputMode.getNextWordTextCase( - mTextCase, + mInputMode.determineNextWordTextCase( InputFieldHelper.isThereText(currentInputConnection), (String) currentInputConnection.getTextBeforeCursor(50, 0) ); - - mTextCase = nextTextCase != -1 ? nextTextCase : mTextCase; } diff --git a/src/io/github/sspanak/tt9/ime/modes/InputMode.java b/src/io/github/sspanak/tt9/ime/modes/InputMode.java index 326a5c7d..686ce02d 100644 --- a/src/io/github/sspanak/tt9/ime/modes/InputMode.java +++ b/src/io/github/sspanak/tt9/ime/modes/InputMode.java @@ -1,8 +1,6 @@ package io.github.sspanak.tt9.ime.modes; -import android.os.Bundle; import android.os.Handler; -import android.os.Message; import java.util.ArrayList; @@ -19,7 +17,9 @@ abstract public class InputMode { public static final int CASE_UPPER = 0; public static final int CASE_CAPITALIZE = 1; public static final int CASE_LOWER = 2; + public static final int CASE_DICTIONARY = 3; // do not force it, but use the dictionary word as-is protected ArrayList allowedTextCases = new ArrayList<>(); + protected int textCase = CASE_LOWER; // data protected ArrayList suggestions = new ArrayList<>(); @@ -45,14 +45,16 @@ abstract public class InputMode { // Suggestions public void onAcceptSuggestion(Language language, String suggestion) {} - public ArrayList getSuggestions() { return suggestions; } - public boolean getSuggestionsAsync(Handler handler, Language language, String lastWord) { return false; } - protected void sendSuggestions(Handler handler, ArrayList suggestions) { - Bundle bundle = new Bundle(); - bundle.putStringArrayList("suggestions", suggestions); - Message msg = new Message(); - msg.setData(bundle); - handler.sendMessage(msg); + protected void onSuggestionsUpdated(Handler handler) { handler.sendEmptyMessage(0); } + public boolean loadSuggestions(Handler handler, Language language, String lastWord) { return false; } + + public ArrayList getSuggestions(Language language) { + ArrayList newSuggestions = new ArrayList<>(); + for (String s : suggestions) { + newSuggestions.add(adjustSuggestionTextCase(s, textCase, language)); + } + + return newSuggestions; } // Word @@ -65,15 +67,38 @@ abstract public class InputMode { // Utility abstract public int getId(); - public ArrayList getAllowedTextCases() { return allowedTextCases; } - // Perform any special logic to determine the text case of the next word, or return "-1" if there is no need to change it. - public int getNextWordTextCase(int currentTextCase, boolean isThereText, String textBeforeCursor) { return -1; } abstract public int getSequenceLength(); // The number of key presses for the current word. public void reset() { suggestions = new ArrayList<>(); word = null; } + // Text case + public int getTextCase() { return textCase; } + + public boolean setTextCase(int newTextCase) { + if (!allowedTextCases.contains(newTextCase)) { + return false; + } + + textCase = newTextCase; + return true; + } + + public void defaultTextCase() { + textCase = allowedTextCases.get(0); + } + + public void nextTextCase() { + int nextIndex = (allowedTextCases.indexOf(textCase) + 1) % allowedTextCases.size(); + textCase = allowedTextCases.get(nextIndex); + } + + public void determineNextWordTextCase(boolean isThereText, String textBeforeCursor) {} + + // Based on the internal logic of the mode (punctuation or grammar rules), re-adjust the text case for when getSuggestions() is called. + protected String adjustSuggestionTextCase(String word, int newTextCase, Language language) { return word; } + // Stem filtering. // Where applicable, return "true" if the mode supports it and the operation was possible. public boolean clearWordStem() { return false; } diff --git a/src/io/github/sspanak/tt9/ime/modes/ModeABC.java b/src/io/github/sspanak/tt9/ime/modes/ModeABC.java index 7d75059e..c024446d 100644 --- a/src/io/github/sspanak/tt9/ime/modes/ModeABC.java +++ b/src/io/github/sspanak/tt9/ime/modes/ModeABC.java @@ -1,5 +1,7 @@ package io.github.sspanak.tt9.ime.modes; +import java.util.ArrayList; + import io.github.sspanak.tt9.languages.Language; public class ModeABC extends InputMode { @@ -19,10 +21,10 @@ public class ModeABC extends InputMode { word = null; if (hold) { - suggestions = null; + suggestions = new ArrayList<>(); word = String.valueOf(key); } else if (repeat) { - suggestions = null; + suggestions = new ArrayList<>(); shouldSelectNextLetter = true; } @@ -30,6 +32,11 @@ public class ModeABC extends InputMode { } + protected String adjustSuggestionTextCase(String word, int newTextCase, Language language) { + return newTextCase == CASE_UPPER ? word.toUpperCase(language.getLocale()) : word.toLowerCase(language.getLocale()); + } + + final public boolean isABC() { return true; } public int getSequenceLength() { return 1; } diff --git a/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java b/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java index 106d44f6..7dff60a4 100644 --- a/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java +++ b/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java @@ -5,7 +5,6 @@ import android.os.Looper; import android.os.Message; import java.util.ArrayList; -import java.util.regex.Matcher; import java.util.regex.Pattern; import io.github.sspanak.tt9.Logger; @@ -29,11 +28,14 @@ public class ModePredictive extends InputMode { private String lastInputFieldWord = ""; private static Handler handleSuggestionsExternal; + // auto text case selection + private final Pattern endOfSentence = Pattern.compile("(? suggestions = msg.getData().getStringArrayList("suggestions"); - suggestions = suggestions == null ? new ArrayList<>() : suggestions; + ArrayList dbSuggestions = msg.getData().getStringArrayList("suggestions"); + dbSuggestions = dbSuggestions == null ? new ArrayList<>() : dbSuggestions; - if (suggestions.size() == 0 && digitSequence.length() > 0) { - suggestions = generatePossibleCompletions(currentLanguage, lastInputFieldWord); + if (dbSuggestions.size() == 0 && digitSequence.length() > 0) { + dbSuggestions = generatePossibleCompletions(currentLanguage, lastInputFieldWord); } - ArrayList stemVariations = generatePossibleStemVariations(currentLanguage, suggestions); - stemVariations.addAll(suggestions); + suggestions.clear(); + suggestStem(); + suggestions.addAll(generatePossibleStemVariations(currentLanguage, dbSuggestions)); + suggestMoreWords(dbSuggestions); - ModePredictive.super.sendSuggestions(handleSuggestionsExternal, stemVariations); + ModePredictive.super.onSuggestionsUpdated(handleSuggestionsExternal); } }; @@ -269,22 +264,28 @@ public class ModePredictive extends InputMode { * * For example, if the filter is "extr", the current word is "extr_" and the user has pressed "1", * the database would have returned only "extra", but this function would also - * generate: "extrb" and "extrc". This is useful for typing an unknown word, similar to the ones - * in the dictionary. + * generate: "extrb" and "extrc". This is useful for typing an unknown word, that is similar to + * the ones in the dictionary. */ - private ArrayList generatePossibleStemVariations(Language language, ArrayList currentSuggestions) { + private ArrayList generatePossibleStemVariations(Language language, ArrayList dbSuggestions) { ArrayList variations = new ArrayList<>(); if (stem.length() == 0) { return variations; } - if (stem.length() == digitSequence.length() && !currentSuggestions.contains(stem)) { - variations.add(stem); - } - if (isStemFuzzy && stem.length() == digitSequence.length() - 1) { - for (String word : generatePossibleCompletions(language, stem)) { - if (!currentSuggestions.contains(word)) { + ArrayList allPossibleVariations = generatePossibleCompletions(language, stem); + + // first add the known words, because it makes more sense to see them first + for (String word : allPossibleVariations) { + if (dbSuggestions.contains(word)) { + variations.add(word); + } + } + + // then add the unknown ones, so they can be used as possible beginnings of new words. + for (String word : allPossibleVariations) { + if (!dbSuggestions.contains(word)) { variations.add(word); } } @@ -293,6 +294,30 @@ public class ModePredictive extends InputMode { return variations; } + /** + * suggestStem + * Add the current stem filter to the suggestion list, when it has length of X and + * the user has pressed X keys. + */ + public void suggestStem() { + if (stem.length() > 0 && stem.length() == digitSequence.length()) { + suggestions.add(stem); + } + } + + + /** + * suggestMoreWords + * Takes a list of words and appends them to the suggestion list, if they are missing. + */ + public void suggestMoreWords(ArrayList newSuggestions) { + for (String word : newSuggestions) { + if (!suggestions.contains(word)) { + suggestions.add(word); + } + } + } + /** * onAcceptSuggestion @@ -316,28 +341,61 @@ public class ModePredictive extends InputMode { /** - * getNextWordTextCase - * Dynamically determine text case of words as the user types to reduce key presses. + * adjustSuggestionTextCase + * In addition to uppercase/lowercase, here we use the result from determineNextWordTextCase(), + * to conveniently start sentences with capitals or whatnot. + * + * Also, by default we preserve any mixed case words in the dictionary, + * for example: "dB", "Mb", proper names, German nouns, that always start with a capital, + * or Dutch words such as: "'s-Hertogenbosch". + */ + protected String adjustSuggestionTextCase(String word, int newTextCase, Language language) { + switch (newTextCase) { + case CASE_UPPER: + return word.toUpperCase(language.getLocale()); + case CASE_LOWER: + return word.toLowerCase(language.getLocale()); + case CASE_CAPITALIZE: + return language.isMixedCaseWord(word) ? word : language.capitalize(word); + case CASE_DICTIONARY: + return language.isMixedCaseWord(word) ? word : word.toLowerCase(language.getLocale()); + default: + return word; + } + } + + + /** + * determineNextWordTextCase + * Dynamically determine text case of words as the user types, to reduce key presses. * For example, this function will return CASE_LOWER by default, but CASE_UPPER at the beginning * of a sentence. */ - public int getNextWordTextCase(int currentTextCase, boolean isThereText, String textBeforeCursor) { + public void determineNextWordTextCase(boolean isThereText, String textBeforeCursor) { // If the user wants to type in uppercase, this must be for a reason, so we better not override it. - if (currentTextCase == CASE_UPPER) { - return -1; + if (textCase == CASE_UPPER) { + return; } // start of text if (!isThereText) { - return CASE_CAPITALIZE; + textCase = CASE_CAPITALIZE; + return; } // start of sentence, excluding after "..." - Matcher endOfSentenceMatch = Pattern.compile("(?> characterMap = new ArrayList<>(); + // settings + protected boolean isPunctuationPartOfWords; // see the getter for more info + final public int getId() { return id; } @@ -31,6 +33,15 @@ public class Language { return icon; } + final public String getDictionaryFile() { + return dictionaryFile; + } + + final public int getAbcIcon(boolean lowerCase) { + return lowerCase ? abcLowerCaseIcon : abcUpperCaseIcon; + } + + /** * isPunctuationPartOfWords * This plays a role in Predictive mode only. @@ -49,12 +60,15 @@ public class Language { */ final public boolean isPunctuationPartOfWords() { return isPunctuationPartOfWords; } - final public String getDictionaryFile() { - return dictionaryFile; + + /************* utility *************/ + + public String capitalize(String word) { + return word != null ? word.substring(0, 1).toUpperCase(locale) + word.substring(1).toLowerCase(locale) : null; } - final public int getAbcIcon(boolean lowerCase) { - return lowerCase ? abcLowerCaseIcon : abcUpperCaseIcon; + public boolean isMixedCaseWord(String word) { + return word != null && !word.toLowerCase(locale).equals(word) && !word.toUpperCase(locale).equals(word); } public ArrayList getKeyCharacters(int key) { diff --git a/src/io/github/sspanak/tt9/languages/definitions/Bulgarian.java b/src/io/github/sspanak/tt9/languages/definitions/Bulgarian.java index 1a043e9a..8224bb66 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Bulgarian.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Bulgarian.java @@ -14,11 +14,12 @@ public class Bulgarian extends Language { name = "български"; locale = new Locale("bg","BG"); dictionaryFile = "bg-utf8.txt"; - isPunctuationPartOfWords = false; icon = R.drawable.ime_lang_bg; abcLowerCaseIcon = R.drawable.ime_lang_cyrillic_lower; abcUpperCaseIcon = R.drawable.ime_lang_cyrillic_upper; + isPunctuationPartOfWords = false; + characterMap = new ArrayList<>(Arrays.asList( Punctuation.Secondary, // 0 Punctuation.Main, // 1 diff --git a/src/io/github/sspanak/tt9/languages/definitions/Dutch.java b/src/io/github/sspanak/tt9/languages/definitions/Dutch.java index b8fe5f83..1fd81dc6 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Dutch.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Dutch.java @@ -12,10 +12,11 @@ public class Dutch extends English { id = 8; name = "Nederlands"; locale = new Locale("nl","NL"); - isPunctuationPartOfWords = true; dictionaryFile = "nl-utf8.txt"; icon = R.drawable.ime_lang_nl; + isPunctuationPartOfWords = true; + characterMap.get(2).addAll(Arrays.asList("à", "ä", "ç")); characterMap.get(3).addAll(Arrays.asList("é", "è", "ê", "ë")); characterMap.get(4).addAll(Arrays.asList("î", "ï")); diff --git a/src/io/github/sspanak/tt9/languages/definitions/English.java b/src/io/github/sspanak/tt9/languages/definitions/English.java index 17d96964..1a46e955 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/English.java +++ b/src/io/github/sspanak/tt9/languages/definitions/English.java @@ -14,11 +14,12 @@ public class English extends Language { name = "English"; locale = Locale.ENGLISH; dictionaryFile = "en-utf8.txt"; - isPunctuationPartOfWords = true; icon = R.drawable.ime_lang_en; abcLowerCaseIcon = R.drawable.ime_lang_latin_lower; abcUpperCaseIcon = R.drawable.ime_lang_latin_upper; + isPunctuationPartOfWords = true; + characterMap = new ArrayList<>(Arrays.asList( Punctuation.Secondary, // 0 Punctuation.Main, // 1 diff --git a/src/io/github/sspanak/tt9/languages/definitions/French.java b/src/io/github/sspanak/tt9/languages/definitions/French.java index 93e11aac..844d672f 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/French.java +++ b/src/io/github/sspanak/tt9/languages/definitions/French.java @@ -14,6 +14,7 @@ public class French extends English { locale = Locale.FRENCH; dictionaryFile = "fr-utf8.txt"; icon = R.drawable.ime_lang_fr; + isPunctuationPartOfWords = false; characterMap.get(2).addAll(Arrays.asList("à", "â", "æ", "ç")); diff --git a/src/io/github/sspanak/tt9/languages/definitions/German.java b/src/io/github/sspanak/tt9/languages/definitions/German.java index 3a05f1fe..ec52221b 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/German.java +++ b/src/io/github/sspanak/tt9/languages/definitions/German.java @@ -13,6 +13,7 @@ public class German extends English { locale = Locale.GERMAN; dictionaryFile = "de-utf8.txt"; icon = R.drawable.ime_lang_de; + isPunctuationPartOfWords = false; characterMap.get(2).add("ä"); diff --git a/src/io/github/sspanak/tt9/languages/definitions/Italian.java b/src/io/github/sspanak/tt9/languages/definitions/Italian.java index cf882d46..c5181c49 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Italian.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Italian.java @@ -14,6 +14,7 @@ public class Italian extends English { locale = Locale.ITALIAN; dictionaryFile = "it-utf8.txt"; icon = R.drawable.ime_lang_it; + isPunctuationPartOfWords = false; characterMap.get(2).add("à"); diff --git a/src/io/github/sspanak/tt9/languages/definitions/Russian.java b/src/io/github/sspanak/tt9/languages/definitions/Russian.java index 0bded11b..c039720c 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Russian.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Russian.java @@ -14,11 +14,12 @@ public class Russian extends Language { name = "русский"; locale = new Locale("ru","RU"); dictionaryFile = "ru-utf8.txt"; - isPunctuationPartOfWords = false; icon = R.drawable.ime_lang_ru; abcLowerCaseIcon = R.drawable.ime_lang_cyrillic_lower; abcUpperCaseIcon = R.drawable.ime_lang_cyrillic_upper; + isPunctuationPartOfWords = false; + characterMap = new ArrayList<>(Arrays.asList( Punctuation.Secondary, // 0 Punctuation.Main, // 1 diff --git a/src/io/github/sspanak/tt9/languages/definitions/Ukrainian.java b/src/io/github/sspanak/tt9/languages/definitions/Ukrainian.java index a6a4ff2b..0ce93175 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Ukrainian.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Ukrainian.java @@ -14,11 +14,12 @@ public class Ukrainian extends Language { name = "українська"; locale = new Locale("uk","UA"); dictionaryFile = "uk-utf8.txt"; - isPunctuationPartOfWords = true; icon = R.drawable.ime_lang_uk; abcLowerCaseIcon = R.drawable.ime_lang_cyrillic_lower; abcUpperCaseIcon = R.drawable.ime_lang_cyrillic_upper; + isPunctuationPartOfWords = true; + characterMap = new ArrayList<>(Arrays.asList( Punctuation.Secondary, // 0 Punctuation.Main, // 1 diff --git a/src/io/github/sspanak/tt9/ui/CandidateView.java b/src/io/github/sspanak/tt9/ui/CandidateView.java index 258fc069..d3a17996 100644 --- a/src/io/github/sspanak/tt9/ui/CandidateView.java +++ b/src/io/github/sspanak/tt9/ui/CandidateView.java @@ -10,14 +10,12 @@ import android.view.View; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import io.github.sspanak.tt9.R; -import io.github.sspanak.tt9.ime.modes.InputMode; public class CandidateView extends View { - private List mSuggestions; + private List mSuggestions = new ArrayList<>(); protected int mSelectedIndex; private Drawable mSelectionHighlight; @@ -32,7 +30,7 @@ public class CandidateView extends View { private static final int X_GAP = 10; - private static final List EMPTY_LIST = new ArrayList(); + private static final List EMPTY_LIST = new ArrayList<>(); private int mColorNormal; private int mColorRecommended; @@ -47,8 +45,6 @@ public class CandidateView extends View { /** * Construct a CandidateView for showing suggested words for completion. - * - * @param context */ public CandidateView(Context context) { super(context); @@ -204,23 +200,6 @@ public class CandidateView extends View { requestLayout(); } - public void changeCase(int textCase, Locale locale) { - ArrayList newSuggestions = new ArrayList<>(); - - for (String s : mSuggestions) { - if (textCase == InputMode.CASE_LOWER) { - newSuggestions.add(s.toLowerCase(locale)); - } else if (textCase == InputMode.CASE_CAPITALIZE) { - String cs = s.substring(0, 1).toUpperCase(locale) + s.substring(1).toLowerCase(locale); - newSuggestions.add(cs); - } else { - newSuggestions.add(s.toUpperCase(locale)); - } - } - - setSuggestions(newSuggestions, mSelectedIndex); - } - protected void clear() { mSuggestions = EMPTY_LIST; mSelectedIndex = -1; diff --git a/src/io/github/sspanak/tt9/ui/UI.java b/src/io/github/sspanak/tt9/ui/UI.java index cc7ff2bc..e3476ba2 100644 --- a/src/io/github/sspanak/tt9/ui/UI.java +++ b/src/io/github/sspanak/tt9/ui/UI.java @@ -35,9 +35,9 @@ public class UI { * Set the status icon that is appropriate in current mode (based on * openwmm-legacy) */ - public static void updateStatusIcon(TraditionalT9 tt9, Language inputLanguage, InputMode inputMode, int textCase) { + public static void updateStatusIcon(TraditionalT9 tt9, Language inputLanguage, InputMode inputMode) { if (inputMode.isABC()) { - tt9.showStatusIcon(inputLanguage.getAbcIcon(textCase == InputMode.CASE_LOWER)); + tt9.showStatusIcon(inputLanguage.getAbcIcon(inputMode.getTextCase() == InputMode.CASE_LOWER)); } else if (inputMode.isPredictive()) { tt9.showStatusIcon(inputLanguage.getIcon()); } else if (inputMode.is123()) {