1
0
Fork 0

fixed inconsistent text case visualization and optimized the rendering speed

This commit is contained in:
sspanak 2025-06-11 18:02:22 +03:00 committed by Dimo Karaivanov
parent 903e756dc0
commit b26aba2273
8 changed files with 62 additions and 34 deletions

View file

@ -234,9 +234,7 @@ public abstract class HotkeyHandler extends CommandHandler {
mInputMode.onAcceptSuggestion(suggestionOps.acceptIncomplete()); mInputMode.onAcceptSuggestion(suggestionOps.acceptIncomplete());
resetKeyRepeat(); resetKeyRepeat();
if (settings.isMainLayoutNumpad()) { mainView.renderDynamicKeys();
mainView.renderKeys();
}
return true; return true;
} }
@ -273,9 +271,7 @@ public abstract class HotkeyHandler extends CommandHandler {
.loadSuggestions(filter); .loadSuggestions(filter);
} }
if (settings.isMainLayoutNumpad()) { mainView.renderDynamicKeys();
mainView.renderKeys();
}
return true; return true;
} }
@ -292,9 +288,7 @@ public abstract class HotkeyHandler extends CommandHandler {
backward = isLanguageRTL != backward; backward = isLanguageRTL != backward;
scrollSuggestions(backward); scrollSuggestions(backward);
if (settings.isMainLayoutNumpad()) { mainView.renderDynamicKeys();
mainView.renderKeys();
}
return true; return true;
} }

View file

@ -120,9 +120,7 @@ public abstract class TypingHandler extends KeyPadHandler {
if (appHacks.onBackspace(settings, mInputMode)) { if (appHacks.onBackspace(settings, mInputMode)) {
mInputMode.reset(); mInputMode.reset();
if (settings.isMainLayoutNumpad()) { mainView.renderDynamicKeys();
mainView.renderKeys();
}
return false; return false;
} }
@ -147,6 +145,7 @@ public abstract class TypingHandler extends KeyPadHandler {
if (settings.getBackspaceRecomposing() && repeat == 0 && noTextSelection && suggestionOps.isEmpty() && !DictionaryLoader.getInstance(this).isRunning()) { if (settings.getBackspaceRecomposing() && repeat == 0 && noTextSelection && suggestionOps.isEmpty() && !DictionaryLoader.getInstance(this).isRunning()) {
final String previousWord = mInputMode.recompose(); final String previousWord = mInputMode.recompose();
if (textField.recompose(previousWord)) { if (textField.recompose(previousWord)) {
mInputMode.setOnEndRecomposing(this::updateShiftState);
getSuggestions(previousWord); getSuggestions(previousWord);
} else { } else {
mInputMode.reset(); mInputMode.reset();
@ -233,9 +232,7 @@ public abstract class TypingHandler extends KeyPadHandler {
autoCorrectSpace(text, true, -1); autoCorrectSpace(text, true, -1);
forceShowWindow(); forceShowWindow();
if (settings.isMainLayoutNumpad()) { mainView.renderDynamicKeys();
mainView.renderKeys();
}
return true; return true;
} }
@ -375,9 +372,7 @@ public abstract class TypingHandler extends KeyPadHandler {
mInputMode.onAcceptSuggestion(word, true); mInputMode.onAcceptSuggestion(word, true);
autoCorrectSpace(word, false, mInputMode.getSequence().isEmpty() ? -1 : mInputMode.getSequence().charAt(0) - '0'); autoCorrectSpace(word, false, mInputMode.getSequence().isEmpty() ? -1 : mInputMode.getSequence().charAt(0) - '0');
mInputMode.determineNextWordTextCase(-1); mInputMode.determineNextWordTextCase(-1);
if (settings.isMainLayoutNumpad()) { updateShiftState();
mainView.renderKeys();
}
} }
private void onAcceptSuggestionsDelayed(String word) { private void onAcceptSuggestionsDelayed(String word) {
@ -390,9 +385,6 @@ public abstract class TypingHandler extends KeyPadHandler {
if (!word.isEmpty()) { if (!word.isEmpty()) {
autoCorrectSpace(word, true, fromKey); autoCorrectSpace(word, true, fromKey);
resetKeyRepeat(); resetKeyRepeat();
if (settings.isMainLayoutNumpad()) {
mainView.renderKeys();
}
} }
} }
@ -439,13 +431,9 @@ public abstract class TypingHandler extends KeyPadHandler {
String trimmedWord = suggestionOps.getCurrent(mLanguage, mInputMode.getSequenceLength()); String trimmedWord = suggestionOps.getCurrent(mLanguage, mInputMode.getSequenceLength());
appHacks.setComposingTextWithHighlightedStem(trimmedWord, mInputMode); appHacks.setComposingTextWithHighlightedStem(trimmedWord, mInputMode);
if (new Text(suggestionOps.getCurrent()).isAlphabetic()) { if (!suggestionOps.isEmpty() && new Text(suggestionOps.getCurrent()).isAlphabetic()) {
setStatusIcon(mInputMode, mLanguage); updateShiftState();
if (settings.isMainLayoutNumpad()) {
mainView.renderKeys();
}
} }
forceShowWindow(); forceShowWindow();
} }
@ -456,4 +444,13 @@ public abstract class TypingHandler extends KeyPadHandler {
mInputMode.setWordStem(suggestionOps.getCurrent(), true); mInputMode.setWordStem(suggestionOps.getCurrent(), true);
appHacks.setComposingTextWithHighlightedStem(suggestionOps.getCurrent(), mInputMode); appHacks.setComposingTextWithHighlightedStem(suggestionOps.getCurrent(), mInputMode);
} }
protected void updateShiftState() {
setStatusIcon(mInputMode, mLanguage);
mainView.renderDynamicKeys();
if (!mainView.isTextEditingPaletteShown() && !mainView.isCommandPaletteShown()) {
statusBar.setText(mInputMode);
}
}
} }

View file

@ -79,6 +79,10 @@ abstract class UiHandler extends AbstractHandler {
protected void setStatusIcon(@Nullable InputMode mode, @Nullable Language language) { 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 displayTextCase = getDisplayTextCase(language, mode != null ? mode.getTextCase() : InputMode.CASE_UNDEFINED);
final int resId = new StatusIcon(settings, mode, language, displayTextCase).resourceId; final int resId = new StatusIcon(settings, mode, language, displayTextCase).resourceId;
if (resId == 0) { if (resId == 0) {

View file

@ -39,6 +39,7 @@ abstract public class InputMode {
@NonNull protected String digitSequence = ""; @NonNull protected String digitSequence = "";
protected final boolean isEmailMode; protected final boolean isEmailMode;
@NonNull protected Language language = new NullLanguage(); @NonNull protected Language language = new NullLanguage();
@NonNull protected Runnable onEndRecomposing = () -> {};
protected final SettingsStore settings; protected final SettingsStore settings;
@NonNull protected final ArrayList<String> suggestions = new ArrayList<>(); @NonNull protected final ArrayList<String> suggestions = new ArrayList<>();
@NonNull protected Runnable onSuggestionsUpdated = () -> {}; @NonNull protected Runnable onSuggestionsUpdated = () -> {};
@ -164,6 +165,7 @@ abstract public class InputMode {
public void beforeDeleteText() {} public void beforeDeleteText() {}
public String recompose() { return null; } public String recompose() { return null; }
public void setOnEndRecomposing(Runnable r) { onEndRecomposing = r != null ? r : () -> {}; }
public void replaceLastLetter() {} public void replaceLastLetter() {}
public void reset() { public void reset() {

View file

@ -33,6 +33,7 @@ class ModeWords extends ModeCheonjiin {
// text analysis tools // text analysis tools
private final AutoTextCase autoTextCase; private final AutoTextCase autoTextCase;
private boolean isCursorDirectionForward = false; private boolean isCursorDirectionForward = false;
private boolean isRecomposing = false;
private int textFieldTextCase; private int textFieldTextCase;
@ -76,6 +77,7 @@ class ModeWords extends ModeCheonjiin {
if (digitSequence.isEmpty()) { if (digitSequence.isEmpty()) {
clearWordStem(); clearWordStem();
endRecomposing();
} else if (stem.length() > digitSequence.length()) { } else if (stem.length() > digitSequence.length()) {
stem = stem.substring(0, digitSequence.length()); stem = stem.substring(0, digitSequence.length());
} }
@ -123,6 +125,7 @@ class ModeWords extends ModeCheonjiin {
@Override @Override
public String recompose() { public String recompose() {
isRecomposing = false;
if (!language.hasSpaceBetweenWords() || language.isTranscribed()) { if (!language.hasSpaceBetweenWords() || language.isTranscribed()) {
return null; return null;
} }
@ -144,6 +147,7 @@ class ModeWords extends ModeCheonjiin {
reset(); reset();
digitSequence = language.getDigitSequenceForWord(previousWord); digitSequence = language.getDigitSequenceForWord(previousWord);
textCase = new Text(language, previousWord).getTextCase(); textCase = new Text(language, previousWord).getTextCase();
isRecomposing = true;
} catch (InvalidLanguageCharactersException e) { } catch (InvalidLanguageCharactersException e) {
Logger.d(LOG_TAG, "Not recomposing word: '" + previousWord + "'. " + e.getMessage()); Logger.d(LOG_TAG, "Not recomposing word: '" + previousWord + "'. " + e.getMessage());
return null; return null;
@ -152,6 +156,14 @@ class ModeWords extends ModeCheonjiin {
return previousWord; return previousWord;
} }
private void endRecomposing() {
if (isRecomposing) {
isRecomposing = false;
textCase = settings.getTextCase();
onEndRecomposing.run();
}
}
@Override @Override
public void reset() { public void reset() {
basicReset(); basicReset();
@ -315,6 +327,7 @@ class ModeWords extends ModeCheonjiin {
clearLastAcceptedWord(); clearLastAcceptedWord();
} else { } else {
reset(); reset();
endRecomposing();
} }
stem = ""; stem = "";

View file

@ -16,6 +16,7 @@ import androidx.annotation.RequiresApi;
import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsCompat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import io.github.sspanak.tt9.R; import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.ime.TraditionalT9; import io.github.sspanak.tt9.ime.TraditionalT9;
@ -32,6 +33,7 @@ abstract class BaseMainLayout {
protected View view = null; protected View view = null;
@NonNull protected final ArrayList<SoftKey> keys = new ArrayList<>(); @NonNull protected final ArrayList<SoftKey> keys = new ArrayList<>();
@NonNull protected final HashSet<Integer> dynamicKeys = new HashSet<>();
BaseMainLayout(TraditionalT9 tt9, int xml) { BaseMainLayout(TraditionalT9 tt9, int xml) {
@ -311,11 +313,26 @@ abstract class BaseMainLayout {
abstract void render(); 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<Integer> keyIds) {
if (keyIds != null && keyIds.isEmpty()) {
return;
}
for (SoftKey key : getKeys()) { for (SoftKey key : getKeys()) {
key.render(); if (keyIds == null || keyIds.contains(key.getId())) {
key.render();
}
} }
} }
void renderKeys() {
renderKeys(null);
}
void renderDynamicKeys() {
renderKeys(dynamicKeys);
}
} }

View file

@ -30,6 +30,8 @@ class MainLayoutNumpad extends BaseMainLayout {
MainLayoutNumpad(TraditionalT9 tt9) { MainLayoutNumpad(TraditionalT9 tt9) {
super(tt9, R.layout.main_numpad); super(tt9, R.layout.main_numpad);
dynamicKeys.add(R.id.soft_key_filter);
dynamicKeys.add(R.id.soft_key_shift);
} }

View file

@ -18,7 +18,6 @@ public class MainView {
protected MainView(TraditionalT9 tt9) { protected MainView(TraditionalT9 tt9) {
this.tt9 = tt9; this.tt9 = tt9;
forceCreate(); forceCreate();
} }
@ -78,13 +77,13 @@ public class MainView {
main.render(); main.render();
} }
public void renderKeys() { public void renderDynamicKeys() {
if (main == null) { 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; return;
} }
main.renderKeys(); main.renderDynamicKeys();
} }
public void showCommandPalette() { public void showCommandPalette() {