1
0
Fork 0

fixed more problems regarding Shift and automatic text case

This commit is contained in:
sspanak 2025-06-19 14:59:01 +03:00 committed by Dimo Karaivanov
parent 62e8a08576
commit 548041be28
7 changed files with 30 additions and 46 deletions

View file

@ -209,10 +209,12 @@ abstract public class CommandHandler extends TextEditingHandler {
protected boolean nextTextCase() { protected boolean nextTextCase() {
if (!mInputMode.nextTextCase(true)) { if (!mInputMode.nextTextCase()) {
return false; return false;
} }
mInputMode.skipNextTextCaseDetection();
// if there are no suggestions or they are special chars, we don't need to adjust their text case // if there are no suggestions or they are special chars, we don't need to adjust their text case
final String currentWord = suggestionOps.isEmpty() || mInputMode.getSequence().isEmpty() ? "" : suggestionOps.getCurrent(); final String currentWord = suggestionOps.isEmpty() || mInputMode.getSequence().isEmpty() ? "" : suggestionOps.getCurrent();
if (currentWord.isEmpty() || !Character.isAlphabetic(currentWord.charAt(0))) { if (currentWord.isEmpty() || !Character.isAlphabetic(currentWord.charAt(0))) {
@ -227,7 +229,7 @@ abstract public class CommandHandler extends TextEditingHandler {
currentSuggestionIndex = suggestionOps.containsStem() ? currentSuggestionIndex - 1 : currentSuggestionIndex; currentSuggestionIndex = suggestionOps.containsStem() ? currentSuggestionIndex - 1 : currentSuggestionIndex;
for (int retries = 0; retries <= 2; retries++) { for (int retries = 0; retries <= 2; retries++) {
if (!currentWord.equals(mInputMode.getSuggestions().get(currentSuggestionIndex)) || !mInputMode.nextTextCase(false)) { if (!currentWord.equals(mInputMode.getSuggestions().get(currentSuggestionIndex)) || !mInputMode.nextTextCase()) {
break; break;
} }
} }

View file

@ -146,15 +146,10 @@ 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();
} }
if (!mainView.isTextEditingPaletteShown() && !mainView.isCommandPaletteShown()) {
statusBar.setText(mInputMode);
}
} }
return true; return true;
@ -432,7 +427,7 @@ 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);
updateShiftState(false, true); updateShiftState(mInputMode.getSuggestions().isEmpty(), true);
forceShowWindow(); forceShowWindow();
} }
@ -445,8 +440,8 @@ public abstract class TypingHandler extends KeyPadHandler {
} }
protected void updateShiftState(boolean determineTextCase, boolean onlyWhenWords) { protected void updateShiftState(boolean determineTextCase, boolean onlyWhenLetters) {
if (onlyWhenWords && (suggestionOps.isEmpty() || !new Text(suggestionOps.getCurrent()).isAlphabetic())) { if (onlyWhenLetters && !new Text(suggestionOps.getCurrent()).isAlphabetic()) {
return; return;
} }
@ -460,9 +455,4 @@ public abstract class TypingHandler extends KeyPadHandler {
statusBar.setText(mInputMode); statusBar.setText(mInputMode);
} }
} }
protected void updateShiftState() {
updateShiftState(false, false);
}
} }

View file

@ -73,7 +73,7 @@ abstract class UiHandler extends AbstractHandler {
return modeTextCase; return modeTextCase;
} }
int wordTextCase = currentWord.getTextCase(); final int wordTextCase = currentWord.getTextCase();
return wordTextCase == InputMode.CASE_UPPER ? InputMode.CASE_CAPITALIZE : wordTextCase; return wordTextCase == InputMode.CASE_UPPER ? InputMode.CASE_CAPITALIZE : wordTextCase;
} }

View file

@ -39,7 +39,6 @@ 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 = () -> {};
@ -179,7 +178,6 @@ 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() {
@ -208,7 +206,7 @@ abstract public class InputMode {
* If "analyzeSurroundingText" is true, and when the mode supports text analyzing, it may apply * If "analyzeSurroundingText" is true, and when the mode supports text analyzing, it may apply
* additional logic to determine the next valid text case. * additional logic to determine the next valid text case.
*/ */
public boolean nextTextCase(boolean analyzeSurroundingText) { public boolean nextTextCase() {
if (!language.hasUpperCase()) { if (!language.hasUpperCase()) {
return false; return false;
} }
@ -220,6 +218,7 @@ abstract public class InputMode {
} }
public void determineNextWordTextCase(int nextDigit) {} public void determineNextWordTextCase(int nextDigit) {}
public void skipNextTextCaseDetection() {}
// Based on the internal logic of the mode (punctuation or grammar rules), re-adjust the text case for when getSuggestions() is called. // 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; } protected String adjustSuggestionTextCase(String word, int newTextCase) { return word; }

View file

@ -30,7 +30,7 @@ public class ModeIdeograms extends ModeWords {
@Override protected String adjustSuggestionTextCase(String word, int newTextCase) { return word; } @Override protected String adjustSuggestionTextCase(String word, int newTextCase) { return word; }
@Override public void determineNextWordTextCase(int nextDigit) {} @Override public void determineNextWordTextCase(int nextDigit) {}
@Override public boolean nextTextCase(boolean analyzeSurroundingText) { return false; } @Override public boolean nextTextCase() { return false; }
@Override @Override

View file

@ -160,10 +160,10 @@ class ModeWords extends ModeCheonjiin {
if (isRecomposing) { if (isRecomposing) {
isRecomposing = false; isRecomposing = false;
textCase = settings.getTextCase(); textCase = settings.getTextCase();
onEndRecomposing.run();
} }
} }
@Override @Override
public void reset() { public void reset() {
basicReset(); basicReset();
@ -382,14 +382,12 @@ class ModeWords extends ModeCheonjiin {
} }
@Override @Override
public boolean nextTextCase(boolean analyzeSurroundingText) { public boolean nextTextCase() {
boolean changed = super.nextTextCase(analyzeSurroundingText); // convert any internally used text cases to user-friendly, because this is what the user
// is allowed to choose from.
textCase = getTextCase();
// "analyzeSurroundingText" is true only when Shift is pressed to avoid expensive boolean changed = super.nextTextCase();
// calls to getStringBeforeCursor().
if (analyzeSurroundingText && textCase == CASE_LOWER && autoTextCase.isLowerCaseForbidden(language, textField.getStringBeforeCursor())) {
changed = super.nextTextCase(true);
}
// since it's a user's choice, the default matters no more // since it's a user's choice, the default matters no more
textFieldTextCase = changed ? CASE_UNDEFINED : textFieldTextCase; textFieldTextCase = changed ? CASE_UNDEFINED : textFieldTextCase;
@ -397,6 +395,10 @@ class ModeWords extends ModeCheonjiin {
return changed; return changed;
} }
@Override
public void skipNextTextCaseDetection() {
autoTextCase.skipNext();
}
@Override @Override
public boolean shouldReplaceLastLetter(int n, boolean h) { public boolean shouldReplaceLastLetter(int n, boolean h) {

View file

@ -13,12 +13,14 @@ public class AutoTextCase {
@NonNull private final Sequences sequences; @NonNull private final Sequences sequences;
@NonNull private final SettingsStore settings; @NonNull private final SettingsStore settings;
private final boolean isUs; private final boolean isUs;
private boolean skipNext;
public AutoTextCase(@NonNull SettingsStore settingsStore, @NonNull Sequences sequences, @Nullable InputType inputType) { public AutoTextCase(@NonNull SettingsStore settingsStore, @NonNull Sequences sequences, @Nullable InputType inputType) {
this.sequences = sequences; this.sequences = sequences;
settings = settingsStore; settings = settingsStore;
isUs = inputType != null && inputType.isUs(); isUs = inputType != null && inputType.isUs();
skipNext = false;
} }
/** /**
@ -59,6 +61,11 @@ public class AutoTextCase {
return currentTextCase; return currentTextCase;
} }
if (skipNext) {
skipNext = false;
return textFieldTextCase != InputMode.CASE_UNDEFINED ? textFieldTextCase : currentTextCase;
}
// lowercase also takes priority but not as strict as uppercase // lowercase also takes priority but not as strict as uppercase
if (textFieldTextCase != InputMode.CASE_UNDEFINED && currentTextCase != InputMode.CASE_LOWER) { if (textFieldTextCase != InputMode.CASE_UNDEFINED && currentTextCase != InputMode.CASE_LOWER) {
return textFieldTextCase; return textFieldTextCase;
@ -90,23 +97,7 @@ public class AutoTextCase {
} }
/** public void skipNext() {
* Prevent lowercase at the beginning of a line when the respective setting is enabled, skipNext = true;
* or at the beginning of a sentence, when auto capitalization is enabled.
*/
public boolean isLowerCaseForbidden(@NonNull Language language, @NonNull String beforeCursor) {
if (!language.hasUpperCase()) {
return false;
}
if (settings.getAutoTextCase() && (beforeCursor.isEmpty() || Text.isStartOfSentence(beforeCursor))) {
return true;
}
if (settings.getAutoCapitalsAfterNewline() && beforeCursor.endsWith("\n")) {
return true;
}
return false;
} }
} }