fixed inconsistencies between the current text case the status icon and the virtual Shift key icon
This commit is contained in:
parent
e66e7f7c61
commit
c9e5573b58
10 changed files with 63 additions and 37 deletions
|
|
@ -217,27 +217,26 @@ abstract public class CommandHandler extends TextEditingHandler {
|
|||
return false;
|
||||
}
|
||||
|
||||
// When there are no suggestions, there is no need to execute the code below for adjusting their text case.
|
||||
if (mInputMode.getSuggestions().isEmpty()) {
|
||||
// if there are no suggestions or they are special chars, we don't need to adjust their text case
|
||||
final String before = suggestionOps.getCurrent();
|
||||
boolean beforeStartsWithLetter = !before.isEmpty() && Character.isAlphabetic(before.charAt(0));
|
||||
if (!beforeStartsWithLetter) {
|
||||
settings.saveTextCase(mInputMode.getTextCase());
|
||||
return true;
|
||||
}
|
||||
|
||||
// When we are in AUTO mode and current dictionary word is in uppercase,
|
||||
// the mode would switch to UPPERCASE, but visually, the word would not change.
|
||||
// This is why we retry, until there is a visual change.
|
||||
String before = suggestionOps.get(0);
|
||||
boolean beforeStartsWithLetter = !before.isEmpty() && Character.isAlphabetic(before.charAt(0));
|
||||
for (int retries = 0; beforeStartsWithLetter && retries < 2 && mInputMode.nextTextCase(); retries++) {
|
||||
String after = mInputMode.getSuggestions().get(0);
|
||||
if (!after.equals(before)) {
|
||||
// This is why we retry using the code below, until there is a visual change.
|
||||
int currentSuggestionIndex = suggestionOps.getCurrentIndex();
|
||||
currentSuggestionIndex = suggestionOps.containsStem() ? currentSuggestionIndex - 1 : currentSuggestionIndex;
|
||||
|
||||
for (int retries = 0; retries <= 2; retries++) {
|
||||
if (!before.equals(mInputMode.getSuggestions().get(currentSuggestionIndex)) || !mInputMode.nextTextCase()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int currentSuggestionIndex = suggestionOps.getCurrentIndex();
|
||||
currentSuggestionIndex = suggestionOps.containsStem() ? currentSuggestionIndex - 1 : currentSuggestionIndex;
|
||||
|
||||
suggestionOps.set(mInputMode.getSuggestions(), currentSuggestionIndex, mInputMode.containsGeneratedSuggestions());
|
||||
textField.setComposingText(suggestionOps.getCurrent());
|
||||
|
||||
|
|
|
|||
|
|
@ -150,11 +150,14 @@ public abstract class TypingHandler extends KeyPadHandler {
|
|||
mInputMode.reset();
|
||||
}
|
||||
|
||||
setStatusIcon(mInputMode, mLanguage);
|
||||
|
||||
if (!mainView.isTextEditingPaletteShown() && !mainView.isCommandPaletteShown()) {
|
||||
statusBar.setText(mInputMode);
|
||||
}
|
||||
}
|
||||
|
||||
// this updates Shift and Filter, so we can't do it only when recomposing
|
||||
if (settings.isMainLayoutNumpad()) {
|
||||
mainView.renderKeys();
|
||||
}
|
||||
|
|
@ -190,14 +193,11 @@ public abstract class TypingHandler extends KeyPadHandler {
|
|||
String lastWord = suggestionOps.acceptIncompleteAndKeepList();
|
||||
mInputMode.onAcceptSuggestion(lastWord);
|
||||
autoCorrectSpace(lastWord, false, key);
|
||||
if (settings.isMainLayoutNumpad()) {
|
||||
mainView.renderKeys();
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-adjust the text case before each word, if the InputMode supports it.
|
||||
if (mInputMode.getSuggestions().isEmpty()) {
|
||||
mInputMode.determineNextWordTextCase();
|
||||
mInputMode.determineNextWordTextCase(key);
|
||||
}
|
||||
|
||||
if (!mInputMode.onNumber(key, hold, repeat)) {
|
||||
|
|
@ -379,7 +379,7 @@ public abstract class TypingHandler extends KeyPadHandler {
|
|||
protected void onAcceptSuggestionAutomatically(String word) {
|
||||
mInputMode.onAcceptSuggestion(word, true);
|
||||
autoCorrectSpace(word, false, mInputMode.getSequence().isEmpty() ? -1 : mInputMode.getSequence().charAt(0) - '0');
|
||||
mInputMode.determineNextWordTextCase();
|
||||
mInputMode.determineNextWordTextCase(-1);
|
||||
if (settings.isMainLayoutNumpad()) {
|
||||
mainView.renderKeys();
|
||||
}
|
||||
|
|
@ -444,6 +444,11 @@ public abstract class TypingHandler extends KeyPadHandler {
|
|||
String trimmedWord = suggestionOps.getCurrent(mLanguage, mInputMode.getSequenceLength());
|
||||
appHacks.setComposingTextWithHighlightedStem(trimmedWord, mInputMode);
|
||||
|
||||
setStatusIcon(mInputMode, mLanguage);
|
||||
if (settings.isMainLayoutNumpad()) {
|
||||
mainView.renderKeys();
|
||||
}
|
||||
|
||||
forceShowWindow();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
|||
import io.github.sspanak.tt9.ui.StatusIcon;
|
||||
import io.github.sspanak.tt9.ui.main.ResizableMainView;
|
||||
import io.github.sspanak.tt9.ui.tray.StatusBar;
|
||||
import io.github.sspanak.tt9.util.Text;
|
||||
import io.github.sspanak.tt9.util.sys.DeviceInfo;
|
||||
import io.github.sspanak.tt9.util.sys.SystemSettings;
|
||||
|
||||
|
|
@ -55,8 +56,23 @@ abstract class UiHandler extends AbstractHandler {
|
|||
}
|
||||
|
||||
|
||||
public int getDisplayTextCase(Language language, int modeTextCase) {
|
||||
boolean hasUpperCase = language != null && language.hasUpperCase();
|
||||
if (!hasUpperCase) {
|
||||
return InputMode.CASE_UNDEFINED;
|
||||
}
|
||||
|
||||
if (modeTextCase == InputMode.CASE_UPPER) {
|
||||
return InputMode.CASE_UPPER;
|
||||
}
|
||||
|
||||
int wordTextCase = new Text(language, getSuggestionOps().getCurrent()).getTextCase();
|
||||
return wordTextCase == InputMode.CASE_UPPER ? InputMode.CASE_CAPITALIZE : wordTextCase;
|
||||
}
|
||||
|
||||
|
||||
protected void setStatusIcon(InputMode mode, Language language) {
|
||||
int resId = new StatusIcon(settings, mode, language).resourceId;
|
||||
int resId = new StatusIcon(settings, mode, language, getDisplayTextCase(language, mode.getTextCase())).resourceId;
|
||||
if (resId == 0) {
|
||||
hideStatusIcon();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ abstract public class InputMode {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void determineNextWordTextCase() {}
|
||||
public void determineNextWordTextCase(int nextDigit) {}
|
||||
|
||||
// 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) { return word; }
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class ModeIdeograms extends ModeWords {
|
|||
|
||||
|
||||
@Override protected String adjustSuggestionTextCase(String word, int newTextCase) { return word; }
|
||||
@Override public void determineNextWordTextCase() {}
|
||||
@Override public void determineNextWordTextCase(int nextDigit) {}
|
||||
@Override public boolean nextTextCase() { return false; }
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ class ModeWords extends ModeCheonjiin {
|
|||
protected ModeWords(SettingsStore settings, Language lang, InputType inputType, TextField textField) {
|
||||
super(settings, inputType, textField);
|
||||
|
||||
autoTextCase = new AutoTextCase(settings, inputType);
|
||||
seq = new Sequences();
|
||||
autoTextCase = new AutoTextCase(settings, seq, inputType);
|
||||
|
||||
setLanguage(lang);
|
||||
defaultTextCase();
|
||||
|
|
@ -343,8 +343,8 @@ class ModeWords extends ModeCheonjiin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void determineNextWordTextCase() {
|
||||
textCase = autoTextCase.determineNextWordTextCase(textCase, textFieldTextCase, textField.getStringBeforeCursor(), digitSequence);
|
||||
public void determineNextWordTextCase(int nextDigit) {
|
||||
textCase = autoTextCase.determineNextWordTextCase(language, textCase, textFieldTextCase, textField.getStringBeforeCursor(), digitSequence + nextDigit);
|
||||
}
|
||||
|
||||
private void determineTextFieldTextCase() {
|
||||
|
|
|
|||
|
|
@ -5,15 +5,18 @@ import androidx.annotation.Nullable;
|
|||
|
||||
import io.github.sspanak.tt9.hacks.InputType;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||
import io.github.sspanak.tt9.util.Text;
|
||||
|
||||
public class AutoTextCase {
|
||||
@NonNull private final Sequences sequences;
|
||||
@NonNull private final SettingsStore settings;
|
||||
private final boolean isUs;
|
||||
|
||||
|
||||
public AutoTextCase(@NonNull SettingsStore settingsStore, @Nullable InputType inputType) {
|
||||
public AutoTextCase(@NonNull SettingsStore settingsStore, @NonNull Sequences sequences, @Nullable InputType inputType) {
|
||||
this.sequences = sequences;
|
||||
settings = settingsStore;
|
||||
isUs = inputType != null && inputType.isUs();
|
||||
}
|
||||
|
|
@ -44,7 +47,7 @@ public class AutoTextCase {
|
|||
* For example, this function will return CASE_LOWER by default, but CASE_UPPER at the beginning
|
||||
* of a sentence.
|
||||
*/
|
||||
public int determineNextWordTextCase(int currentTextCase, int textFieldTextCase, String beforeCursor, String digitSequence) {
|
||||
public int determineNextWordTextCase(Language language, int currentTextCase, int textFieldTextCase, String beforeCursor, String digitSequence) {
|
||||
if (
|
||||
// When the setting is off, don't do any changes.
|
||||
!settings.getAutoTextCase()
|
||||
|
|
@ -56,7 +59,6 @@ public class AutoTextCase {
|
|||
return currentTextCase;
|
||||
}
|
||||
|
||||
|
||||
if (textFieldTextCase != InputMode.CASE_UNDEFINED) {
|
||||
return textFieldTextCase;
|
||||
}
|
||||
|
|
@ -77,10 +79,8 @@ public class AutoTextCase {
|
|||
return InputMode.CASE_CAPITALIZE;
|
||||
}
|
||||
|
||||
// This is mostly for English "I", inserted in the middle of a word. However, we don't want to
|
||||
// enforce lowercase for words like "-ROM" in "CD-ROM". We have to use the digitSequence here,
|
||||
// because the composing text is not yet set in some cases, when this is called.
|
||||
if (Text.isNextToWord(beforeCursor) && !digitSequence.startsWith("1")) {
|
||||
// Prevent English "I", inserted in the middle of a word, from being uppercase.
|
||||
if (sequences.isEnglishI(language, digitSequence) && Text.isNextToWord(beforeCursor)) {
|
||||
return InputMode.CASE_LOWER;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ package io.github.sspanak.tt9.ime.modes.helpers;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||
|
||||
public class Sequences {
|
||||
public static final int CHARS_0_KEY = 0;
|
||||
public static final int CHARS_0_CODE = CHARS_0_KEY + '0';
|
||||
|
|
@ -73,4 +76,8 @@ public class Sequences {
|
|||
|| sequence.startsWith(CHARS_GROUP_0_SEQUENCE)
|
||||
|| sequence.startsWith(CHARS_GROUP_1_SEQUENCE);
|
||||
}
|
||||
|
||||
public boolean isEnglishI(@Nullable Language language, @NonNull String digitSequence) {
|
||||
return LanguageKind.isEnglish(language) && digitSequence.equals("4");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -20,7 +20,7 @@ public class SoftKeyShift extends BaseSoftKeyWithIcons {
|
|||
}
|
||||
|
||||
@Override protected int getCentralIcon() {
|
||||
final int textCase = tt9 != null ? tt9.getTextCase() : InputMode.CASE_UNDEFINED;
|
||||
final int textCase = tt9 != null ? tt9.getDisplayTextCase(tt9.getLanguage(), tt9.getTextCase()) : InputMode.CASE_UNDEFINED;
|
||||
return switch (textCase) {
|
||||
case InputMode.CASE_CAPITALIZE -> R.drawable.ic_fn_shift_caps;
|
||||
case InputMode.CASE_UPPER -> R.drawable.ic_fn_shift_up;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue