diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/HotkeyHandler.java b/app/src/main/java/io/github/sspanak/tt9/ime/HotkeyHandler.java index cda1be42..75b68860 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/HotkeyHandler.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/HotkeyHandler.java @@ -234,9 +234,7 @@ public abstract class HotkeyHandler extends CommandHandler { mInputMode.onAcceptSuggestion(suggestionOps.acceptIncomplete()); resetKeyRepeat(); - if (settings.isMainLayoutNumpad()) { - mainView.renderKeys(); - } + mainView.renderDynamicKeys(); return true; } @@ -273,9 +271,7 @@ public abstract class HotkeyHandler extends CommandHandler { .loadSuggestions(filter); } - if (settings.isMainLayoutNumpad()) { - mainView.renderKeys(); - } + mainView.renderDynamicKeys(); return true; } @@ -292,9 +288,7 @@ public abstract class HotkeyHandler extends CommandHandler { backward = isLanguageRTL != backward; scrollSuggestions(backward); - if (settings.isMainLayoutNumpad()) { - mainView.renderKeys(); - } + mainView.renderDynamicKeys(); return true; } diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/TypingHandler.java b/app/src/main/java/io/github/sspanak/tt9/ime/TypingHandler.java index 012a7e0e..0501b350 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/TypingHandler.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/TypingHandler.java @@ -120,9 +120,7 @@ public abstract class TypingHandler extends KeyPadHandler { if (appHacks.onBackspace(settings, mInputMode)) { mInputMode.reset(); - if (settings.isMainLayoutNumpad()) { - mainView.renderKeys(); - } + mainView.renderDynamicKeys(); return false; } @@ -147,6 +145,7 @@ public abstract class TypingHandler extends KeyPadHandler { if (settings.getBackspaceRecomposing() && repeat == 0 && noTextSelection && suggestionOps.isEmpty() && !DictionaryLoader.getInstance(this).isRunning()) { final String previousWord = mInputMode.recompose(); if (textField.recompose(previousWord)) { + mInputMode.setOnEndRecomposing(this::updateShiftState); getSuggestions(previousWord); } else { mInputMode.reset(); @@ -233,9 +232,7 @@ public abstract class TypingHandler extends KeyPadHandler { autoCorrectSpace(text, true, -1); forceShowWindow(); - if (settings.isMainLayoutNumpad()) { - mainView.renderKeys(); - } + mainView.renderDynamicKeys(); return true; } @@ -375,9 +372,7 @@ public abstract class TypingHandler extends KeyPadHandler { mInputMode.onAcceptSuggestion(word, true); autoCorrectSpace(word, false, mInputMode.getSequence().isEmpty() ? -1 : mInputMode.getSequence().charAt(0) - '0'); mInputMode.determineNextWordTextCase(-1); - if (settings.isMainLayoutNumpad()) { - mainView.renderKeys(); - } + updateShiftState(); } private void onAcceptSuggestionsDelayed(String word) { @@ -390,9 +385,6 @@ public abstract class TypingHandler extends KeyPadHandler { if (!word.isEmpty()) { autoCorrectSpace(word, true, fromKey); resetKeyRepeat(); - if (settings.isMainLayoutNumpad()) { - mainView.renderKeys(); - } } } @@ -439,13 +431,9 @@ public abstract class TypingHandler extends KeyPadHandler { String trimmedWord = suggestionOps.getCurrent(mLanguage, mInputMode.getSequenceLength()); appHacks.setComposingTextWithHighlightedStem(trimmedWord, mInputMode); - if (new Text(suggestionOps.getCurrent()).isAlphabetic()) { - setStatusIcon(mInputMode, mLanguage); - if (settings.isMainLayoutNumpad()) { - mainView.renderKeys(); - } + if (!suggestionOps.isEmpty() && new Text(suggestionOps.getCurrent()).isAlphabetic()) { + updateShiftState(); } - forceShowWindow(); } @@ -456,4 +444,13 @@ public abstract class TypingHandler extends KeyPadHandler { mInputMode.setWordStem(suggestionOps.getCurrent(), true); appHacks.setComposingTextWithHighlightedStem(suggestionOps.getCurrent(), mInputMode); } + + + protected void updateShiftState() { + setStatusIcon(mInputMode, mLanguage); + mainView.renderDynamicKeys(); + if (!mainView.isTextEditingPaletteShown() && !mainView.isCommandPaletteShown()) { + statusBar.setText(mInputMode); + } + } } diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/UiHandler.java b/app/src/main/java/io/github/sspanak/tt9/ime/UiHandler.java index 8d1b2015..bf041d3e 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/UiHandler.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/UiHandler.java @@ -79,6 +79,10 @@ abstract class UiHandler extends AbstractHandler { protected void setStatusIcon(@Nullable InputMode mode, @Nullable Language language) { + if (!settings.isStatusIconEnabled()) { + return; + } + final int displayTextCase = getDisplayTextCase(language, mode != null ? mode.getTextCase() : InputMode.CASE_UNDEFINED); final int resId = new StatusIcon(settings, mode, language, displayTextCase).resourceId; if (resId == 0) { diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java index 8d5e2601..835fbd3b 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java @@ -39,6 +39,7 @@ abstract public class InputMode { @NonNull protected String digitSequence = ""; protected final boolean isEmailMode; @NonNull protected Language language = new NullLanguage(); + @NonNull protected Runnable onEndRecomposing = () -> {}; protected final SettingsStore settings; @NonNull protected final ArrayList suggestions = new ArrayList<>(); @NonNull protected Runnable onSuggestionsUpdated = () -> {}; @@ -164,6 +165,7 @@ abstract public class InputMode { public void beforeDeleteText() {} public String recompose() { return null; } + public void setOnEndRecomposing(Runnable r) { onEndRecomposing = r != null ? r : () -> {}; } public void replaceLastLetter() {} public void reset() { diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java index 7dd9dc6f..df67d8e3 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java @@ -33,6 +33,7 @@ class ModeWords extends ModeCheonjiin { // text analysis tools private final AutoTextCase autoTextCase; private boolean isCursorDirectionForward = false; + private boolean isRecomposing = false; private int textFieldTextCase; @@ -76,6 +77,7 @@ class ModeWords extends ModeCheonjiin { if (digitSequence.isEmpty()) { clearWordStem(); + endRecomposing(); } else if (stem.length() > digitSequence.length()) { stem = stem.substring(0, digitSequence.length()); } @@ -123,6 +125,7 @@ class ModeWords extends ModeCheonjiin { @Override public String recompose() { + isRecomposing = false; if (!language.hasSpaceBetweenWords() || language.isTranscribed()) { return null; } @@ -144,6 +147,7 @@ class ModeWords extends ModeCheonjiin { reset(); digitSequence = language.getDigitSequenceForWord(previousWord); textCase = new Text(language, previousWord).getTextCase(); + isRecomposing = true; } catch (InvalidLanguageCharactersException e) { Logger.d(LOG_TAG, "Not recomposing word: '" + previousWord + "'. " + e.getMessage()); return null; @@ -152,6 +156,14 @@ class ModeWords extends ModeCheonjiin { return previousWord; } + private void endRecomposing() { + if (isRecomposing) { + isRecomposing = false; + textCase = settings.getTextCase(); + onEndRecomposing.run(); + } + } + @Override public void reset() { basicReset(); @@ -315,6 +327,7 @@ class ModeWords extends ModeCheonjiin { clearLastAcceptedWord(); } else { reset(); + endRecomposing(); } stem = ""; diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/BaseMainLayout.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/BaseMainLayout.java index 355642fb..970350a7 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/BaseMainLayout.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/BaseMainLayout.java @@ -16,6 +16,7 @@ import androidx.annotation.RequiresApi; import androidx.core.view.WindowInsetsCompat; import java.util.ArrayList; +import java.util.HashSet; import io.github.sspanak.tt9.R; import io.github.sspanak.tt9.ime.TraditionalT9; @@ -32,6 +33,7 @@ abstract class BaseMainLayout { protected View view = null; @NonNull protected final ArrayList keys = new ArrayList<>(); + @NonNull protected final HashSet dynamicKeys = new HashSet<>(); BaseMainLayout(TraditionalT9 tt9, int xml) { @@ -311,11 +313,26 @@ abstract class BaseMainLayout { abstract void render(); /** - * Run render only on the keys, for example, to refresh their state. + * Render specific keys to update their state. If the list is empty, no keys are rendered. If the + * list is null, all keys are rendered. */ - void renderKeys() { + private void renderKeys(@Nullable HashSet keyIds) { + if (keyIds != null && keyIds.isEmpty()) { + return; + } + for (SoftKey key : getKeys()) { - key.render(); + if (keyIds == null || keyIds.contains(key.getId())) { + key.render(); + } } } + + void renderKeys() { + renderKeys(null); + } + + void renderDynamicKeys() { + renderKeys(dynamicKeys); + } } diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java index a471e932..bb60833b 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java @@ -30,6 +30,8 @@ class MainLayoutNumpad extends BaseMainLayout { MainLayoutNumpad(TraditionalT9 tt9) { super(tt9, R.layout.main_numpad); + dynamicKeys.add(R.id.soft_key_filter); + dynamicKeys.add(R.id.soft_key_shift); } diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/MainView.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/MainView.java index a85c9f71..66dec650 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/MainView.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/MainView.java @@ -18,7 +18,6 @@ public class MainView { protected MainView(TraditionalT9 tt9) { this.tt9 = tt9; - forceCreate(); } @@ -78,13 +77,13 @@ public class MainView { main.render(); } - public void renderKeys() { + public void renderDynamicKeys() { if (main == null) { - Logger.e(LOG_TAG, "Cannot render keys for a null MainView."); + Logger.e(LOG_TAG, "Cannot render dynamic keys for a null MainView."); return; } - main.renderKeys(); + main.renderDynamicKeys(); } public void showCommandPalette() {