diff --git a/src/io/github/sspanak/tt9/ime/KeyPadHandler.java b/src/io/github/sspanak/tt9/ime/KeyPadHandler.java index 45f0bf7b..54dda8d5 100644 --- a/src/io/github/sspanak/tt9/ime/KeyPadHandler.java +++ b/src/io/github/sspanak/tt9/ime/KeyPadHandler.java @@ -119,9 +119,8 @@ abstract class KeyPadHandler extends InputMethodService { // Logger.d("onKeyDown", "Key: " + event + " repeat?: " + event.getRepeatCount() + " long-time: " + event.isLongPress()); // "backspace" key must repeat its function when held down, so we handle it in a special way - if (Key.isBackspace(settings, keyCode)) { - isBackspaceHandled = onBackspace(); - return isBackspaceHandled; + if (Key.isBackspace(settings, keyCode) && onBackspace()) { + return isBackspaceHandled = true; } else { isBackspaceHandled = false; } @@ -131,12 +130,17 @@ abstract class KeyPadHandler extends InputMethodService { event.startTracking(); } - return Key.isNumber(keyCode) + if (Key.isBack(keyCode)) { + return onBack() && super.onKeyDown(keyCode, event); + } + + return + Key.isNumber(keyCode) || Key.isOK(keyCode) - || Key.isHotkey(settings, keyCode) || Key.isHotkey(settings, -keyCode) // press or hold a hotkey - || (keyCode == KeyEvent.KEYCODE_POUND && onText("#")) - || (keyCode == KeyEvent.KEYCODE_STAR && onText("*")) - || super.onKeyDown(keyCode, event); // let the system handle the keys we don't care about (usually, only: KEYCODE_BACK) + || handleHotkey(keyCode, true, false, true) // hold a hotkey, handled in onKeyLongPress()) + || handleHotkey(keyCode, false, keyRepeatCounter + 1 > 0, true) // press a hotkey, handled in onKeyUp() + || Key.isPoundOrStar(keyCode) && onText(String.valueOf((char) event.getUnicodeChar()), true) + || super.onKeyDown(keyCode, event); // let the system handle the keys we don't care about (usually, the touch "buttons") } @@ -161,7 +165,7 @@ abstract class KeyPadHandler extends InputMethodService { lastKeyCode = 0; } - if (handleHotkey(keyCode, true)) { + if (handleHotkey(keyCode, true, false, false)) { return true; } @@ -193,59 +197,62 @@ abstract class KeyPadHandler extends InputMethodService { return true; } - // repeat handling + if (isBackspaceHandled) { + return true; + } + keyRepeatCounter = (lastKeyCode == keyCode) ? keyRepeatCounter + 1 : 0; lastKeyCode = keyCode; if (Key.isNumber(keyCode)) { numKeyRepeatCounter = (lastNumKeyCode == keyCode) ? numKeyRepeatCounter + 1 : 0; lastNumKeyCode = keyCode; - } - - // backspace is handled in onKeyDown only, so we ignore it here - if (isBackspaceHandled) { - return true; - } - - if (Key.isNumber(keyCode)) { return onNumber(Key.codeToNumber(settings, keyCode), false, numKeyRepeatCounter); } - if (Key.isOK(keyCode)) { - return onOK(); + if (Key.isBack(keyCode)) { + return onBack() && super.onKeyUp(keyCode, event); } - if (handleHotkey(keyCode, false)) { - return true; - } - - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_UP: - case KeyEvent.KEYCODE_DPAD_DOWN: - case KeyEvent.KEYCODE_DPAD_LEFT: - case KeyEvent.KEYCODE_DPAD_RIGHT: return onArrow(keyCode, keyRepeatCounter > 0); - } - - // let the system handle the keys we don't care about (usually, only: KEYCODE_BACK) - return super.onKeyUp(keyCode, event); + return + Key.isOK(keyCode) && onOK() + || handleHotkey(keyCode, false, keyRepeatCounter > 0, false) + || Key.isPoundOrStar(keyCode) && onText(String.valueOf((char) event.getUnicodeChar()), false) + || super.onKeyUp(keyCode, event); // let the system handle the keys we don't care about (usually, the touch "buttons") } - private boolean handleHotkey(int keyCode, boolean hold) { + private boolean handleHotkey(int keyCode, boolean hold, boolean repeat, boolean validateOnly) { if (keyCode == settings.getKeyAddWord() * (hold ? -1 : 1)) { - return onKeyAddWord(); + return onKeyAddWord(validateOnly); + } + + if (keyCode == settings.getKeyFilterClear() * (hold ? -1 : 1)) { + return onKeyFilterClear(validateOnly); + } + + if (keyCode == settings.getKeyFilterSuggestions() * (hold ? -1 : 1)) { + return onKeyFilterSuggestions(validateOnly, repeat); } if (keyCode == settings.getKeyNextLanguage() * (hold ? -1 : 1)) { - return onKeyNextLanguage(); + return onKeyNextLanguage(validateOnly); } if (keyCode == settings.getKeyNextInputMode() * (hold ? -1 : 1)) { - return onKeyNextInputMode(); + return onKeyNextInputMode(validateOnly); + } + + if (keyCode == settings.getKeyPreviousSuggestion() * (hold ? -1 : 1)) { + return onKeyScrollSuggestion(validateOnly, true); + } + + if (keyCode == settings.getKeyNextSuggestion() * (hold ? -1 : 1)) { + return onKeyScrollSuggestion(validateOnly, false); } if (keyCode == settings.getKeyShowSettings() * (hold ? -1 : 1)) { - return onKeyShowSettings(); + return onKeyShowSettings(validateOnly); } return false; @@ -261,17 +268,20 @@ abstract class KeyPadHandler extends InputMethodService { // hardware key handlers - abstract protected boolean onArrow(int key, boolean repeat); + abstract protected boolean onBack(); abstract public boolean onBackspace(); abstract protected boolean onNumber(int key, boolean hold, int repeat); abstract public boolean onOK(); - abstract public boolean onText(String text); // used for "#", "*" and whatnot + abstract public boolean onText(String text, boolean validateOnly); // used for "#", "*" and whatnot // hotkey handlers - abstract protected boolean onKeyAddWord(); - abstract protected boolean onKeyNextLanguage(); - abstract protected boolean onKeyNextInputMode(); - abstract protected boolean onKeyShowSettings(); + abstract protected boolean onKeyAddWord(boolean validateOnly); + abstract protected boolean onKeyFilterClear(boolean validateOnly); + abstract protected boolean onKeyFilterSuggestions(boolean validateOnly, boolean repeat); + abstract protected boolean onKeyNextLanguage(boolean validateOnly); + abstract protected boolean onKeyNextInputMode(boolean validateOnly); + abstract protected boolean onKeyScrollSuggestion(boolean validateOnly, boolean backward); + abstract protected boolean onKeyShowSettings(boolean validateOnly); // helpers abstract protected void onInit(); diff --git a/src/io/github/sspanak/tt9/ime/TraditionalT9.java b/src/io/github/sspanak/tt9/ime/TraditionalT9.java index d436e4eb..41f5f1cb 100644 --- a/src/io/github/sspanak/tt9/ime/TraditionalT9.java +++ b/src/io/github/sspanak/tt9/ime/TraditionalT9.java @@ -211,18 +211,8 @@ public class TraditionalT9 extends KeyPadHandler { } - public boolean onArrow(int key, boolean repeat) { - if (key == settings.getKeyFilterClear()) { - return onKeyFilterClear(); - } else if (key == settings.getKeyFilterSuggestions()) { - return onKeyFilterSuggestions(repeat); - } else if (key == settings.getKeyPreviousSuggestion()) { - return onKeyPreviousSuggestion(); - } else if (key == settings.getKeyNextSuggestion()) { - return onKeyNextSuggestion(); - } - - return false; + public boolean onBack() { + return settings.getShowSoftNumpad(); } @@ -307,11 +297,17 @@ public class TraditionalT9 extends KeyPadHandler { } - public boolean onText(String text) { + public boolean onText(String text) { return onText(text, false); } + + public boolean onText(String text, boolean validateOnly) { if (mInputMode.shouldIgnoreText(text)) { return false; } + if (validateOnly) { + return true; + } + cancelAutoAccept(); // accept the previously typed word (if any) @@ -326,22 +322,30 @@ public class TraditionalT9 extends KeyPadHandler { } - public boolean onKeyAddWord() { + public boolean onKeyAddWord(boolean validateOnly) { if (!isInputViewShown() || mInputMode.isNumeric()) { return false; } + if (validateOnly) { + return true; + } + cancelAutoAccept(); showAddWord(); return true; } - public boolean onKeyFilterClear() { - if (suggestionBar.isEmpty()) { + public boolean onKeyFilterClear(boolean validateOnly) { + if (isSuggestionViewHidden()) { return false; } + if (validateOnly) { + return true; + } + cancelAutoAccept(); if (mInputMode.clearWordStem()) { @@ -353,11 +357,15 @@ public class TraditionalT9 extends KeyPadHandler { } - public boolean onKeyFilterSuggestions(boolean repeat) { - if (suggestionBar.isEmpty()) { + public boolean onKeyFilterSuggestions(boolean validateOnly, boolean repeat) { + if (isSuggestionViewHidden()) { return false; } + if (validateOnly) { + return true; + } + cancelAutoAccept(); String filter; @@ -377,68 +385,77 @@ public class TraditionalT9 extends KeyPadHandler { } - public boolean onKeyNextSuggestion() { - if (nextSuggestion()) { - cancelAutoAccept(); - mInputMode.setWordStem(suggestionBar.getCurrentSuggestion(), true); - textField.setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion(), mInputMode); + public boolean onKeyScrollSuggestion(boolean validateOnly, boolean backward) { + if (isSuggestionViewHidden()) { + return false; + } + + if (validateOnly) { return true; } - return false; + cancelAutoAccept(); + if (backward) previousSuggestion(); + else nextSuggestion(); + mInputMode.setWordStem(suggestionBar.getCurrentSuggestion(), true); + textField.setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion(), mInputMode); + return true; } - public boolean onKeyPreviousSuggestion() { - if (previousSuggestion()) { - cancelAutoAccept(); - mInputMode.setWordStem(suggestionBar.getCurrentSuggestion(), true); - textField.setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion(), mInputMode); + public boolean onKeyNextLanguage(boolean validateOnly) { + if (mInputMode.isNumeric() || mEnabledLanguages.size() < 2) { + return false; + } + + if (validateOnly) { return true; } - return false; + cancelAutoAccept(); + commitCurrentSuggestion(false); + clearSuggestions(); + resetKeyRepeat(); + nextLang(); + mInputMode.changeLanguage(mLanguage); + mInputMode.reset(); + + statusBar.setText(mInputMode.toString()); + mainView.render(); + forceShowWindowIfHidden(); + + return true; } - public boolean onKeyNextLanguage() { - if (nextLang()) { - cancelAutoAccept(); - commitCurrentSuggestion(false); - mInputMode.changeLanguage(mLanguage); - mInputMode.reset(); - resetKeyRepeat(); - clearSuggestions(); - statusBar.setText(mInputMode.toString()); - mainView.render(); - forceShowWindowIfHidden(); + public boolean onKeyNextInputMode(boolean validateOnly) { + if (allowedInputModes.size() == 1) { + return false; + } + if (validateOnly) { return true; } - return false; - } - - - public boolean onKeyNextInputMode() { scheduleAutoAccept(mInputMode.getAutoAcceptTimeout()); // restart the timer nextInputMode(); mainView.render(); - if (allowedInputModes.size() == 1) { - return false; - } forceShowWindowIfHidden(); return true; } - public boolean onKeyShowSettings() { + public boolean onKeyShowSettings(boolean validateOnly) { if (!isInputViewShown()) { return false; } + if (validateOnly) { + return true; + } + cancelAutoAccept(); UI.showSettingsScreen(this); return true; @@ -450,27 +467,15 @@ public class TraditionalT9 extends KeyPadHandler { } - private boolean previousSuggestion() { - if (isSuggestionViewHidden()) { - return false; - } - + private void previousSuggestion() { suggestionBar.scrollToSuggestion(-1); textField.setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion(), mInputMode); - - return true; } - private boolean nextSuggestion() { - if (isSuggestionViewHidden()) { - return false; - } - + private void nextSuggestion() { suggestionBar.scrollToSuggestion(1); textField.setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion(), mInputMode); - - return true; } @@ -661,11 +666,7 @@ public class TraditionalT9 extends KeyPadHandler { } - private boolean nextLang() { - if (mInputMode.isNumeric() || mEnabledLanguages.size() < 2) { - return false; - } - + private void nextLang() { // select the next language int previous = mEnabledLanguages.indexOf(mLanguage.getId()); int next = (previous + 1) % mEnabledLanguages.size(); @@ -675,8 +676,6 @@ public class TraditionalT9 extends KeyPadHandler { // save it for the next time settings.saveInputLanguage(mLanguage.getId()); - - return true; } diff --git a/src/io/github/sspanak/tt9/ime/helpers/Key.java b/src/io/github/sspanak/tt9/ime/helpers/Key.java index 0aa62cf5..b7aa610d 100644 --- a/src/io/github/sspanak/tt9/ime/helpers/Key.java +++ b/src/io/github/sspanak/tt9/ime/helpers/Key.java @@ -33,6 +33,14 @@ public class Key { } + public static boolean isBack(int keyCode) { return keyCode == KeyEvent.KEYCODE_BACK; } + + + public static boolean isPoundOrStar(int keyCode) { + return keyCode == KeyEvent.KEYCODE_POUND || keyCode == KeyEvent.KEYCODE_STAR; + } + + public static boolean isOK(int keyCode) { return keyCode == KeyEvent.KEYCODE_DPAD_CENTER diff --git a/src/io/github/sspanak/tt9/ui/main/keys/SoftKey.java b/src/io/github/sspanak/tt9/ui/main/keys/SoftKey.java index 3d4875d0..64e3ed01 100644 --- a/src/io/github/sspanak/tt9/ui/main/keys/SoftKey.java +++ b/src/io/github/sspanak/tt9/ui/main/keys/SoftKey.java @@ -135,14 +135,14 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement int keyId = getId(); - if (keyId == R.id.soft_key_add_word) return tt9.onKeyAddWord(); - if (keyId == R.id.soft_key_filter_suggestions) return tt9.onKeyFilterSuggestions(repeat); - if (keyId == R.id.soft_key_left_arrow) return tt9.onKeyPreviousSuggestion(); - if (keyId == R.id.soft_key_right_arrow) return tt9.onKeyNextSuggestion(); - if (keyId == R.id.soft_key_input_mode) return tt9.onKeyNextInputMode(); - if (keyId == R.id.soft_key_language) return tt9.onKeyNextLanguage(); + if (keyId == R.id.soft_key_add_word) return tt9.onKeyAddWord(false); + if (keyId == R.id.soft_key_filter_suggestions) return tt9.onKeyFilterSuggestions(false, repeat); + if (keyId == R.id.soft_key_left_arrow) return tt9.onKeyScrollSuggestion(false, true); + if (keyId == R.id.soft_key_right_arrow) return tt9.onKeyScrollSuggestion(false, false); + if (keyId == R.id.soft_key_input_mode) return tt9.onKeyNextInputMode(false); + if (keyId == R.id.soft_key_language) return tt9.onKeyNextLanguage(false); if (keyId == R.id.soft_key_ok) return tt9.onOK(); - if (keyId == R.id.soft_key_settings) return tt9.onKeyShowSettings(); + if (keyId == R.id.soft_key_settings) return tt9.onKeyShowSettings(false); return false; }