From 9b33937220fb3ddbd1a26f4dd2217cbfa67f0c11 Mon Sep 17 00:00:00 2001 From: Dimo Karaivanov Date: Wed, 31 May 2023 09:53:34 +0300 Subject: [PATCH] mEditing is no more (#265) * removed mEditing and simplified initial mode selection and validation * fixed the status bar displaying incorrect text when in a limited field * fixed incorrect auto text case being selected after toggling all modes, then going back to Predictive * fixed the on-screen keyboard sometimes not updating when the input mode changes --- .../github/sspanak/tt9/ime/TraditionalT9.java | 102 +++++++++--------- .../tt9/ime/helpers/InputModeValidator.java | 33 +++--- .../sspanak/tt9/ime/modes/InputMode.java | 1 + .../tt9/preferences/PreferencesActivity.java | 2 +- .../tt9/ui/main/keys/SoftNumberKey.java | 10 +- .../tt9/ui/main/keys/SoftPunctuationKey.java | 8 +- .../github/sspanak/tt9/ui/tray/StatusBar.java | 7 +- 7 files changed, 78 insertions(+), 85 deletions(-) diff --git a/src/io/github/sspanak/tt9/ime/TraditionalT9.java b/src/io/github/sspanak/tt9/ime/TraditionalT9.java index d9cf3114..a04d2f4d 100644 --- a/src/io/github/sspanak/tt9/ime/TraditionalT9.java +++ b/src/io/github/sspanak/tt9/ime/TraditionalT9.java @@ -29,15 +29,8 @@ import io.github.sspanak.tt9.ui.tray.SuggestionsBar; public class TraditionalT9 extends KeyPadHandler { // internal settings/data private boolean isActive = false; - @NotNull - private TextField textField = new TextField(null, null); - @NotNull - private InputType inputType = new InputType(null, null); - - // editing mode - protected static final int NON_EDIT = 0; - protected static final int EDITING = 1; - @Deprecated protected int mEditing = NON_EDIT; // @todo: migrate to "isActive" + @NotNull private TextField textField = new TextField(null, null); + @NotNull private InputType inputType = new InputType(null, null); // input mode private ArrayList allowedInputModes = new ArrayList<>(); @@ -62,6 +55,14 @@ public class TraditionalT9 extends KeyPadHandler { return settings; } + public int getInputMode() { + return mInputMode != null ? mInputMode.getId() : InputMode.MODE_UNDEFINED; + } + + public int getTextCase() { + return mInputMode != null ? mInputMode.getTextCase() : InputMode.CASE_UNDEFINED; + } + private void loadSettings() { mLanguage = LanguageCollection.getLanguage(settings.getInputLanguage()); @@ -74,8 +75,11 @@ public class TraditionalT9 extends KeyPadHandler { private void validateLanguages() { - mEnabledLanguages = InputModeValidator.validateEnabledLanguages(settings, mEnabledLanguages); - mLanguage = InputModeValidator.validateLanguage(settings, mLanguage, mEnabledLanguages); + mEnabledLanguages = InputModeValidator.validateEnabledLanguages(mEnabledLanguages); + mLanguage = InputModeValidator.validateLanguage(mLanguage, mEnabledLanguages); + + settings.saveEnabledLanguageIds(mEnabledLanguages); + settings.saveInputLanguage(mLanguage.getId()); } @@ -86,6 +90,31 @@ public class TraditionalT9 extends KeyPadHandler { } + /** + * determineInputMode + * Restore the last input mode or choose a more appropriate one. + * Some input fields support only numbers or are not suited for predictions (e.g. password fields) + */ + private void determineInputMode() { + allowedInputModes = textField.determineInputModes(inputType); + int validModeId = InputModeValidator.validateMode(settings.getInputMode(), allowedInputModes); + mInputMode = InputMode.getInstance(settings, mLanguage, validModeId); + } + + + /** + * determineTextCase + * Restore the last text case or auto-select a new one. If the InputMode supports it, it can change + * the text case based on grammar rules, otherwise we fallback to the input field properties or the + * last saved mode. + */ + private void determineTextCase() { + mInputMode.setTextFieldCase(textField.determineTextCase(inputType)); + mInputMode.determineNextWordTextCase(textField.isThereText(), textField.getTextBeforeCursor()); + InputModeValidator.validateTextCase(mInputMode, settings.getTextCase()); + } + + protected void onInit() { self = this; @@ -107,16 +136,8 @@ public class TraditionalT9 extends KeyPadHandler { // in case we are back from Settings screen, update the language list mEnabledLanguages = settings.getEnabledLanguageIds(); validateLanguages(); - - // some input fields support only numbers or are not suited for predictions (e.g. password fields) - determineAllowedInputModes(); - int modeId = InputModeValidator.validateMode(settings, mInputMode, allowedInputModes); - mInputMode = InputMode.getInstance(settings, mLanguage, modeId); - mInputMode.setTextFieldCase(textField.determineTextCase(inputType)); - - // Some modes may want to change the default text case based on grammar rules. - determineNextTextCase(); - InputModeValidator.validateTextCase(settings, mInputMode, settings.getTextCase()); + determineInputMode(); + determineTextCase(); } @@ -172,13 +193,13 @@ public class TraditionalT9 extends KeyPadHandler { protected void onFinishTyping() { isActive = false; - mEditing = NON_EDIT; } protected void onStop() { onFinishTyping(); clearSuggestions(); + statusBar.setText("--"); } @@ -299,7 +320,7 @@ public class TraditionalT9 extends KeyPadHandler { // Auto-adjust the text case before each word, if the InputMode supports it. // We don't do it too often, because it is somewhat resource-intensive. if (currentWord.length() == 0) { - determineNextTextCase(); + mInputMode.determineNextWordTextCase(textField.isThereText(), textField.getTextBeforeCursor()); } if (!mInputMode.onNumber(key, hold, repeat)) { @@ -376,12 +397,12 @@ public class TraditionalT9 extends KeyPadHandler { public boolean onKeyNextInputMode() { nextInputMode(); + mainView.render(); if (allowedInputModes.size() == 1) { return false; } - mainView.render(); forceShowWindowIfHidden(); return true; } @@ -556,8 +577,9 @@ public class TraditionalT9 extends KeyPadHandler { } else { int modeIndex = (allowedInputModes.indexOf(mInputMode.getId()) + 1) % allowedInputModes.size(); mInputMode = InputMode.getInstance(settings, mLanguage, allowedInputModes.get(modeIndex)); + mInputMode.setTextFieldCase(textField.determineTextCase(inputType)); + mInputMode.determineNextWordTextCase(textField.isThereText(), textField.getTextBeforeCursor()); - mInputMode.defaultTextCase(); resetKeyRepeat(); } @@ -599,24 +621,6 @@ public class TraditionalT9 extends KeyPadHandler { } - private void determineAllowedInputModes() { - allowedInputModes = textField.determineInputModes(inputType); - - int lastInputModeId = settings.getInputMode(); - if (allowedInputModes.contains(lastInputModeId)) { - mInputMode = InputMode.getInstance(settings, mLanguage, lastInputModeId); - } else if (allowedInputModes.size() == 1 && allowedInputModes.get(0) == InputMode.MODE_DIALER) { - mInputMode = InputMode.getInstance(settings, mLanguage, InputMode.MODE_DIALER); - } else if (allowedInputModes.contains(InputMode.MODE_ABC)) { - mInputMode = InputMode.getInstance(settings, mLanguage, InputMode.MODE_ABC); - } else { - mInputMode = InputMode.getInstance(settings, mLanguage, allowedInputModes.get(0)); - } - - mEditing = EDITING; - } - - private void autoCorrectSpace(String currentWord, boolean isWordAcceptedManually) { if (mInputMode.shouldDeletePrecedingSpace(inputType)) { textField.deletePrecedingSpace(currentWord); @@ -628,14 +632,6 @@ public class TraditionalT9 extends KeyPadHandler { } - private void determineNextTextCase() { - mInputMode.determineNextWordTextCase( - textField.isThereText(), - textField.getTextBeforeCursor() - ); - } - - private boolean performOKAction() { if (currentInputConnection == null) { return false; @@ -735,12 +731,12 @@ public class TraditionalT9 extends KeyPadHandler { @Override protected boolean shouldBeVisible() { - return !mInputMode.isDialer() && mEditing != NON_EDIT; + return !mInputMode.isDialer() && isActive; } @Override protected boolean shouldBeOff() { - return currentInputConnection == null || mEditing == NON_EDIT; + return currentInputConnection == null || !isActive; } } diff --git a/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java b/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java index e73eb38a..695a279e 100644 --- a/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java +++ b/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java @@ -6,10 +6,9 @@ import io.github.sspanak.tt9.Logger; import io.github.sspanak.tt9.ime.modes.InputMode; import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.languages.LanguageCollection; -import io.github.sspanak.tt9.preferences.SettingsStore; public class InputModeValidator { - public static ArrayList validateEnabledLanguages(SettingsStore settings, ArrayList enabledLanguageIds) { + public static ArrayList validateEnabledLanguages(ArrayList enabledLanguageIds) { ArrayList validLanguages = LanguageCollection.getAll(enabledLanguageIds); ArrayList validLanguageIds = new ArrayList<>(); for (Language lang : validLanguages) { @@ -20,12 +19,10 @@ public class InputModeValidator { Logger.e("tt9/validateEnabledLanguages", "The language list seems to be corrupted. Resetting to first language only."); } - settings.saveEnabledLanguageIds(validLanguageIds); - return validLanguageIds; } - public static Language validateLanguage(SettingsStore settings, Language language, ArrayList validLanguageIds) { + public static Language validateLanguage(Language language, ArrayList validLanguageIds) { if (language != null && validLanguageIds.contains(language.getId())) { return language; } @@ -34,34 +31,34 @@ public class InputModeValidator { Language validLanguage = LanguageCollection.getLanguage(validLanguageIds.get(0)); validLanguage = validLanguage != null ? validLanguage : LanguageCollection.getDefault(); - settings.saveInputLanguage(validLanguage.getId()); - Logger.w("tt9/validateSavedLanguage", error + " Enforcing language: " + validLanguage.getId()); + Logger.w("tt9/validateLanguage", error + " Enforcing language: " + validLanguage.getId()); return validLanguage; } - public static int validateMode(SettingsStore settings, InputMode inputMode, ArrayList allowedModes) { - if (allowedModes.size() > 0 && allowedModes.contains(inputMode.getId())) { - return inputMode.getId(); + public static int validateMode(int oldModeId, ArrayList allowedModes) { + int newModeId = InputMode.MODE_123; + + if (allowedModes.contains(oldModeId)) { + newModeId = oldModeId; + } else if (allowedModes.contains(InputMode.MODE_ABC)) { + newModeId = InputMode.MODE_ABC; + } else if (allowedModes.size() > 0) { + newModeId = allowedModes.get(0); } - int newModeId = allowedModes.size() > 0 ? allowedModes.get(0) : InputMode.MODE_123; - settings.saveInputMode(newModeId); - - if (newModeId != inputMode.getId()) { - Logger.w("tt9/validateMode", "Invalid input mode: " + inputMode.getId() + " Enforcing: " + newModeId); + if (newModeId != oldModeId) { + Logger.w("tt9/validateMode", "Invalid input mode: " + oldModeId + " Enforcing: " + newModeId); } return newModeId; } - public static void validateTextCase(SettingsStore settings, InputMode inputMode, int newTextCase) { + public static void validateTextCase(InputMode inputMode, int newTextCase) { if (!inputMode.setTextCase(newTextCase)) { inputMode.defaultTextCase(); Logger.w("tt9/validateTextCase", "Invalid text case: " + newTextCase + " Enforcing: " + inputMode.getTextCase()); } - - settings.saveTextCase(inputMode.getTextCase()); } } diff --git a/src/io/github/sspanak/tt9/ime/modes/InputMode.java b/src/io/github/sspanak/tt9/ime/modes/InputMode.java index 5f96cad5..fb3f9274 100644 --- a/src/io/github/sspanak/tt9/ime/modes/InputMode.java +++ b/src/io/github/sspanak/tt9/ime/modes/InputMode.java @@ -12,6 +12,7 @@ import io.github.sspanak.tt9.preferences.SettingsStore; abstract public class InputMode { // typing mode + public static final int MODE_UNDEFINED = -1; public static final int MODE_PREDICTIVE = 0; public static final int MODE_ABC = 1; public static final int MODE_123 = 2; diff --git a/src/io/github/sspanak/tt9/preferences/PreferencesActivity.java b/src/io/github/sspanak/tt9/preferences/PreferencesActivity.java index 5b203d02..1715bf00 100644 --- a/src/io/github/sspanak/tt9/preferences/PreferencesActivity.java +++ b/src/io/github/sspanak/tt9/preferences/PreferencesActivity.java @@ -40,7 +40,7 @@ public class PreferencesActivity extends AppCompatActivity implements Preference DictionaryDb.init(this); DictionaryDb.normalizeWordFrequencies(settings); - InputModeValidator.validateEnabledLanguages(settings, settings.getEnabledLanguageIds()); + InputModeValidator.validateEnabledLanguages(settings.getEnabledLanguageIds()); validateFunctionKeys(); super.onCreate(savedInstanceState); diff --git a/src/io/github/sspanak/tt9/ui/main/keys/SoftNumberKey.java b/src/io/github/sspanak/tt9/ui/main/keys/SoftNumberKey.java index e67c937e..8c5f9796 100644 --- a/src/io/github/sspanak/tt9/ui/main/keys/SoftNumberKey.java +++ b/src/io/github/sspanak/tt9/ui/main/keys/SoftNumberKey.java @@ -28,7 +28,7 @@ public class SoftNumberKey extends SoftKey { @Override protected boolean handleHold() { - if (tt9 == null || tt9.getSettings().getInputMode() != InputMode.MODE_123 || getId() != R.id.soft_key_0) { + if (tt9 == null || tt9.getInputMode() != InputMode.MODE_123 || getId() != R.id.soft_key_0) { return super.handleHold(); } @@ -70,7 +70,7 @@ public class SoftNumberKey extends SoftKey { int number = getNumber(getId()); if (number == 0) { - if (tt9.getSettings().getInputMode() == InputMode.MODE_123) { + if (tt9.getInputMode() == InputMode.MODE_123) { return "+"; } else { COMPLEX_LABEL_SUB_TITLE_SIZE = 1; @@ -79,7 +79,7 @@ public class SoftNumberKey extends SoftKey { } // no special labels in 123 mode - if (tt9.getSettings().getInputMode() == InputMode.MODE_123) { + if (tt9.getInputMode() == InputMode.MODE_123) { return null; } @@ -89,9 +89,7 @@ public class SoftNumberKey extends SoftKey { } // 2-9 - int textCase = tt9.getSettings().getTextCase(); Language language = LanguageCollection.getLanguage(tt9.getSettings().getInputLanguage()); - if (language == null) { Logger.d("SoftNumberKey.getLabel", "Cannot generate a label when the language is NULL."); return ""; @@ -101,7 +99,7 @@ public class SoftNumberKey extends SoftKey { ArrayList chars = language.getKeyCharacters(number, false); for (int i = 0; i < 5 && i < chars.size(); i++) { sb.append( - textCase == InputMode.CASE_UPPER ? chars.get(i).toUpperCase(language.getLocale()) : chars.get(i) + tt9.getTextCase() == InputMode.CASE_UPPER ? chars.get(i).toUpperCase(language.getLocale()) : chars.get(i) ); } diff --git a/src/io/github/sspanak/tt9/ui/main/keys/SoftPunctuationKey.java b/src/io/github/sspanak/tt9/ui/main/keys/SoftPunctuationKey.java index a5327656..b75ad9b1 100644 --- a/src/io/github/sspanak/tt9/ui/main/keys/SoftPunctuationKey.java +++ b/src/io/github/sspanak/tt9/ui/main/keys/SoftPunctuationKey.java @@ -23,7 +23,7 @@ public class SoftPunctuationKey extends SoftKey { @Override protected boolean handleHold() { - if (tt9 == null || tt9.getSettings().getInputMode() != InputMode.MODE_123) { + if (tt9 == null || tt9.getInputMode() != InputMode.MODE_123) { return super.handleHold(); } @@ -43,7 +43,7 @@ public class SoftPunctuationKey extends SoftKey { } int keyId = getId(); - if (tt9.getSettings().getInputMode() == InputMode.MODE_123) { + if (tt9.getInputMode() == InputMode.MODE_123) { if (keyId == R.id.soft_key_punctuation_1) return tt9.onOtherKey(KeyEvent.KEYCODE_STAR); if (keyId == R.id.soft_key_punctuation_2) return tt9.onOtherKey(KeyEvent.KEYCODE_POUND); } else { @@ -61,7 +61,7 @@ public class SoftPunctuationKey extends SoftKey { } int keyId = getId(); - if (tt9.getSettings().getInputMode() == InputMode.MODE_123) { + if (tt9.getInputMode() == InputMode.MODE_123) { if (keyId == R.id.soft_key_punctuation_1) return "✱"; if (keyId == R.id.soft_key_punctuation_2) return "#"; } else { @@ -75,7 +75,7 @@ public class SoftPunctuationKey extends SoftKey { @Override protected String getSubTitle() { int keyId = getId(); - if (tt9 != null && tt9.getSettings().getInputMode() == InputMode.MODE_123) { + if (tt9 != null && tt9.getInputMode() == InputMode.MODE_123) { if (keyId == R.id.soft_key_punctuation_1) return ","; if (keyId == R.id.soft_key_punctuation_2) return "."; } diff --git a/src/io/github/sspanak/tt9/ui/tray/StatusBar.java b/src/io/github/sspanak/tt9/ui/tray/StatusBar.java index efbe3fa4..3069d2e1 100644 --- a/src/io/github/sspanak/tt9/ui/tray/StatusBar.java +++ b/src/io/github/sspanak/tt9/ui/tray/StatusBar.java @@ -22,9 +22,9 @@ public class StatusBar { public void setText(String text) { statusText = "[ " + text + " ]"; this.render(); - } + public void setDarkTheme(boolean darkTheme) { if (statusView == null) { Logger.w("StatusBar.setDarkTheme", "Not changing the theme of a NULL View."); @@ -45,12 +45,13 @@ public class StatusBar { statusView.setBackgroundColor(backgroundColor); statusView.setTextColor(color); this.render(); - } + private void render() { if (statusText == null) { - Logger.w("StatusBar.render", "Not displaying status of NULL mode"); + Logger.w("StatusBar.render", "Not displaying NULL status"); + return; } statusView.setText(statusText);