added support for languages with one text case
This commit is contained in:
parent
e82ae8eaed
commit
ca15ff230b
9 changed files with 123 additions and 91 deletions
|
|
@ -57,7 +57,8 @@ To support a new language one needs to:
|
||||||
- `name` is the native name of the language (e.g. "English", "Deutsch", "Українська").
|
- `name` is the native name of the language (e.g. "English", "Deutsch", "Українська").
|
||||||
- `locale` contains the language and the country codes (e.g. "en-US", "es-AR", "it-IT"). Refer to the list of [supported locales in Java](https://www.oracle.com/java/technologies/javase/jdk8-jre8-suported-locales.html#util-text).
|
- `locale` contains the language and the country codes (e.g. "en-US", "es-AR", "it-IT"). Refer to the list of [supported locales in Java](https://www.oracle.com/java/technologies/javase/jdk8-jre8-suported-locales.html#util-text).
|
||||||
- `dictionaryFile` is the name of the dictionary in `assets/` folder.
|
- `dictionaryFile` is the name of the dictionary in `assets/` folder.
|
||||||
- `icon`, `abcLowerCaseIcon` and `abcUpperCaseIcon` are the respective status icons for Predictive mode, ABC (lowercase) and ABC (uppercase).
|
- `icon` is the status icon for Predictive mode.
|
||||||
|
- `abcLowerCaseIcon` and `abcUpperCaseIcon` are the respective status icons for ABC (non-predictive) modes. Note that, you must not set `abcUpperCaseIcon`, if your language has no uppercase and lowercase letters (like Arabic, Asian scripts and Hebrew).
|
||||||
- Set `isPunctuationPartOfWords` to `true`, if the dictionary contains words with apostrophes or dashes, such as: `it's`, `you'll`, `a'tje` or `п'ят`. This will allow using 1-key for typing them (they will appear as suggestions). `false` will enable faster typing when apostrophes or other punctuation are not part of the words (no such words will be suggested).
|
- Set `isPunctuationPartOfWords` to `true`, if the dictionary contains words with apostrophes or dashes, such as: `it's`, `you'll`, `a'tje` or `п'ят`. This will allow using 1-key for typing them (they will appear as suggestions). `false` will enable faster typing when apostrophes or other punctuation are not part of the words (no such words will be suggested).
|
||||||
- `characterMap` contains the letters and punctuation marks associated with each key.
|
- `characterMap` contains the letters and punctuation marks associated with each key.
|
||||||
- Finally, add the new language to the list in `LanguageCollection.java`. You only need to add it in one place, in the constructor. Please, be nice and maintain the alphabetical order.
|
- Finally, add the new language to the list in `LanguageCollection.java`. You only need to add it in one place, in the constructor. Please, be nice and maintain the alphabetical order.
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
private void loadSettings() {
|
private void loadSettings() {
|
||||||
mLanguage = LanguageCollection.getLanguage(settings.getInputLanguage());
|
mLanguage = LanguageCollection.getLanguage(settings.getInputLanguage());
|
||||||
mEnabledLanguages = settings.getEnabledLanguageIds();
|
mEnabledLanguages = settings.getEnabledLanguageIds();
|
||||||
mInputMode = InputMode.getInstance(settings, settings.getInputMode());
|
mInputMode = InputMode.getInstance(settings, mLanguage, settings.getInputMode());
|
||||||
mInputMode.setTextCase(settings.getTextCase());
|
mInputMode.setTextCase(settings.getTextCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,9 +96,10 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
// some input fields support only numbers or are not suited for predictions (e.g. password fields)
|
// some input fields support only numbers or are not suited for predictions (e.g. password fields)
|
||||||
determineAllowedInputModes();
|
determineAllowedInputModes();
|
||||||
mInputMode = InputModeValidator.validateMode(settings, mInputMode, allowedInputModes);
|
int modeId = InputModeValidator.validateMode(settings, mInputMode, allowedInputModes);
|
||||||
|
mInputMode = InputMode.getInstance(settings, mLanguage, modeId);
|
||||||
mInputMode.setTextFieldCase(textField.determineTextCase(inputType));
|
mInputMode.setTextFieldCase(textField.determineTextCase(inputType));
|
||||||
|
|
||||||
// Some modes may want to change the default text case based on grammar rules.
|
// Some modes may want to change the default text case based on grammar rules.
|
||||||
determineNextTextCase();
|
determineNextTextCase();
|
||||||
InputModeValidator.validateTextCase(settings, mInputMode, settings.getTextCase());
|
InputModeValidator.validateTextCase(settings, mInputMode, settings.getTextCase());
|
||||||
|
|
@ -197,7 +198,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
String word = mSuggestionView.getCurrentSuggestion();
|
String word = mSuggestionView.getCurrentSuggestion();
|
||||||
|
|
||||||
mInputMode.onAcceptSuggestion(mLanguage, word);
|
mInputMode.onAcceptSuggestion(word);
|
||||||
commitCurrentSuggestion();
|
commitCurrentSuggestion();
|
||||||
autoCorrectSpace(word, true, -1, false, false);
|
autoCorrectSpace(word, true, -1, false, false);
|
||||||
resetKeyRepeat();
|
resetKeyRepeat();
|
||||||
|
|
@ -208,7 +209,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
protected boolean onUp() {
|
protected boolean onUp() {
|
||||||
if (previousSuggestion()) {
|
if (previousSuggestion()) {
|
||||||
mInputMode.setWordStem(mLanguage, mSuggestionView.getCurrentSuggestion(), true);
|
mInputMode.setWordStem(mSuggestionView.getCurrentSuggestion(), true);
|
||||||
textField.setComposingTextWithHighlightedStem(mSuggestionView.getCurrentSuggestion(), mInputMode);
|
textField.setComposingTextWithHighlightedStem(mSuggestionView.getCurrentSuggestion(), mInputMode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -219,7 +220,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
protected boolean onDown() {
|
protected boolean onDown() {
|
||||||
if (nextSuggestion()) {
|
if (nextSuggestion()) {
|
||||||
mInputMode.setWordStem(mLanguage, mSuggestionView.getCurrentSuggestion(), true);
|
mInputMode.setWordStem(mSuggestionView.getCurrentSuggestion(), true);
|
||||||
textField.setComposingTextWithHighlightedStem(mSuggestionView.getCurrentSuggestion(), mInputMode);
|
textField.setComposingTextWithHighlightedStem(mSuggestionView.getCurrentSuggestion(), mInputMode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -230,7 +231,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
protected boolean onLeft() {
|
protected boolean onLeft() {
|
||||||
if (mInputMode.clearWordStem()) {
|
if (mInputMode.clearWordStem()) {
|
||||||
mInputMode.loadSuggestions(handleSuggestionsAsync, mLanguage, getComposingText());
|
mInputMode.loadSuggestions(handleSuggestionsAsync, getComposingText());
|
||||||
} else {
|
} else {
|
||||||
jumpBeforeComposingText();
|
jumpBeforeComposingText();
|
||||||
}
|
}
|
||||||
|
|
@ -247,8 +248,8 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
filter = getComposingText();
|
filter = getComposingText();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mInputMode.setWordStem(mLanguage, filter, repeat)) {
|
if (mInputMode.setWordStem(filter, repeat)) {
|
||||||
mInputMode.loadSuggestions(handleSuggestionsAsync, mLanguage, filter);
|
mInputMode.loadSuggestions(handleSuggestionsAsync, filter);
|
||||||
} else if (filter.length() == 0) {
|
} else if (filter.length() == 0) {
|
||||||
mInputMode.reset();
|
mInputMode.reset();
|
||||||
}
|
}
|
||||||
|
|
@ -270,8 +271,8 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
// Automatically accept the current word, when the next one is a space or whatnot,
|
// Automatically accept the current word, when the next one is a space or whatnot,
|
||||||
// instead of requiring "OK" before that.
|
// instead of requiring "OK" before that.
|
||||||
if (mInputMode.shouldAcceptCurrentSuggestion(mLanguage, key, hold, repeat > 0)) {
|
if (mInputMode.shouldAcceptCurrentSuggestion(key, hold, repeat > 0)) {
|
||||||
mInputMode.onAcceptSuggestion(mLanguage, currentWord);
|
mInputMode.onAcceptSuggestion(currentWord);
|
||||||
commitCurrentSuggestion(false);
|
commitCurrentSuggestion(false);
|
||||||
autoCorrectSpace(currentWord, false, key, hold, repeat > 0);
|
autoCorrectSpace(currentWord, false, key, hold, repeat > 0);
|
||||||
currentWord = "";
|
currentWord = "";
|
||||||
|
|
@ -283,7 +284,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
determineNextTextCase();
|
determineNextTextCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mInputMode.onNumber(mLanguage, key, hold, repeat)) {
|
if (!mInputMode.onNumber(key, hold, repeat)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,7 +296,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
if (mInputMode.getWord() != null) {
|
if (mInputMode.getWord() != null) {
|
||||||
currentWord = mInputMode.getWord();
|
currentWord = mInputMode.getWord();
|
||||||
|
|
||||||
mInputMode.onAcceptSuggestion(mLanguage, currentWord);
|
mInputMode.onAcceptSuggestion(currentWord);
|
||||||
textField.setText(currentWord);
|
textField.setText(currentWord);
|
||||||
clearSuggestions();
|
clearSuggestions();
|
||||||
autoCorrectSpace(currentWord, true, key, hold, repeat > 0);
|
autoCorrectSpace(currentWord, true, key, hold, repeat > 0);
|
||||||
|
|
@ -333,6 +334,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
protected boolean onKeyNextLanguage() {
|
protected boolean onKeyNextLanguage() {
|
||||||
if (nextLang()) {
|
if (nextLang()) {
|
||||||
commitCurrentSuggestion(false);
|
commitCurrentSuggestion(false);
|
||||||
|
mInputMode.changeLanguage(mLanguage);
|
||||||
mInputMode.reset();
|
mInputMode.reset();
|
||||||
resetKeyRepeat();
|
resetKeyRepeat();
|
||||||
clearSuggestions();
|
clearSuggestions();
|
||||||
|
|
@ -430,14 +432,14 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
|
|
||||||
private void getSuggestions() {
|
private void getSuggestions() {
|
||||||
if (!mInputMode.loadSuggestions(handleSuggestionsAsync, mLanguage, mSuggestionView.getCurrentSuggestion())) {
|
if (!mInputMode.loadSuggestions(handleSuggestionsAsync, mSuggestionView.getCurrentSuggestion())) {
|
||||||
handleSuggestions();
|
handleSuggestions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void handleSuggestions() {
|
private void handleSuggestions() {
|
||||||
setSuggestions(mInputMode.getSuggestions(mLanguage));
|
setSuggestions(mInputMode.getSuggestions());
|
||||||
|
|
||||||
// Put the first suggestion in the text field,
|
// Put the first suggestion in the text field,
|
||||||
// but cut it off to the length of the sequence (how many keys were pressed),
|
// but cut it off to the length of the sequence (how many keys were pressed),
|
||||||
|
|
@ -489,7 +491,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
private void nextInputMode() {
|
private void nextInputMode() {
|
||||||
if (mEditing == EDITING_STRICT_NUMERIC || mEditing == EDITING_DIALER) {
|
if (mEditing == EDITING_STRICT_NUMERIC || mEditing == EDITING_DIALER) {
|
||||||
mInputMode = !mInputMode.is123() ? InputMode.getInstance(settings, InputMode.MODE_123) : mInputMode;
|
mInputMode = !mInputMode.is123() ? InputMode.getInstance(settings, mLanguage, InputMode.MODE_123) : mInputMode;
|
||||||
}
|
}
|
||||||
// when typing a word or viewing scrolling the suggestions, only change the case
|
// when typing a word or viewing scrolling the suggestions, only change the case
|
||||||
else if (!isSuggestionViewHidden()) {
|
else if (!isSuggestionViewHidden()) {
|
||||||
|
|
@ -498,9 +500,9 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
// When we are in AUTO mode and the dictionary word is in uppercase,
|
// When we are in AUTO mode and the dictionary word is in uppercase,
|
||||||
// the mode would switch to UPPERCASE, but visually, the word would not change.
|
// the mode would switch to UPPERCASE, but visually, the word would not change.
|
||||||
// This is why we retry, until there is a visual change.
|
// This is why we retry, until there is a visual change.
|
||||||
for (int retries = 0; retries < 2; retries++) {
|
for (int retries = 0; retries < 2 && mLanguage.hasUpperCase(); retries++) {
|
||||||
mInputMode.nextTextCase();
|
mInputMode.nextTextCase();
|
||||||
setSuggestions(mInputMode.getSuggestions(mLanguage), mSuggestionView.getCurrentIndex());
|
setSuggestions(mInputMode.getSuggestions(), mSuggestionView.getCurrentIndex());
|
||||||
refreshComposingText();
|
refreshComposingText();
|
||||||
|
|
||||||
if (!currentSuggestionBefore.equals(getComposingText())) {
|
if (!currentSuggestionBefore.equals(getComposingText())) {
|
||||||
|
|
@ -509,17 +511,17 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// make "abc" and "ABC" separate modes from user perspective
|
// make "abc" and "ABC" separate modes from user perspective
|
||||||
else if (mInputMode.isABC() && mInputMode.getTextCase() == InputMode.CASE_LOWER) {
|
else if (mInputMode.isABC() && mInputMode.getTextCase() == InputMode.CASE_LOWER && mLanguage.hasUpperCase()) {
|
||||||
mInputMode.nextTextCase();
|
mInputMode.nextTextCase();
|
||||||
} else {
|
} else {
|
||||||
int modeIndex = (allowedInputModes.indexOf(mInputMode.getId()) + 1) % allowedInputModes.size();
|
int modeIndex = (allowedInputModes.indexOf(mInputMode.getId()) + 1) % allowedInputModes.size();
|
||||||
mInputMode = InputMode.getInstance(settings, allowedInputModes.get(modeIndex));
|
mInputMode = InputMode.getInstance(settings, mLanguage, allowedInputModes.get(modeIndex));
|
||||||
|
|
||||||
mInputMode.defaultTextCase();
|
mInputMode.defaultTextCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
// save the settings for the next time
|
// save the settings for the next time
|
||||||
settings.saveInputMode(mInputMode);
|
settings.saveInputMode(mInputMode.getId());
|
||||||
settings.saveTextCase(mInputMode.getTextCase());
|
settings.saveTextCase(mInputMode.getTextCase());
|
||||||
|
|
||||||
UI.updateStatusIcon(this, mLanguage, mInputMode);
|
UI.updateStatusIcon(this, mLanguage, mInputMode);
|
||||||
|
|
@ -558,7 +560,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
textField.setComposingText(word, 0);
|
textField.setComposingText(word, 0);
|
||||||
textField.finishComposingText();
|
textField.finishComposingText();
|
||||||
mInputMode.onAcceptSuggestion(mLanguage, word);
|
mInputMode.onAcceptSuggestion(word);
|
||||||
mInputMode.reset();
|
mInputMode.reset();
|
||||||
setSuggestions(null);
|
setSuggestions(null);
|
||||||
}
|
}
|
||||||
|
|
@ -569,11 +571,11 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
int lastInputModeId = settings.getInputMode();
|
int lastInputModeId = settings.getInputMode();
|
||||||
if (allowedInputModes.contains(lastInputModeId)) {
|
if (allowedInputModes.contains(lastInputModeId)) {
|
||||||
mInputMode = InputMode.getInstance(settings, lastInputModeId);
|
mInputMode = InputMode.getInstance(settings, mLanguage, lastInputModeId);
|
||||||
} else if (allowedInputModes.contains(InputMode.MODE_ABC)) {
|
} else if (allowedInputModes.contains(InputMode.MODE_ABC)) {
|
||||||
mInputMode = InputMode.getInstance(settings, InputMode.MODE_ABC);
|
mInputMode = InputMode.getInstance(settings, mLanguage, InputMode.MODE_ABC);
|
||||||
} else {
|
} else {
|
||||||
mInputMode = InputMode.getInstance(settings, allowedInputModes.get(0));
|
mInputMode = InputMode.getInstance(settings, mLanguage, allowedInputModes.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputType.isDialer()) {
|
if (inputType.isDialer()) {
|
||||||
|
|
|
||||||
|
|
@ -41,23 +41,19 @@ public class InputModeValidator {
|
||||||
return validLanguage;
|
return validLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static InputMode validateMode(SettingsStore settings, InputMode inputMode, ArrayList<Integer> allowedModes) {
|
public static int validateMode(SettingsStore settings, InputMode inputMode, ArrayList<Integer> allowedModes) {
|
||||||
if (allowedModes.size() > 0 && allowedModes.contains(inputMode.getId())) {
|
if (allowedModes.size() > 0 && allowedModes.contains(inputMode.getId())) {
|
||||||
inputMode.reset();
|
return inputMode.getId();
|
||||||
return inputMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputMode newMode = InputMode.getInstance(
|
int newModeId = allowedModes.size() > 0 ? allowedModes.get(0) : InputMode.MODE_123;
|
||||||
settings,
|
settings.saveInputMode(newModeId);
|
||||||
allowedModes.size() > 0 ? allowedModes.get(0) : InputMode.MODE_123
|
|
||||||
);
|
|
||||||
settings.saveInputMode(newMode);
|
|
||||||
|
|
||||||
if (newMode.getId() != inputMode.getId()) {
|
if (newModeId != inputMode.getId()) {
|
||||||
Logger.w("tt9/validateMode", "Invalid input mode: " + inputMode.getId() + " Enforcing: " + newMode.getId());
|
Logger.w("tt9/validateMode", "Invalid input mode: " + inputMode.getId() + " Enforcing: " + newModeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newMode;
|
return newModeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void validateTextCase(SettingsStore settings, InputMode inputMode, int newTextCase) {
|
public static void validateTextCase(SettingsStore settings, InputMode inputMode, int newTextCase) {
|
||||||
|
|
|
||||||
|
|
@ -27,16 +27,17 @@ abstract public class InputMode {
|
||||||
protected int textFieldTextCase = CASE_UNDEFINED;
|
protected int textFieldTextCase = CASE_UNDEFINED;
|
||||||
|
|
||||||
// data
|
// data
|
||||||
|
protected Language language;
|
||||||
protected ArrayList<String> suggestions = new ArrayList<>();
|
protected ArrayList<String> suggestions = new ArrayList<>();
|
||||||
protected String word = null;
|
protected String word = null;
|
||||||
|
|
||||||
|
|
||||||
public static InputMode getInstance(SettingsStore settings, int mode) {
|
public static InputMode getInstance(SettingsStore settings, Language language, int mode) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case MODE_PREDICTIVE:
|
case MODE_PREDICTIVE:
|
||||||
return new ModePredictive(settings);
|
return new ModePredictive(settings, language);
|
||||||
case MODE_ABC:
|
case MODE_ABC:
|
||||||
return new ModeABC();
|
return new ModeABC(language);
|
||||||
default:
|
default:
|
||||||
Logger.w("tt9/InputMode", "Defaulting to mode: " + Mode123.class.getName() + " for unknown InputMode: " + mode);
|
Logger.w("tt9/InputMode", "Defaulting to mode: " + Mode123.class.getName() + " for unknown InputMode: " + mode);
|
||||||
case MODE_123:
|
case MODE_123:
|
||||||
|
|
@ -46,17 +47,17 @@ abstract public class InputMode {
|
||||||
|
|
||||||
// Key handlers. Return "true" when handling the key or "false", when is nothing to do.
|
// Key handlers. Return "true" when handling the key or "false", when is nothing to do.
|
||||||
public boolean onBackspace() { return false; }
|
public boolean onBackspace() { return false; }
|
||||||
abstract public boolean onNumber(Language language, int key, boolean hold, int repeat);
|
abstract public boolean onNumber(int key, boolean hold, int repeat);
|
||||||
|
|
||||||
// Suggestions
|
// Suggestions
|
||||||
public void onAcceptSuggestion(Language language, String suggestion) {}
|
public void onAcceptSuggestion(String suggestion) {}
|
||||||
protected void onSuggestionsUpdated(Handler handler) { handler.sendEmptyMessage(0); }
|
protected void onSuggestionsUpdated(Handler handler) { handler.sendEmptyMessage(0); }
|
||||||
public boolean loadSuggestions(Handler handler, Language language, String currentWord) { return false; }
|
public boolean loadSuggestions(Handler handler, String currentWord) { return false; }
|
||||||
|
|
||||||
public ArrayList<String> getSuggestions(Language language) {
|
public ArrayList<String> getSuggestions() {
|
||||||
ArrayList<String> newSuggestions = new ArrayList<>();
|
ArrayList<String> newSuggestions = new ArrayList<>();
|
||||||
for (String s : suggestions) {
|
for (String s : suggestions) {
|
||||||
newSuggestions.add(adjustSuggestionTextCase(s, textCase, language));
|
newSuggestions.add(adjustSuggestionTextCase(s, textCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
return newSuggestions;
|
return newSuggestions;
|
||||||
|
|
@ -73,9 +74,14 @@ abstract public class InputMode {
|
||||||
// Utility
|
// Utility
|
||||||
abstract public int getId();
|
abstract public int getId();
|
||||||
abstract public int getSequenceLength(); // The number of key presses for the current word.
|
abstract public int getSequenceLength(); // The number of key presses for the current word.
|
||||||
|
public void changeLanguage(Language newLanguage) {
|
||||||
|
if (newLanguage != null) {
|
||||||
|
language = newLanguage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Interaction with the IME. Return "true" if it should perform the respective action.
|
// Interaction with the IME. Return "true" if it should perform the respective action.
|
||||||
public boolean shouldAcceptCurrentSuggestion(Language language, int key, boolean hold, boolean repeat) { return false; }
|
public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) { return false; }
|
||||||
public boolean shouldAddAutoSpace(InputType inputType, TextField textField, boolean isWordAcceptedManually, int incomingKey, boolean hold, boolean repeat) { return false; }
|
public boolean shouldAddAutoSpace(InputType inputType, TextField textField, boolean isWordAcceptedManually, int incomingKey, boolean hold, boolean repeat) { return false; }
|
||||||
public boolean shouldDeletePrecedingSpace(InputType inputType) { return false; }
|
public boolean shouldDeletePrecedingSpace(InputType inputType) { return false; }
|
||||||
public boolean shouldSelectNextSuggestion() { return false; }
|
public boolean shouldSelectNextSuggestion() { return false; }
|
||||||
|
|
@ -116,12 +122,12 @@ abstract public class InputMode {
|
||||||
public void determineNextWordTextCase(SettingsStore settings, boolean isThereText, String textBeforeCursor) {}
|
public void determineNextWordTextCase(SettingsStore settings, boolean isThereText, String textBeforeCursor) {}
|
||||||
|
|
||||||
// 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, Language language) { return word; }
|
protected String adjustSuggestionTextCase(String word, int newTextCase) { return word; }
|
||||||
|
|
||||||
// Stem filtering.
|
// Stem filtering.
|
||||||
// Where applicable, return "true" if the mode supports it and the operation was possible.
|
// Where applicable, return "true" if the mode supports it and the operation was possible.
|
||||||
public boolean clearWordStem() { return false; }
|
public boolean clearWordStem() { return false; }
|
||||||
public boolean isStemFilterFuzzy() { return false; }
|
public boolean isStemFilterFuzzy() { return false; }
|
||||||
public String getWordStem() { return ""; }
|
public String getWordStem() { return ""; }
|
||||||
public boolean setWordStem(Language language, String stem, boolean exact) { return false; }
|
public boolean setWordStem(String stem, boolean exact) { return false; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ package io.github.sspanak.tt9.ime.modes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
|
||||||
|
|
||||||
public class Mode123 extends InputMode {
|
public class Mode123 extends InputMode {
|
||||||
public int getId() { return MODE_123; }
|
public int getId() { return MODE_123; }
|
||||||
|
|
||||||
|
|
@ -12,7 +10,7 @@ public class Mode123 extends InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean onNumber(Language l, int key, boolean hold, int repeat) {
|
public boolean onNumber(int key, boolean hold, int repeat) {
|
||||||
if (key != 0) {
|
if (key != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,13 @@ public class ModeABC extends InputMode {
|
||||||
|
|
||||||
private boolean shouldSelectNextLetter = false;
|
private boolean shouldSelectNextLetter = false;
|
||||||
|
|
||||||
ModeABC() {
|
ModeABC(Language lang) {
|
||||||
allowedTextCases.add(CASE_LOWER);
|
changeLanguage(lang);
|
||||||
allowedTextCases.add(CASE_UPPER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean onNumber(Language language, int key, boolean hold, int repeat) {
|
@Override
|
||||||
|
public boolean onNumber(int key, boolean hold, int repeat) {
|
||||||
shouldSelectNextLetter = false;
|
shouldSelectNextLetter = false;
|
||||||
suggestions = language.getKeyCharacters(key);
|
suggestions = language.getKeyCharacters(key);
|
||||||
word = null;
|
word = null;
|
||||||
|
|
@ -31,18 +31,29 @@ public class ModeABC extends InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected String adjustSuggestionTextCase(String word, int newTextCase, Language language) {
|
@Override
|
||||||
|
protected String adjustSuggestionTextCase(String word, int newTextCase) {
|
||||||
return newTextCase == CASE_UPPER ? word.toUpperCase(language.getLocale()) : word.toLowerCase(language.getLocale());
|
return newTextCase == CASE_UPPER ? word.toUpperCase(language.getLocale()) : word.toLowerCase(language.getLocale());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changeLanguage(Language language) {
|
||||||
|
super.changeLanguage(language);
|
||||||
|
|
||||||
final public boolean isABC() { return true; }
|
allowedTextCases.clear();
|
||||||
public int getSequenceLength() { return 1; }
|
allowedTextCases.add(CASE_LOWER);
|
||||||
|
if (language.hasUpperCase()) {
|
||||||
|
allowedTextCases.add(CASE_UPPER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean shouldAcceptCurrentSuggestion(Language l, int key, boolean hold, boolean repeat) { return hold || !repeat; }
|
@Override final public boolean isABC() { return true; }
|
||||||
public boolean shouldTrackUpDown() { return true; }
|
@Override public int getSequenceLength() { return 1; }
|
||||||
public boolean shouldTrackLeftRight() { return true; }
|
|
||||||
public boolean shouldSelectNextSuggestion() {
|
@Override public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) { return hold || !repeat; }
|
||||||
|
@Override public boolean shouldTrackUpDown() { return true; }
|
||||||
|
@Override public boolean shouldTrackLeftRight() { return true; }
|
||||||
|
@Override public boolean shouldSelectNextSuggestion() {
|
||||||
return shouldSelectNextLetter;
|
return shouldSelectNextLetter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ public class ModePredictive extends InputMode {
|
||||||
private String stem = "";
|
private String stem = "";
|
||||||
|
|
||||||
// async suggestion handling
|
// async suggestion handling
|
||||||
private Language currentLanguage = null;
|
|
||||||
private String currentInputFieldWord = "";
|
private String currentInputFieldWord = "";
|
||||||
private static Handler handleSuggestionsExternal;
|
private static Handler handleSuggestionsExternal;
|
||||||
|
|
||||||
|
|
@ -44,10 +43,8 @@ public class ModePredictive extends InputMode {
|
||||||
private final String maxEmojiSequence;
|
private final String maxEmojiSequence;
|
||||||
|
|
||||||
|
|
||||||
ModePredictive(SettingsStore settings) {
|
ModePredictive(SettingsStore settings, Language lang) {
|
||||||
allowedTextCases.add(CASE_LOWER);
|
changeLanguage(lang);
|
||||||
allowedTextCases.add(CASE_CAPITALIZE);
|
|
||||||
allowedTextCases.add(CASE_UPPER);
|
|
||||||
|
|
||||||
emptyDbWarning = new EmptyDatabaseWarning(settings);
|
emptyDbWarning = new EmptyDatabaseWarning(settings);
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
|
|
@ -81,13 +78,13 @@ public class ModePredictive extends InputMode {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onNumber(Language language, int key, boolean hold, int repeat) {
|
public boolean onNumber(int key, boolean hold, int repeat) {
|
||||||
if (hold) {
|
if (hold) {
|
||||||
// hold to type any digit
|
// hold to type any digit
|
||||||
reset();
|
reset();
|
||||||
word = String.valueOf(key);
|
word = String.valueOf(key);
|
||||||
} else if (key == 0 && repeat > 0) {
|
} else if (key == 0 && repeat > 0) {
|
||||||
onDouble0(language);
|
onDouble0();
|
||||||
} else {
|
} else {
|
||||||
// words
|
// words
|
||||||
super.reset();
|
super.reset();
|
||||||
|
|
@ -102,7 +99,7 @@ public class ModePredictive extends InputMode {
|
||||||
* onDouble0
|
* onDouble0
|
||||||
* Double "0" is a shortcut for the preferred character.
|
* Double "0" is a shortcut for the preferred character.
|
||||||
*/
|
*/
|
||||||
private void onDouble0(Language language) {
|
private void onDouble0() {
|
||||||
try {
|
try {
|
||||||
reset();
|
reset();
|
||||||
word = settings.getDoubleZeroChar();
|
word = settings.getDoubleZeroChar();
|
||||||
|
|
@ -115,6 +112,19 @@ public class ModePredictive extends InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changeLanguage(Language language) {
|
||||||
|
super.changeLanguage(language);
|
||||||
|
|
||||||
|
allowedTextCases.clear();
|
||||||
|
allowedTextCases.add(CASE_LOWER);
|
||||||
|
if (language.hasUpperCase()) {
|
||||||
|
allowedTextCases.add(CASE_CAPITALIZE);
|
||||||
|
allowedTextCases.add(CASE_UPPER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
super.reset();
|
super.reset();
|
||||||
|
|
@ -156,7 +166,7 @@ public class ModePredictive extends InputMode {
|
||||||
* Note that you need to manually get the suggestions again to obtain a filtered list.
|
* Note that you need to manually get the suggestions again to obtain a filtered list.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean setWordStem(Language language, String wordStem, boolean exact) {
|
public boolean setWordStem(String wordStem, boolean exact) {
|
||||||
if (language == null || wordStem == null || wordStem.length() < 1) {
|
if (language == null || wordStem == null || wordStem.length() < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -202,7 +212,7 @@ public class ModePredictive extends InputMode {
|
||||||
* Similar to "loadSuggestions()", but loads suggestions that are not in the database.
|
* Similar to "loadSuggestions()", but loads suggestions that are not in the database.
|
||||||
* Returns "false", when there are no static suggestions for the current digitSequence.
|
* Returns "false", when there are no static suggestions for the current digitSequence.
|
||||||
*/
|
*/
|
||||||
private boolean loadStaticSuggestions(Language language) {
|
private boolean loadStaticSuggestions() {
|
||||||
if (digitSequence.equals("0")) {
|
if (digitSequence.equals("0")) {
|
||||||
stem = "";
|
stem = "";
|
||||||
suggestions = language.getKeyCharacters(0, false);
|
suggestions = language.getKeyCharacters(0, false);
|
||||||
|
|
@ -231,8 +241,8 @@ public class ModePredictive extends InputMode {
|
||||||
* See: generatePossibleCompletions()
|
* See: generatePossibleCompletions()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean loadSuggestions(Handler handler, Language language, String currentWord) {
|
public boolean loadSuggestions(Handler handler, String currentWord) {
|
||||||
if (loadStaticSuggestions(language)) {
|
if (loadStaticSuggestions()) {
|
||||||
super.onSuggestionsUpdated(handler);
|
super.onSuggestionsUpdated(handler);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +254,6 @@ public class ModePredictive extends InputMode {
|
||||||
|
|
||||||
handleSuggestionsExternal = handler;
|
handleSuggestionsExternal = handler;
|
||||||
currentInputFieldWord = currentWord.toLowerCase(language.getLocale());
|
currentInputFieldWord = currentWord.toLowerCase(language.getLocale());
|
||||||
currentLanguage = language;
|
|
||||||
super.reset();
|
super.reset();
|
||||||
|
|
||||||
DictionaryDb.getSuggestions(
|
DictionaryDb.getSuggestions(
|
||||||
|
|
@ -272,13 +281,13 @@ public class ModePredictive extends InputMode {
|
||||||
dbSuggestions = dbSuggestions == null ? new ArrayList<>() : dbSuggestions;
|
dbSuggestions = dbSuggestions == null ? new ArrayList<>() : dbSuggestions;
|
||||||
|
|
||||||
if (dbSuggestions.size() == 0 && digitSequence.length() > 0) {
|
if (dbSuggestions.size() == 0 && digitSequence.length() > 0) {
|
||||||
emptyDbWarning.emitOnce(currentLanguage);
|
emptyDbWarning.emitOnce(language);
|
||||||
dbSuggestions = generatePossibleCompletions(currentLanguage, currentInputFieldWord);
|
dbSuggestions = generatePossibleCompletions(currentInputFieldWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
suggestions.clear();
|
suggestions.clear();
|
||||||
suggestStem();
|
suggestStem();
|
||||||
suggestions.addAll(generatePossibleStemVariations(currentLanguage, dbSuggestions));
|
suggestions.addAll(generatePossibleStemVariations(dbSuggestions));
|
||||||
suggestMoreWords(dbSuggestions);
|
suggestMoreWords(dbSuggestions);
|
||||||
|
|
||||||
ModePredictive.super.onSuggestionsUpdated(handleSuggestionsExternal);
|
ModePredictive.super.onSuggestionsUpdated(handleSuggestionsExternal);
|
||||||
|
|
@ -295,7 +304,7 @@ public class ModePredictive extends InputMode {
|
||||||
* For example, if the word is "missin_" and the last pressed key is "4", the results would be:
|
* For example, if the word is "missin_" and the last pressed key is "4", the results would be:
|
||||||
* | missing | missinh | missini |
|
* | missing | missinh | missini |
|
||||||
*/
|
*/
|
||||||
private ArrayList<String> generatePossibleCompletions(Language language, String baseWord) {
|
private ArrayList<String> generatePossibleCompletions(String baseWord) {
|
||||||
ArrayList<String> generatedWords = new ArrayList<>();
|
ArrayList<String> generatedWords = new ArrayList<>();
|
||||||
|
|
||||||
// Make sure the displayed word and the digit sequence, we will be generating suggestions from,
|
// Make sure the displayed word and the digit sequence, we will be generating suggestions from,
|
||||||
|
|
@ -334,14 +343,14 @@ public class ModePredictive extends InputMode {
|
||||||
* generate: "extrb" and "extrc". This is useful for typing an unknown word, that is similar to
|
* generate: "extrb" and "extrc". This is useful for typing an unknown word, that is similar to
|
||||||
* the ones in the dictionary.
|
* the ones in the dictionary.
|
||||||
*/
|
*/
|
||||||
private ArrayList<String> generatePossibleStemVariations(Language language, ArrayList<String> dbSuggestions) {
|
private ArrayList<String> generatePossibleStemVariations(ArrayList<String> dbSuggestions) {
|
||||||
ArrayList<String> variations = new ArrayList<>();
|
ArrayList<String> variations = new ArrayList<>();
|
||||||
if (stem.length() == 0) {
|
if (stem.length() == 0) {
|
||||||
return variations;
|
return variations;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStemFuzzy && stem.length() == digitSequence.length() - 1) {
|
if (isStemFuzzy && stem.length() == digitSequence.length() - 1) {
|
||||||
ArrayList<String> allPossibleVariations = generatePossibleCompletions(language, stem);
|
ArrayList<String> allPossibleVariations = generatePossibleCompletions(stem);
|
||||||
|
|
||||||
// first add the known words, because it makes more sense to see them first
|
// first add the known words, because it makes more sense to see them first
|
||||||
for (String word : allPossibleVariations) {
|
for (String word : allPossibleVariations) {
|
||||||
|
|
@ -391,7 +400,7 @@ public class ModePredictive extends InputMode {
|
||||||
* Bring this word up in the suggestions list next time.
|
* Bring this word up in the suggestions list next time.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onAcceptSuggestion(Language language, String currentWord) {
|
public void onAcceptSuggestion(String currentWord) {
|
||||||
lastAcceptedWord = currentWord;
|
lastAcceptedWord = currentWord;
|
||||||
lastAcceptedSequence = digitSequence;
|
lastAcceptedSequence = digitSequence;
|
||||||
reset();
|
reset();
|
||||||
|
|
@ -425,7 +434,7 @@ public class ModePredictive extends InputMode {
|
||||||
* or Dutch words such as: "'s-Hertogenbosch".
|
* or Dutch words such as: "'s-Hertogenbosch".
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected String adjustSuggestionTextCase(String word, int newTextCase, Language language) {
|
protected String adjustSuggestionTextCase(String word, int newTextCase) {
|
||||||
switch (newTextCase) {
|
switch (newTextCase) {
|
||||||
case CASE_UPPER:
|
case CASE_UPPER:
|
||||||
return word.toUpperCase(language.getLocale());
|
return word.toUpperCase(language.getLocale());
|
||||||
|
|
@ -492,7 +501,7 @@ public class ModePredictive extends InputMode {
|
||||||
* we also increase its' priority. This function determines whether we want to do all this or not.
|
* we also increase its' priority. This function determines whether we want to do all this or not.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldAcceptCurrentSuggestion(Language language, int key, boolean hold, boolean repeat) {
|
public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) {
|
||||||
return
|
return
|
||||||
hold
|
hold
|
||||||
// Quickly accept suggestions using "space" instead of pressing "ok" then "space"
|
// Quickly accept suggestions using "space" instead of pressing "ok" then "space"
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,11 @@ public class Language {
|
||||||
final public boolean isPunctuationPartOfWords() { return isPunctuationPartOfWords; }
|
final public boolean isPunctuationPartOfWords() { return isPunctuationPartOfWords; }
|
||||||
|
|
||||||
|
|
||||||
|
final public boolean hasUpperCase() {
|
||||||
|
return abcUpperCaseIcon != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ************ utility ************ */
|
/* ************ utility ************ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -140,14 +140,18 @@ public class SettingsStore {
|
||||||
return prefs.getInt("pref_input_mode", InputMode.MODE_PREDICTIVE);
|
return prefs.getInt("pref_input_mode", InputMode.MODE_PREDICTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveInputMode(InputMode mode) {
|
public void saveInputMode(int mode) {
|
||||||
if (mode == null) {
|
boolean isModeValid = isIntInList(
|
||||||
Logger.w("tt9/saveInputMode", "Not saving NULL input mode");
|
mode,
|
||||||
return;
|
new ArrayList<>(Arrays.asList(InputMode.MODE_123, InputMode.MODE_PREDICTIVE, InputMode.MODE_ABC)),
|
||||||
}
|
"tt9/saveInputMode",
|
||||||
|
"Not saving invalid input mode: " + mode
|
||||||
|
);
|
||||||
|
|
||||||
prefsEditor.putInt("pref_input_mode", mode.getId());
|
if (isModeValid) {
|
||||||
prefsEditor.apply();
|
prefsEditor.putInt("pref_input_mode", mode);
|
||||||
|
prefsEditor.apply();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue