* each input mode is now in a separate file (#75)
* fixed mode 123 being incorrectly forced after typing in a numeric field, then going to a text field * simplified context usage everywhere * added some missing translations * moved the Soft Key view to the SoftKey class to avoid memory leaks and to simplify the code a bit
This commit is contained in:
parent
8d85215444
commit
575293edb9
21 changed files with 606 additions and 393 deletions
|
|
@ -1,6 +1,5 @@
|
|||
package io.github.sspanak.tt9.db;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteConstraintException;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
|
@ -15,6 +14,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||
import io.github.sspanak.tt9.languages.InvalidLanguageException;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
|
||||
|
|
@ -43,32 +43,32 @@ public class DictionaryDb {
|
|||
};
|
||||
|
||||
|
||||
private static synchronized void createInstance(Context context) {
|
||||
dbInstance = Room.databaseBuilder(context, T9RoomDb.class, "t9dict.db")
|
||||
private static synchronized void createInstance() {
|
||||
dbInstance = Room.databaseBuilder(TraditionalT9.getMainContext(), T9RoomDb.class, "t9dict.db")
|
||||
.addCallback(TRIGGER_CALLBACK)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
public static T9RoomDb getInstance(Context context) {
|
||||
private static T9RoomDb getInstance() {
|
||||
if (dbInstance == null) {
|
||||
createInstance(context);
|
||||
createInstance();
|
||||
}
|
||||
|
||||
return dbInstance;
|
||||
}
|
||||
|
||||
|
||||
public static void beginTransaction(Context context) {
|
||||
getInstance(context).beginTransaction();
|
||||
public static void beginTransaction() {
|
||||
getInstance().beginTransaction();
|
||||
}
|
||||
|
||||
|
||||
public static void endTransaction(Context context, boolean success) {
|
||||
public static void endTransaction(boolean success) {
|
||||
if (success) {
|
||||
getInstance(context).setTransactionSuccessful();
|
||||
getInstance().setTransactionSuccessful();
|
||||
}
|
||||
getInstance(context).endTransaction();
|
||||
getInstance().endTransaction();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -81,18 +81,18 @@ public class DictionaryDb {
|
|||
}
|
||||
|
||||
|
||||
public static void truncateWords(Context context, Handler handler) {
|
||||
public static void truncateWords(Handler handler) {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
getInstance(context).clearAllTables();
|
||||
getInstance().clearAllTables();
|
||||
handler.sendEmptyMessage(0);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
|
||||
public static void insertWord(Context context, Handler handler, Language language, String word) throws Exception {
|
||||
public static void insertWord(Handler handler, Language language, String word) throws Exception {
|
||||
if (language == null) {
|
||||
throw new InvalidLanguageException();
|
||||
}
|
||||
|
|
@ -111,8 +111,8 @@ public class DictionaryDb {
|
|||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
getInstance(context).wordsDao().insert(dbWord);
|
||||
getInstance(context).wordsDao().incrementFrequency(dbWord.langId, dbWord.word, dbWord.sequence);
|
||||
getInstance().wordsDao().insert(dbWord);
|
||||
getInstance().wordsDao().incrementFrequency(dbWord.langId, dbWord.word, dbWord.sequence);
|
||||
handler.sendEmptyMessage(0);
|
||||
} catch (SQLiteConstraintException e) {
|
||||
String msg = "Constraint violation when inserting a word: '" + dbWord.word + "' / sequence: '" + dbWord.sequence + "', for language: " + dbWord.langId;
|
||||
|
|
@ -128,12 +128,12 @@ public class DictionaryDb {
|
|||
}
|
||||
|
||||
|
||||
public static void insertWordsSync(Context context, List<Word> words) {
|
||||
getInstance(context).wordsDao().insertMany(words);
|
||||
public static void insertWordsSync(List<Word> words) {
|
||||
getInstance().wordsDao().insertMany(words);
|
||||
}
|
||||
|
||||
|
||||
public static void incrementWordFrequency(Context context, Language language, String word, String sequence) throws Exception {
|
||||
public static void incrementWordFrequency(Language language, String word, String sequence) throws Exception {
|
||||
if (language == null) {
|
||||
throw new InvalidLanguageException();
|
||||
}
|
||||
|
|
@ -153,7 +153,7 @@ public class DictionaryDb {
|
|||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
getInstance(context).wordsDao().incrementFrequency(language.getId(), word, sequence);
|
||||
getInstance().wordsDao().incrementFrequency(language.getId(), word, sequence);
|
||||
} catch (Exception e) {
|
||||
Logger.e(
|
||||
DictionaryDb.class.getName(),
|
||||
|
|
@ -165,7 +165,7 @@ public class DictionaryDb {
|
|||
}
|
||||
|
||||
|
||||
public static void getSuggestions(Context context, Handler handler, Language language, String sequence, int minimumWords, int maximumWords) {
|
||||
public static void getSuggestions(Handler handler, Language language, String sequence, int minimumWords, int maximumWords) {
|
||||
final int minWords = Math.max(minimumWords, 0);
|
||||
final int maxWords = Math.max(maximumWords, minimumWords);
|
||||
|
||||
|
|
@ -173,24 +173,24 @@ public class DictionaryDb {
|
|||
@Override
|
||||
public void run() {
|
||||
if (sequence == null || sequence.length() == 0) {
|
||||
Logger.w("tt9/getSuggestions", "Attempting to get suggestions for an empty sequence.");
|
||||
Logger.w("tt9/db.getSuggestions", "Attempting to get suggestions for an empty sequence.");
|
||||
sendSuggestions(handler, new ArrayList<>());
|
||||
return;
|
||||
}
|
||||
|
||||
if (language == null) {
|
||||
Logger.w("tt9/getSuggestions", "Attempting to get suggestions for NULL language.");
|
||||
Logger.w("tt9/db.getSuggestions", "Attempting to get suggestions for NULL language.");
|
||||
sendSuggestions(handler, new ArrayList<>());
|
||||
return;
|
||||
}
|
||||
|
||||
// get exact sequence matches, for example: "9422" -> "what"
|
||||
List<Word> exactMatches = getInstance(context).wordsDao().getMany(language.getId(), sequence, maxWords);
|
||||
Logger.d("getWords", "Exact matches: " + exactMatches.size());
|
||||
List<Word> exactMatches = getInstance().wordsDao().getMany(language.getId(), sequence, maxWords);
|
||||
Logger.d("db.getSuggestions", "Exact matches: " + exactMatches.size());
|
||||
|
||||
ArrayList<String> suggestions = new ArrayList<>();
|
||||
for (Word word : exactMatches) {
|
||||
Logger.d("getWords", "exact match: " + word.word + ", priority: " + word.frequency);
|
||||
Logger.d("db.getSuggestions", "exact match: " + word.word + ", priority: " + word.frequency);
|
||||
suggestions.add(word.word);
|
||||
}
|
||||
|
||||
|
|
@ -198,15 +198,19 @@ public class DictionaryDb {
|
|||
// for example: "rol" => "roll", "roller", "rolling", ...
|
||||
if (exactMatches.size() < minWords && sequence.length() >= 2) {
|
||||
int extraWordsNeeded = minWords - exactMatches.size();
|
||||
List<Word> extraWords = getInstance(context).wordsDao().getFuzzy(language.getId(), sequence, extraWordsNeeded);
|
||||
Logger.d("getWords", "Fuzzy matches: " + extraWords.size());
|
||||
List<Word> extraWords = getInstance().wordsDao().getFuzzy(language.getId(), sequence, extraWordsNeeded);
|
||||
Logger.d("db.getSuggestions", "Fuzzy matches: " + extraWords.size());
|
||||
|
||||
for (Word word : extraWords) {
|
||||
Logger.d("getWords", "fuzzy match: " + word.word + ", sequence: " + word.sequence);
|
||||
Logger.d("db.getSuggestions", "fuzzy match: " + word.word + ", sequence: " + word.sequence);
|
||||
suggestions.add(word.word);
|
||||
}
|
||||
}
|
||||
|
||||
if (suggestions.size() == 0) {
|
||||
Logger.i("db.getSuggestions", "No suggestions for sequence: " + sequence);
|
||||
}
|
||||
|
||||
// pack the words in a message and send it to the calling thread
|
||||
sendSuggestions(handler, suggestions);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import java.util.ArrayList;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
|
||||
|
||||
class InputFieldHelper {
|
||||
public static boolean isThereText(InputConnection currentInputConnection) {
|
||||
|
|
@ -79,7 +81,7 @@ class InputFieldHelper {
|
|||
ArrayList<Integer> allowedModes = new ArrayList<>();
|
||||
|
||||
if (inputField == null) {
|
||||
allowedModes.add(TraditionalT9.MODE_123);
|
||||
allowedModes.add(InputMode.MODE_123);
|
||||
return allowedModes;
|
||||
}
|
||||
|
||||
|
|
@ -90,8 +92,8 @@ class InputFieldHelper {
|
|||
&& inputField.privateImeOptions.equals("io.github.sspanak.tt9.addword=true")
|
||||
)
|
||||
) {
|
||||
allowedModes.add(TraditionalT9.MODE_123);
|
||||
allowedModes.add(TraditionalT9.MODE_ABC);
|
||||
allowedModes.add(InputMode.MODE_123);
|
||||
allowedModes.add(InputMode.MODE_ABC);
|
||||
return allowedModes;
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +105,7 @@ class InputFieldHelper {
|
|||
case InputType.TYPE_CLASS_PHONE:
|
||||
// Phones will also default to the symbols keyboard, though
|
||||
// often you will want to have a dedicated phone keyboard.
|
||||
allowedModes.add(TraditionalT9.MODE_123);
|
||||
allowedModes.add(InputMode.MODE_123);
|
||||
return allowedModes;
|
||||
|
||||
case InputType.TYPE_CLASS_TEXT:
|
||||
|
|
@ -112,7 +114,7 @@ class InputFieldHelper {
|
|||
// be doing predictive text (showing candidates as the
|
||||
// user types).
|
||||
if (!isSpecializedTextField(inputField)) {
|
||||
allowedModes.add(TraditionalT9.MODE_PREDICTIVE);
|
||||
allowedModes.add(InputMode.MODE_PREDICTIVE);
|
||||
}
|
||||
|
||||
// ↓ fallthrough to add ABC and 123 modes ↓
|
||||
|
|
@ -120,8 +122,8 @@ class InputFieldHelper {
|
|||
default:
|
||||
// For all unknown input types, default to the alphabetic
|
||||
// keyboard with no special features.
|
||||
allowedModes.add(TraditionalT9.MODE_123);
|
||||
allowedModes.add(TraditionalT9.MODE_ABC);
|
||||
allowedModes.add(InputMode.MODE_123);
|
||||
allowedModes.add(InputMode.MODE_ABC);
|
||||
|
||||
return allowedModes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ package io.github.sspanak.tt9.ime;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.languages.definitions.English;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.languages.definitions.English;
|
||||
import io.github.sspanak.tt9.preferences.T9Preferences;
|
||||
|
||||
public class InputModeValidator {
|
||||
|
|
@ -42,16 +43,16 @@ public class InputModeValidator {
|
|||
return validLanguage;
|
||||
}
|
||||
|
||||
public static int validateMode(T9Preferences prefs, int inputMode, ArrayList<Integer> allowedModes) {
|
||||
if (allowedModes.size() > 0 && allowedModes.contains(inputMode)) {
|
||||
public static InputMode validateMode(T9Preferences prefs, InputMode inputMode, ArrayList<Integer> allowedModes) {
|
||||
if (allowedModes.size() > 0 && allowedModes.contains(inputMode.getId())) {
|
||||
return inputMode;
|
||||
}
|
||||
|
||||
int newMode = allowedModes.size() > 0 ? allowedModes.get(0) : TraditionalT9.MODE_123;
|
||||
InputMode newMode = InputMode.getInstance(allowedModes.size() > 0 ? allowedModes.get(0) : InputMode.MODE_123);
|
||||
prefs.saveInputMode(newMode);
|
||||
|
||||
if (newMode != inputMode) {
|
||||
Logger.w("tt9/validateMode", "Invalid input mode: " + inputMode + " Enforcing: " + newMode);
|
||||
if (newMode.getId() != inputMode.getId()) {
|
||||
Logger.w("tt9/validateMode", "Invalid input mode: " + inputMode.getId() + " Enforcing: " + newMode.getId());
|
||||
}
|
||||
|
||||
return newMode;
|
||||
|
|
@ -62,7 +63,7 @@ public class InputModeValidator {
|
|||
return textCase;
|
||||
}
|
||||
|
||||
int newCase = allowedTextCases.size() > 0 ? allowedTextCases.get(0) : TraditionalT9.CASE_LOWER;
|
||||
int newCase = allowedTextCases.size() > 0 ? allowedTextCases.get(0) : InputMode.CASE_LOWER;
|
||||
prefs.saveTextCase(newCase);
|
||||
|
||||
if (textCase != newCase) {
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import android.view.View;
|
|||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
import io.github.sspanak.tt9.ui.CandidateView;
|
||||
import io.github.sspanak.tt9.preferences.T9Preferences;
|
||||
import io.github.sspanak.tt9.ui.CandidateView;
|
||||
|
||||
|
||||
abstract class KeyPadHandler extends InputMethodService {
|
||||
|
|
@ -28,7 +28,7 @@ abstract class KeyPadHandler extends InputMethodService {
|
|||
// temporal key handling
|
||||
private int ignoreNextKeyUp = 0;
|
||||
private int lastKeyCode = 0;
|
||||
protected boolean isNumKeyRepeated = false;
|
||||
private boolean isNumKeyRepeated = false;
|
||||
|
||||
// throttling
|
||||
private static final int BACKSPACE_DEBOUNCE_TIME = 80;
|
||||
|
|
@ -42,7 +42,7 @@ abstract class KeyPadHandler extends InputMethodService {
|
|||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
prefs = T9Preferences.getInstance(this);
|
||||
prefs = new T9Preferences(getApplicationContext());
|
||||
|
||||
onInit();
|
||||
}
|
||||
|
|
@ -95,8 +95,8 @@ abstract class KeyPadHandler extends InputMethodService {
|
|||
@Override
|
||||
public void onStartInput(EditorInfo inputField, boolean restarting) {
|
||||
currentInputConnection = getCurrentInputConnection();
|
||||
// Logger.d("T9.onStartInput", "INPUTTYPE: " + inputField.inputType + " FIELDID: " + inputField.fieldId +
|
||||
// " FIELDNAME: " + inputField.fieldName + " PACKAGE NAME: " + inputField.packageName);
|
||||
// Logger.d("T9.onStartInput", "inputType: " + inputField.inputType + " fieldId: " + inputField.fieldId +
|
||||
// " fieldName: " + inputField.fieldName + " packageName: " + inputField.packageName);
|
||||
|
||||
mEditing = NON_EDIT;
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ abstract class KeyPadHandler extends InputMethodService {
|
|||
}
|
||||
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_0: return on0(true);
|
||||
case KeyEvent.KEYCODE_0:
|
||||
case KeyEvent.KEYCODE_1:
|
||||
case KeyEvent.KEYCODE_2:
|
||||
case KeyEvent.KEYCODE_3:
|
||||
|
|
@ -229,7 +229,7 @@ abstract class KeyPadHandler extends InputMethodService {
|
|||
case KeyEvent.KEYCODE_7:
|
||||
case KeyEvent.KEYCODE_8:
|
||||
case KeyEvent.KEYCODE_9:
|
||||
return on1to9(keyCodeToKeyNumber(keyCode), true);
|
||||
return onNumber(keyCodeToKeyNumber(keyCode), true, false);
|
||||
}
|
||||
|
||||
ignoreNextKeyUp = 0;
|
||||
|
|
@ -275,7 +275,7 @@ abstract class KeyPadHandler extends InputMethodService {
|
|||
}
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_0) {
|
||||
return on0(false);
|
||||
return onNumber(0, false, isNumKeyRepeated);
|
||||
}
|
||||
|
||||
// dialer fields are similar to pure numeric fields, but for user convenience, holding "0"
|
||||
|
|
@ -305,7 +305,7 @@ abstract class KeyPadHandler extends InputMethodService {
|
|||
case KeyEvent.KEYCODE_7:
|
||||
case KeyEvent.KEYCODE_8:
|
||||
case KeyEvent.KEYCODE_9:
|
||||
return on1to9(keyCodeToKeyNumber(keyCode), false);
|
||||
return onNumber(keyCodeToKeyNumber(keyCode), false, isNumKeyRepeated);
|
||||
case KeyEvent.KEYCODE_STAR: return onStar();
|
||||
case KeyEvent.KEYCODE_POUND: return onPound();
|
||||
}
|
||||
|
|
@ -378,8 +378,7 @@ abstract class KeyPadHandler extends InputMethodService {
|
|||
abstract public boolean onOK();
|
||||
abstract protected boolean onUp();
|
||||
abstract protected boolean onDown();
|
||||
abstract protected boolean on0(boolean hold);
|
||||
abstract protected boolean on1to9(int key, boolean hold);
|
||||
abstract protected boolean onNumber(int key, boolean hold, boolean repeat);
|
||||
abstract protected boolean onStar();
|
||||
abstract protected boolean onPound();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package io.github.sspanak.tt9.ime;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
|
|
@ -8,18 +9,39 @@ import io.github.sspanak.tt9.ui.UI;
|
|||
|
||||
class SoftKeyHandler implements View.OnTouchListener {
|
||||
private static final int[] buttons = { R.id.main_left, R.id.main_right, R.id.main_mid };
|
||||
private final TraditionalT9 parent;
|
||||
private final TraditionalT9 tt9;
|
||||
private View view = null;
|
||||
|
||||
public SoftKeyHandler(View mainView, TraditionalT9 tt9) {
|
||||
this.parent = tt9;
|
||||
changeView(mainView);
|
||||
public SoftKeyHandler(LayoutInflater layoutInflater, TraditionalT9 tt9) {
|
||||
this.tt9 = tt9;
|
||||
|
||||
createView(layoutInflater);
|
||||
}
|
||||
|
||||
|
||||
public void changeView(View v) {
|
||||
for (int buttonId : buttons) {
|
||||
View button = v.findViewById(buttonId);
|
||||
button.setOnTouchListener(this);
|
||||
View createView(LayoutInflater layoutInflater) {
|
||||
if (view == null) {
|
||||
view = layoutInflater.inflate(R.layout.mainview, null);
|
||||
|
||||
for (int buttonId : buttons) {
|
||||
view.findViewById(buttonId).setOnTouchListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
void show() {
|
||||
if (view != null) {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hide() {
|
||||
if (view != null) {
|
||||
view.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -30,17 +52,17 @@ class SoftKeyHandler implements View.OnTouchListener {
|
|||
int buttonId = view.getId();
|
||||
|
||||
if (buttonId == R.id.main_left && action == MotionEvent.ACTION_UP) {
|
||||
UI.showPreferencesScreen(parent);
|
||||
UI.showPreferencesScreen(tt9);
|
||||
return view.performClick();
|
||||
}
|
||||
|
||||
if (buttonId == R.id.main_mid && action == MotionEvent.ACTION_UP) {
|
||||
parent.onOK();
|
||||
tt9.onOK();
|
||||
return view.performClick();
|
||||
}
|
||||
|
||||
if (buttonId == R.id.main_right && action == MotionEvent.AXIS_PRESSURE) {
|
||||
return parent.handleBackspaceHold();
|
||||
return tt9.handleBackspaceHold();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package io.github.sspanak.tt9.ime;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
|
@ -9,31 +10,24 @@ import android.view.View;
|
|||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.languages.Punctuation;
|
||||
import io.github.sspanak.tt9.ui.UI;
|
||||
|
||||
public class TraditionalT9 extends KeyPadHandler {
|
||||
private static TraditionalT9 self;
|
||||
|
||||
// input mode
|
||||
public static final int MODE_PREDICTIVE = 0;
|
||||
public static final int MODE_ABC = 1;
|
||||
public static final int MODE_123 = 2;
|
||||
private ArrayList<Integer> allowedInputModes = new ArrayList<>();
|
||||
private int mInputMode = MODE_123;
|
||||
private InputMode mInputMode;
|
||||
|
||||
// text case
|
||||
public static final int CASE_LOWER = 0;
|
||||
public static final int CASE_CAPITALIZE = 1;
|
||||
public static final int CASE_UPPER = 2;
|
||||
private ArrayList<Integer> allowedTextCases = new ArrayList<>();
|
||||
private int mTextCase = CASE_LOWER;
|
||||
private int mTextCase = InputMode.CASE_LOWER;
|
||||
|
||||
// language
|
||||
protected ArrayList<Integer> mEnabledLanguages;
|
||||
|
|
@ -41,16 +35,18 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
// soft key view
|
||||
private SoftKeyHandler softKeyHandler = null;
|
||||
private View softKeyView = null;
|
||||
|
||||
// @todo: move predictive mode stuff in its own class in #66
|
||||
private String predictionSequence = "";
|
||||
|
||||
|
||||
public static Context getMainContext() {
|
||||
return self.getApplicationContext();
|
||||
}
|
||||
|
||||
|
||||
private void loadPreferences() {
|
||||
mLanguage = LanguageCollection.getLanguage(prefs.getInputLanguage());
|
||||
mEnabledLanguages = prefs.getEnabledLanguages();
|
||||
mInputMode = prefs.getInputMode();
|
||||
mInputMode = InputMode.getInstance(prefs.getInputMode());
|
||||
mTextCase = prefs.getTextCase();
|
||||
}
|
||||
|
||||
|
|
@ -67,8 +63,10 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
protected void onInit() {
|
||||
self = this;
|
||||
|
||||
if (softKeyHandler == null) {
|
||||
softKeyHandler = new SoftKeyHandler(getLayoutInflater().inflate(R.layout.mainview, null), this);
|
||||
softKeyHandler = new SoftKeyHandler(getLayoutInflater(), this);
|
||||
}
|
||||
|
||||
loadPreferences();
|
||||
|
|
@ -77,15 +75,18 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
protected void onRestart(EditorInfo inputField) {
|
||||
// in case we are back from Preferences screen, update the language list
|
||||
mEnabledLanguages = prefs.getEnabledLanguages();
|
||||
validatePreferences();
|
||||
// determine the valid state for the current input field and preferences
|
||||
determineAllowedInputModes(inputField);
|
||||
determineAllowedTextCases();
|
||||
mEnabledLanguages = prefs.getEnabledLanguages(); // in case we are back from Preferences screen, update the language list
|
||||
|
||||
// reset all UI elements
|
||||
predictionSequence = "";
|
||||
// enforce a valid initial state
|
||||
validatePreferences();
|
||||
clearSuggestions();
|
||||
|
||||
// build the UI
|
||||
UI.updateStatusIcon(this, mLanguage, mInputMode, mTextCase);
|
||||
displaySoftKeyMenu();
|
||||
softKeyHandler.show();
|
||||
if (!isInputViewShown()) {
|
||||
showWindow(true);
|
||||
}
|
||||
|
|
@ -93,37 +94,31 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
requestShowSelf(1);
|
||||
}
|
||||
|
||||
determineAllowedInputModes(inputField);
|
||||
determineAllowedTextCases();
|
||||
|
||||
restoreAddedWordIfAny();
|
||||
}
|
||||
|
||||
|
||||
protected void onFinish() {
|
||||
predictionSequence = "";
|
||||
clearSuggestions();
|
||||
|
||||
hideStatusIcon();
|
||||
hideWindow();
|
||||
|
||||
if (softKeyView != null) {
|
||||
softKeyView.setVisibility(View.GONE);
|
||||
}
|
||||
softKeyHandler.hide();
|
||||
}
|
||||
|
||||
|
||||
public boolean onBackspace() {
|
||||
if (!InputFieldHelper.isThereText(currentInputConnection)) {
|
||||
Logger.d("onBackspace", "backspace ignored");
|
||||
mInputMode.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
resetKeyRepeat();
|
||||
|
||||
if (mInputMode == MODE_PREDICTIVE && predictionSequence.length() > 1) {
|
||||
predictionSequence = predictionSequence.substring(0, predictionSequence.length() - 1);
|
||||
applyPredictionSequence();
|
||||
if (mInputMode.onBackspace()) {
|
||||
getSuggestions();
|
||||
} else {
|
||||
commitCurrentSuggestion();
|
||||
super.sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
|
||||
|
|
@ -139,6 +134,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
acceptCurrentSuggestion();
|
||||
resetKeyRepeat();
|
||||
mInputMode.reset();
|
||||
|
||||
return !isSuggestionViewHidden();
|
||||
}
|
||||
|
|
@ -153,72 +149,46 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
return nextSuggestion();
|
||||
}
|
||||
|
||||
/**
|
||||
* onNumber
|
||||
*
|
||||
* @param key Must be a number from 1 to 9, not a "KeyEvent.KEYCODE_X"
|
||||
* @param hold If "true" we are calling the handler, because the key is being held.
|
||||
* @param repeat If "true" we are calling the handler, because the key was pressed more than once
|
||||
* @return boolean
|
||||
*/
|
||||
protected boolean onNumber(int key, boolean hold, boolean repeat) {
|
||||
if (mInputMode.shouldAcceptCurrentSuggestion(key, hold, repeat)) {
|
||||
acceptCurrentSuggestion();
|
||||
}
|
||||
|
||||
protected boolean on0(boolean hold) {
|
||||
if (!hold && nextSuggestionInModeAbc()) {
|
||||
if (!mInputMode.onNumber(mLanguage, key, hold, repeat)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mInputMode.shouldSelectNextSuggestion() && !isSuggestionViewHidden()) {
|
||||
nextSuggestion();
|
||||
return true;
|
||||
}
|
||||
|
||||
acceptCurrentSuggestion();
|
||||
|
||||
setSuggestions(
|
||||
mInputMode == MODE_ABC && !hold ? mLanguage.getKeyCharacters(0) : null,
|
||||
0
|
||||
);
|
||||
|
||||
if (hold) {
|
||||
String chr = mInputMode == MODE_123 ? "+" : "0";
|
||||
currentInputConnection.commitText(chr, 1);
|
||||
} else if (mInputMode == MODE_PREDICTIVE) {
|
||||
currentInputConnection.commitText(" ", 1);
|
||||
} else if (mInputMode == MODE_123) {
|
||||
currentInputConnection.commitText("0", 1);
|
||||
if (mInputMode.getWord() != null) {
|
||||
setText(mInputMode.getWord());
|
||||
} else {
|
||||
getSuggestions();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* on1to9
|
||||
*
|
||||
* @param key Must be a number from 1 to 9, not a "KeyEvent.KEYCODE_X"
|
||||
* @param hold If "true" we are calling the handler, because the key is being held.
|
||||
* @return boolean
|
||||
*/
|
||||
protected boolean on1to9(int key, boolean hold) {
|
||||
if (mInputMode == MODE_123) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hold) {
|
||||
commitCurrentSuggestion(); // commit the previous one before adding the "hold" character
|
||||
currentInputConnection.commitText(String.valueOf(key), 1);
|
||||
return true;
|
||||
} else if (wordInPredictiveMode(key)) {
|
||||
return true;
|
||||
} else if (emoticonInPredictiveMode(key)) {
|
||||
return true;
|
||||
} else if (nextSuggestionInModeAbc()) {
|
||||
return true;
|
||||
} else if (mInputMode == MODE_ABC || mInputMode == MODE_PREDICTIVE) {
|
||||
commitCurrentSuggestion(); // commit the previous one before suggesting the new one
|
||||
setSuggestions(mLanguage.getKeyCharacters(key, mTextCase == CASE_LOWER));
|
||||
setComposingTextFromCurrentSuggestion();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected boolean onPound() {
|
||||
currentInputConnection.commitText("#", 1);
|
||||
setText("#");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected boolean onStar() {
|
||||
currentInputConnection.commitText("*", 1);
|
||||
setText("*");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +201,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
if (hold) {
|
||||
nextLang();
|
||||
} else {
|
||||
nextKeyMode();
|
||||
nextInputMode();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -254,7 +224,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
protected boolean shouldTrackNumPress() {
|
||||
return mInputMode != TraditionalT9.MODE_123;
|
||||
return mInputMode.shouldTrackNumPress();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -274,9 +244,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
}
|
||||
|
||||
mSuggestionView.scrollToSuggestion(-1);
|
||||
|
||||
String word = mSuggestionView.getCurrentSuggestion();
|
||||
currentInputConnection.setComposingText(word, word.length());
|
||||
setComposingTextFromCurrentSuggestion();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -288,143 +256,46 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
}
|
||||
|
||||
mSuggestionView.scrollToSuggestion(1);
|
||||
|
||||
String word = mSuggestionView.getCurrentSuggestion();
|
||||
currentInputConnection.setComposingText(word, word.length());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private boolean emoticonInPredictiveMode(int key) {
|
||||
if (key != 1 || mInputMode != MODE_PREDICTIVE || !isNumKeyRepeated) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setSuggestions(Punctuation.Emoticons);
|
||||
setComposingTextFromCurrentSuggestion();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleSuggestions(ArrayList<String> suggestions, int maxWordLength) {
|
||||
setSuggestions(suggestions);
|
||||
|
||||
private boolean wordInPredictiveMode(int key) {
|
||||
if (
|
||||
mInputMode != MODE_PREDICTIVE ||
|
||||
// 0 is not a word, but space, so we handle it in on0().
|
||||
key == 0 ||
|
||||
// double 1 is not a word, but an emoticon and it is handled elsewhere
|
||||
(key == 1 && isNumKeyRepeated)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
// Punctuation is considered "a word", so that we can increase the priority as needed
|
||||
// Also, it must break the current word.
|
||||
(key == 1 && predictionSequence.length() > 0) ||
|
||||
// On the other hand, letters also "break" punctuation.
|
||||
(key != 1 && predictionSequence.endsWith("1"))
|
||||
) {
|
||||
acceptCurrentSuggestion();
|
||||
}
|
||||
|
||||
predictionSequence += key;
|
||||
applyPredictionSequence();
|
||||
|
||||
return true;
|
||||
// Put the first suggestion in the text field,
|
||||
// but cut it off to the length of the sequence (how many keys were pressed),
|
||||
// for a more intuitive experience.
|
||||
String word = mSuggestionView.getCurrentSuggestion();
|
||||
word = word.substring(0, Math.min(maxWordLength, word.length()));
|
||||
setComposingText(word);
|
||||
}
|
||||
|
||||
private final Handler handleSuggestions = new Handler(Looper.getMainLooper()) {
|
||||
private final Handler handleSuggestionsAsync = new Handler(Looper.getMainLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
ArrayList<String> suggestions = msg.getData().getStringArrayList("suggestions");
|
||||
suggestions = guessSuggestionsWhenNone(suggestions, mSuggestionView.getCurrentSuggestion());
|
||||
|
||||
setSuggestions(suggestions);
|
||||
mSuggestionView.changeCase(mTextCase, mLanguage.getLocale());
|
||||
|
||||
// Put the first suggestion in the text field,
|
||||
// but cut it off to the length of the sequence (how many keys were pressed),
|
||||
// for a more intuitive experience.
|
||||
String word = mSuggestionView.getCurrentSuggestion();
|
||||
word = mSuggestionView.getCurrentSuggestion().substring(0, Math.min(predictionSequence.length(), word.length()));
|
||||
currentInputConnection.setComposingText(word, word.length());
|
||||
handleSuggestions(
|
||||
msg.getData().getStringArrayList("suggestions"),
|
||||
msg.getData().getInt("maxWordLength", 1000)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
private void applyPredictionSequence() {
|
||||
if (predictionSequence.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
DictionaryDb.getSuggestions(
|
||||
this,
|
||||
handleSuggestions,
|
||||
mLanguage,
|
||||
predictionSequence,
|
||||
prefs.getSuggestionsMin(),
|
||||
prefs.getSuggestionsMax()
|
||||
);
|
||||
}
|
||||
|
||||
private ArrayList<String> guessSuggestionsWhenNone(ArrayList<String> suggestions, String lastWord) {
|
||||
if (
|
||||
(suggestions != null && suggestions.size() > 0) ||
|
||||
predictionSequence.length() == 0 ||
|
||||
predictionSequence.charAt(0) == '1'
|
||||
) {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
lastWord = lastWord.substring(0, Math.min(predictionSequence.length() - 1, lastWord.length()));
|
||||
try {
|
||||
int lastDigit = predictionSequence.charAt(predictionSequence.length() - 1) - '0';
|
||||
lastWord += mLanguage.getKeyCharacters(lastDigit).get(0);
|
||||
} catch (Exception e) {
|
||||
lastWord += predictionSequence.charAt(predictionSequence.length() - 1);
|
||||
}
|
||||
|
||||
return new ArrayList<>(Collections.singletonList(lastWord));
|
||||
}
|
||||
|
||||
|
||||
private boolean nextSuggestionInModeAbc() {
|
||||
return isNumKeyRepeated && mInputMode == MODE_ABC && nextSuggestion();
|
||||
}
|
||||
|
||||
|
||||
private void acceptCurrentSuggestion() {
|
||||
// bring this word up in the suggestions list next time
|
||||
if (mInputMode == MODE_PREDICTIVE) {
|
||||
String currentWord = mSuggestionView.getCurrentSuggestion();
|
||||
if (currentWord.length() == 0) {
|
||||
Logger.i("acceptCurrentSuggestion", "Current word is empty. Nothing to accept.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String sequence = mLanguage.getDigitSequenceForWord(currentWord);
|
||||
DictionaryDb.incrementWordFrequency(this, mLanguage, currentWord, sequence);
|
||||
} catch (Exception e) {
|
||||
Logger.e(getClass().getName(), "Failed incrementing priority of word: '" + currentWord + "'. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
mInputMode.onAcceptSuggestion(mLanguage, mSuggestionView.getCurrentSuggestion());
|
||||
commitCurrentSuggestion();
|
||||
}
|
||||
|
||||
|
||||
private void commitCurrentSuggestion() {
|
||||
predictionSequence = "";
|
||||
|
||||
// commit the current suggestion to the input field
|
||||
if (!isSuggestionViewHidden()) {
|
||||
if (mSuggestionView.getCurrentSuggestion().equals(" ")) {
|
||||
// finishComposingText() seems to ignore a single space,
|
||||
// so we have to force commit it.
|
||||
currentInputConnection.commitText(" ", 1);
|
||||
setText(" ");
|
||||
} else {
|
||||
currentInputConnection.finishComposingText();
|
||||
}
|
||||
|
|
@ -435,34 +306,47 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
private void clearSuggestions() {
|
||||
setSuggestions(null);
|
||||
|
||||
if (currentInputConnection != null) {
|
||||
currentInputConnection.setComposingText("", 1);
|
||||
setComposingTextFromCurrentSuggestion();
|
||||
currentInputConnection.finishComposingText();
|
||||
}
|
||||
|
||||
setSuggestions(null);
|
||||
}
|
||||
|
||||
protected void setSuggestions(List<String> suggestions) {
|
||||
setSuggestions(suggestions, 0);
|
||||
private void getSuggestions() {
|
||||
if (!mInputMode.getSuggestionsAsync(handleSuggestionsAsync, mLanguage, mSuggestionView.getCurrentSuggestion())) {
|
||||
handleSuggestions(mInputMode.getSuggestions(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setSuggestions(List<String> suggestions, int initialSel) {
|
||||
private void setSuggestions(List<String> suggestions) {
|
||||
if (mSuggestionView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean show = suggestions != null && suggestions.size() > 0;
|
||||
|
||||
mSuggestionView.setSuggestions(suggestions, initialSel);
|
||||
mSuggestionView.setSuggestions(suggestions, 0);
|
||||
mSuggestionView.changeCase(mTextCase, mLanguage.getLocale());
|
||||
setCandidatesViewShown(show);
|
||||
}
|
||||
|
||||
private void setText(String text) {
|
||||
if (text != null) {
|
||||
currentInputConnection.commitText(text, text.length());
|
||||
}
|
||||
}
|
||||
|
||||
private void nextKeyMode() {
|
||||
private void setComposingText(String text) {
|
||||
currentInputConnection.setComposingText(text, 1);
|
||||
}
|
||||
|
||||
|
||||
private void nextInputMode() {
|
||||
if (mEditing == EDITING_STRICT_NUMERIC || mEditing == EDITING_DIALER) {
|
||||
clearSuggestions();
|
||||
mInputMode = MODE_123;
|
||||
mInputMode = InputMode.getInstance(InputMode.MODE_123);
|
||||
}
|
||||
// when typing a word or viewing scrolling the suggestions, only change the case
|
||||
else if (!isSuggestionViewHidden()) {
|
||||
|
|
@ -475,13 +359,13 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
setComposingTextFromCurrentSuggestion();
|
||||
}
|
||||
// make "abc" and "ABC" separate modes from user perspective
|
||||
else if (mInputMode == MODE_ABC && mTextCase == CASE_LOWER) {
|
||||
mTextCase = CASE_UPPER;
|
||||
else if (mInputMode.isABC() && mTextCase == InputMode.CASE_LOWER) {
|
||||
mTextCase = InputMode.CASE_UPPER;
|
||||
} else {
|
||||
int modeIndex = (allowedInputModes.indexOf(mInputMode) + 1) % allowedInputModes.size();
|
||||
mInputMode = allowedInputModes.get(modeIndex);
|
||||
int modeIndex = (allowedInputModes.indexOf(mInputMode.getId()) + 1) % allowedInputModes.size();
|
||||
mInputMode = InputMode.getInstance(allowedInputModes.get(modeIndex));
|
||||
|
||||
mTextCase = mInputMode == MODE_PREDICTIVE ? CASE_CAPITALIZE : CASE_LOWER;
|
||||
mTextCase = mInputMode.isPredictive() ? InputMode.CASE_CAPITALIZE : InputMode.CASE_LOWER;
|
||||
}
|
||||
|
||||
// save the settings for the next time
|
||||
|
|
@ -493,7 +377,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
private void setComposingTextFromCurrentSuggestion() {
|
||||
if (!isSuggestionViewHidden()) {
|
||||
currentInputConnection.setComposingText(mSuggestionView.getCurrentSuggestion(), 1);
|
||||
setComposingText(mSuggestionView.getCurrentSuggestion());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -522,18 +406,18 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
private void determineAllowedInputModes(EditorInfo inputField) {
|
||||
allowedInputModes = InputFieldHelper.determineInputModes(inputField);
|
||||
|
||||
int lastInputMode = prefs.getInputMode();
|
||||
if (allowedInputModes.contains(lastInputMode)) {
|
||||
mInputMode = lastInputMode;
|
||||
} else if (allowedInputModes.contains(TraditionalT9.MODE_ABC)) {
|
||||
mInputMode = TraditionalT9.MODE_ABC;
|
||||
int lastInputModeId = prefs.getInputMode();
|
||||
if (allowedInputModes.contains(lastInputModeId)) {
|
||||
mInputMode = InputMode.getInstance(lastInputModeId);
|
||||
} else if (allowedInputModes.contains(InputMode.MODE_ABC)) {
|
||||
mInputMode = InputMode.getInstance(InputMode.MODE_ABC);
|
||||
} else {
|
||||
mInputMode = allowedInputModes.get(0);
|
||||
mInputMode = InputMode.getInstance(allowedInputModes.get(0));
|
||||
}
|
||||
|
||||
if (InputFieldHelper.isDialerField(inputField)) {
|
||||
mEditing = EDITING_DIALER;
|
||||
} else if (mInputMode == TraditionalT9.MODE_123 && allowedInputModes.size() == 1) {
|
||||
} else if (mInputMode.is123() && allowedInputModes.size() == 1) {
|
||||
mEditing = EDITING_STRICT_NUMERIC;
|
||||
} else {
|
||||
mEditing = InputFieldHelper.isFilterTextField(inputField) ? EDITING_NOSHOW : EDITING;
|
||||
|
|
@ -542,20 +426,8 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
private void determineAllowedTextCases() {
|
||||
// @todo: determine case from input
|
||||
|
||||
allowedTextCases = new ArrayList<>();
|
||||
|
||||
if (mInputMode == TraditionalT9.MODE_PREDICTIVE) {
|
||||
allowedTextCases.add(TraditionalT9.CASE_LOWER);
|
||||
allowedTextCases.add(TraditionalT9.CASE_CAPITALIZE);
|
||||
allowedTextCases.add(TraditionalT9.CASE_UPPER);
|
||||
} else if (mInputMode == TraditionalT9.MODE_ABC) {
|
||||
allowedTextCases.add(TraditionalT9.CASE_LOWER);
|
||||
allowedTextCases.add(TraditionalT9.CASE_UPPER);
|
||||
} else {
|
||||
allowedTextCases.add(TraditionalT9.CASE_LOWER);
|
||||
}
|
||||
allowedTextCases = mInputMode.getAllowedTextCases();
|
||||
// @todo: determine the text case of the input and validate using the allowed ones
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -581,8 +453,8 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
try {
|
||||
Logger.d("restoreAddedWordIfAny", "Restoring word: '" + word + "'...");
|
||||
predictionSequence = mLanguage.getDigitSequenceForWord(word);
|
||||
currentInputConnection.commitText(word, word.length());
|
||||
setText(word);
|
||||
mInputMode.reset();
|
||||
} catch (Exception e) {
|
||||
Logger.w("tt9/restoreLastWord", "Could not restore the last added word. " + e.getMessage());
|
||||
}
|
||||
|
|
@ -594,16 +466,6 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
* Generates the actual UI of TT9.
|
||||
*/
|
||||
protected View createSoftKeyView() {
|
||||
if (softKeyView == null) {
|
||||
softKeyView = getLayoutInflater().inflate(R.layout.mainview, null);
|
||||
}
|
||||
softKeyHandler.changeView(softKeyView);
|
||||
return softKeyView;
|
||||
}
|
||||
|
||||
|
||||
private void displaySoftKeyMenu() {
|
||||
createSoftKeyView();
|
||||
softKeyView.setVisibility(View.VISIBLE);
|
||||
return softKeyHandler.createView(getLayoutInflater());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
77
src/io/github/sspanak/tt9/ime/modes/InputMode.java
Normal file
77
src/io/github/sspanak/tt9/ime/modes/InputMode.java
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
package io.github.sspanak.tt9.ime.modes;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
|
||||
abstract public class InputMode {
|
||||
// typing mode
|
||||
public static final int MODE_PREDICTIVE = 0;
|
||||
public static final int MODE_ABC = 1;
|
||||
public static final int MODE_123 = 2;
|
||||
|
||||
// text case
|
||||
public static final int CASE_LOWER = 0;
|
||||
public static final int CASE_CAPITALIZE = 1;
|
||||
public static final int CASE_UPPER = 2;
|
||||
protected ArrayList<Integer> allowedTextCases = new ArrayList<>();
|
||||
|
||||
// data
|
||||
protected ArrayList<String> suggestions = new ArrayList<>();
|
||||
protected String word = null;
|
||||
|
||||
|
||||
public static InputMode getInstance(int mode) {
|
||||
switch(mode) {
|
||||
case MODE_PREDICTIVE:
|
||||
return new ModePredictive();
|
||||
case MODE_ABC:
|
||||
return new ModeABC();
|
||||
default:
|
||||
Logger.w("tt9/InputMode", "Defaulting to mode: " + Mode123.class.getName() + " for unknown InputMode: " + mode);
|
||||
case MODE_123:
|
||||
return new Mode123();
|
||||
}
|
||||
}
|
||||
|
||||
// Key handlers. Return "true" when handling the key or "false", when is nothing to do.
|
||||
public boolean onBackspace() { return false; }
|
||||
abstract public boolean onNumber(Language language, int key, boolean hold, boolean repeat);
|
||||
|
||||
// Suggestions
|
||||
public void onAcceptSuggestion(Language language, String suggestion) {}
|
||||
public ArrayList<String> getSuggestions() { return suggestions; }
|
||||
public boolean getSuggestionsAsync(Handler handler, Language language, String lastWord) { return false; }
|
||||
protected void sendSuggestions(Handler handler, ArrayList<String> suggestions, int maxWordLength) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putStringArrayList("suggestions", suggestions);
|
||||
bundle.putInt("maxWordLength", maxWordLength);
|
||||
Message msg = new Message();
|
||||
msg.setData(bundle);
|
||||
handler.sendMessage(msg);
|
||||
}
|
||||
|
||||
// Word
|
||||
public String getWord() { return word; }
|
||||
|
||||
// Mode identifiers
|
||||
public boolean isPredictive() { return false; }
|
||||
public boolean isABC() { return false; }
|
||||
public boolean is123() { return false; }
|
||||
|
||||
// Utility
|
||||
abstract public int getId();
|
||||
public ArrayList<Integer> getAllowedTextCases() { return allowedTextCases; }
|
||||
public void reset() {
|
||||
suggestions = new ArrayList<>();
|
||||
word = null;
|
||||
}
|
||||
public boolean shouldTrackNumPress() { return true; }
|
||||
public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) { return false; }
|
||||
public boolean shouldSelectNextSuggestion() { return false; }
|
||||
}
|
||||
28
src/io/github/sspanak/tt9/ime/modes/Mode123.java
Normal file
28
src/io/github/sspanak/tt9/ime/modes/Mode123.java
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package io.github.sspanak.tt9.ime.modes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
|
||||
public class Mode123 extends InputMode {
|
||||
public int getId() { return MODE_123; }
|
||||
|
||||
Mode123() {
|
||||
allowedTextCases.add(CASE_LOWER);
|
||||
}
|
||||
|
||||
|
||||
public boolean onNumber(Language l, int key, boolean hold, boolean repeat) {
|
||||
if (key != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
suggestions = new ArrayList<>();
|
||||
word = hold ? "+" : "0";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
final public boolean is123() { return true; }
|
||||
public boolean shouldTrackNumPress() { return false; }
|
||||
}
|
||||
38
src/io/github/sspanak/tt9/ime/modes/ModeABC.java
Normal file
38
src/io/github/sspanak/tt9/ime/modes/ModeABC.java
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package io.github.sspanak.tt9.ime.modes;
|
||||
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
|
||||
public class ModeABC extends InputMode {
|
||||
public int getId() { return MODE_ABC; }
|
||||
|
||||
private boolean shouldSelectNextLetter = false;
|
||||
|
||||
ModeABC() {
|
||||
allowedTextCases.add(CASE_LOWER);
|
||||
allowedTextCases.add(CASE_UPPER);
|
||||
}
|
||||
|
||||
|
||||
public boolean onNumber(Language language, int key, boolean hold, boolean repeat) {
|
||||
shouldSelectNextLetter = false;
|
||||
suggestions = language.getKeyCharacters(key);
|
||||
word = null;
|
||||
|
||||
if (hold) {
|
||||
suggestions = null;
|
||||
word = String.valueOf(key);
|
||||
} else if (repeat) {
|
||||
suggestions = null;
|
||||
shouldSelectNextLetter = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
final public boolean isABC() { return true; }
|
||||
public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) { return hold || !repeat; }
|
||||
public boolean shouldSelectNextSuggestion() {
|
||||
return shouldSelectNextLetter;
|
||||
}
|
||||
}
|
||||
196
src/io/github/sspanak/tt9/ime/modes/ModePredictive.java
Normal file
196
src/io/github/sspanak/tt9/ime/modes/ModePredictive.java
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
package io.github.sspanak.tt9.ime.modes;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.Punctuation;
|
||||
import io.github.sspanak.tt9.preferences.T9Preferences;
|
||||
|
||||
public class ModePredictive extends InputMode {
|
||||
public int getId() { return MODE_PREDICTIVE; }
|
||||
|
||||
private Language currentLanguage = null;
|
||||
private String digitSequence = "";
|
||||
private boolean isEmoticon = false;
|
||||
private String lastInputFieldWord = "";
|
||||
private static Handler handleSuggestionsExternal;
|
||||
|
||||
|
||||
|
||||
ModePredictive() {
|
||||
allowedTextCases.add(CASE_CAPITALIZE);
|
||||
allowedTextCases.add(CASE_LOWER);
|
||||
allowedTextCases.add(CASE_UPPER);
|
||||
}
|
||||
|
||||
|
||||
public boolean onBackspace() {
|
||||
if (digitSequence.length() < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
digitSequence = digitSequence.substring(0, digitSequence.length() - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public boolean onNumber(Language l, int key, boolean hold, boolean repeat) {
|
||||
isEmoticon = false;
|
||||
|
||||
if (hold) {
|
||||
// hold to type any digit
|
||||
reset();
|
||||
word = String.valueOf(key);
|
||||
} else if (key == 0) {
|
||||
// "0" is " "
|
||||
reset();
|
||||
word = " ";
|
||||
} else if (key == 1 && repeat) {
|
||||
// emoticons
|
||||
reset();
|
||||
isEmoticon = true;
|
||||
suggestions = Punctuation.Emoticons;
|
||||
}
|
||||
else {
|
||||
// words
|
||||
super.reset();
|
||||
digitSequence += key;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void reset() {
|
||||
super.reset();
|
||||
digitSequence = "";
|
||||
}
|
||||
|
||||
|
||||
final public boolean isPredictive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* shouldAcceptCurrentSuggestion
|
||||
* In this mode, In addition to confirming the suggestion in the input field,
|
||||
* we also increase its' priority. This function determines whether we want to do all this or not.
|
||||
*/
|
||||
public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) {
|
||||
return
|
||||
hold
|
||||
// Quickly accept suggestions using "space" instead of pressing "ok" then "space"
|
||||
|| key == 0
|
||||
// Punctuation is considered "a word", so that we can increase the priority as needed
|
||||
// Also, it must break the current word.
|
||||
|| (key == 1 && digitSequence.length() > 0 && !digitSequence.endsWith("1"))
|
||||
// On the other hand, letters also "break" punctuation.
|
||||
|| (key != 1 && digitSequence.endsWith("1"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* getSuggestionsAsync
|
||||
* Queries the dictionary database for a list of suggestions matching the current language and
|
||||
* sequence. Returns "false" when there is nothing to do.
|
||||
*
|
||||
* "lastWord" is used for generating suggestions when there are no results.
|
||||
* See: generateSuggestionWhenNone()
|
||||
*/
|
||||
public boolean getSuggestionsAsync(Handler handler, Language language, String lastWord) {
|
||||
if (isEmoticon) {
|
||||
super.sendSuggestions(handler, suggestions, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (digitSequence.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
handleSuggestionsExternal = handler;
|
||||
lastInputFieldWord = lastWord;
|
||||
currentLanguage = language;
|
||||
super.reset();
|
||||
|
||||
DictionaryDb.getSuggestions(
|
||||
handleSuggestions,
|
||||
language,
|
||||
digitSequence,
|
||||
T9Preferences.getInstance().getSuggestionsMin(),
|
||||
T9Preferences.getInstance().getSuggestionsMax()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* handleSuggestions
|
||||
* Extracts the suggestions from the Message object and passes them to the actual external Handler.
|
||||
* If there were no matches in the database, they will be generated based on the "lastInputFieldWord".
|
||||
*/
|
||||
private final Handler handleSuggestions = new Handler(Looper.getMainLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
ArrayList<String> suggestions = msg.getData().getStringArrayList("suggestions");
|
||||
suggestions = generateSuggestionWhenNone(suggestions, currentLanguage, lastInputFieldWord);
|
||||
|
||||
ModePredictive.super.sendSuggestions(handleSuggestionsExternal, suggestions, digitSequence.length());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* generateSuggestionWhenNone
|
||||
* When there are no matching suggestions after the last key press, generate a list of possible
|
||||
* ones, so that the user can complete the missing word.
|
||||
*/
|
||||
private ArrayList<String> generateSuggestionWhenNone(ArrayList<String> suggestions, Language language, String lastWord) {
|
||||
if (
|
||||
(lastWord == null || lastWord.length() == 0) ||
|
||||
(suggestions != null && suggestions.size() > 0) ||
|
||||
digitSequence.length() == 0 ||
|
||||
digitSequence.charAt(0) == '1'
|
||||
) {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
lastWord = lastWord.substring(0, Math.min(digitSequence.length() - 1, lastWord.length()));
|
||||
try {
|
||||
int lastDigit = digitSequence.charAt(digitSequence.length() - 1) - '0';
|
||||
lastWord += language.getKeyCharacters(lastDigit).get(0);
|
||||
} catch (Exception e) {
|
||||
lastWord += digitSequence.charAt(digitSequence.length() - 1);
|
||||
}
|
||||
|
||||
return new ArrayList<>(Collections.singletonList(lastWord));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* onAcceptSuggestion
|
||||
* Bring this word up in the suggestions list next time.
|
||||
*/
|
||||
public void onAcceptSuggestion(Language language, String currentWord) {
|
||||
digitSequence = "";
|
||||
|
||||
if (currentWord.length() == 0) {
|
||||
Logger.i("acceptCurrentSuggestion", "Current word is empty. Nothing to accept.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String sequence = language.getDigitSequenceForWord(currentWord);
|
||||
DictionaryDb.incrementWordFrequency(language, currentWord, sequence);
|
||||
} catch (Exception e) {
|
||||
Logger.e("tt9/ModePredictive", "Failed incrementing priority of word: '" + currentWord + "'. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -39,15 +39,11 @@ public class Language {
|
|||
}
|
||||
|
||||
public ArrayList<String> getKeyCharacters(int key) {
|
||||
return getKeyCharacters(key, true);
|
||||
}
|
||||
|
||||
public ArrayList<String> getKeyCharacters(int key, boolean lowerCase) {
|
||||
if (key < 0 || key >= characterMap.size()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
ArrayList<String> chars = lowerCase ? new ArrayList<>(characterMap.get(key)) : getUpperCaseChars(key);
|
||||
ArrayList<String> chars = new ArrayList<>(characterMap.get(key));
|
||||
if (chars.size() > 0) {
|
||||
chars.add(String.valueOf(key));
|
||||
}
|
||||
|
|
@ -55,15 +51,6 @@ public class Language {
|
|||
return chars;
|
||||
}
|
||||
|
||||
private ArrayList<String> getUpperCaseChars(int mapId) {
|
||||
ArrayList<String> uppercaseChars = new ArrayList<>();
|
||||
for (String ch : characterMap.get(mapId)) {
|
||||
uppercaseChars.add(ch.toUpperCase(locale));
|
||||
}
|
||||
|
||||
return uppercaseChars;
|
||||
}
|
||||
|
||||
public String getDigitSequenceForWord(String word) throws Exception {
|
||||
StringBuilder sequence = new StringBuilder();
|
||||
String lowerCaseWord = word.toLowerCase(locale);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import java.util.Arrays;
|
|||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
|
||||
|
||||
|
|
@ -23,13 +24,13 @@ public class T9Preferences {
|
|||
private final SharedPreferences.Editor prefsEditor;
|
||||
|
||||
public T9Preferences (Context context) {
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
prefsEditor = prefs.edit();
|
||||
}
|
||||
|
||||
public static T9Preferences getInstance(Context context) {
|
||||
public static T9Preferences getInstance() {
|
||||
if (self == null) {
|
||||
self = new T9Preferences(context);
|
||||
self = new T9Preferences(TraditionalT9.getMainContext());
|
||||
}
|
||||
|
||||
return self;
|
||||
|
|
@ -101,13 +102,13 @@ public class T9Preferences {
|
|||
}
|
||||
|
||||
public int getTextCase() {
|
||||
return prefs.getInt("pref_text_case", TraditionalT9.CASE_LOWER);
|
||||
return prefs.getInt("pref_text_case", InputMode.CASE_LOWER);
|
||||
}
|
||||
|
||||
public void saveTextCase(int textCase) {
|
||||
boolean isTextCaseValid = isIntInList(
|
||||
textCase,
|
||||
new ArrayList<>(Arrays.asList(TraditionalT9.CASE_CAPITALIZE, TraditionalT9.CASE_LOWER, TraditionalT9.CASE_UPPER)),
|
||||
new ArrayList<>(Arrays.asList(InputMode.CASE_CAPITALIZE, InputMode.CASE_LOWER, InputMode.CASE_UPPER)),
|
||||
"tt9/saveTextCase",
|
||||
"Not saving invalid text case: " + textCase
|
||||
);
|
||||
|
|
@ -131,21 +132,17 @@ public class T9Preferences {
|
|||
}
|
||||
|
||||
public int getInputMode() {
|
||||
return prefs.getInt("pref_input_mode", TraditionalT9.MODE_PREDICTIVE);
|
||||
return prefs.getInt("pref_input_mode", InputMode.MODE_PREDICTIVE);
|
||||
}
|
||||
|
||||
public void saveInputMode(int mode) {
|
||||
boolean isModeValid = isIntInList(
|
||||
mode,
|
||||
new ArrayList<>(Arrays.asList(TraditionalT9.MODE_123, TraditionalT9.MODE_ABC, TraditionalT9.MODE_PREDICTIVE)),
|
||||
"tt9/saveInputMode",
|
||||
"Not saving invalid text case: " + mode
|
||||
);
|
||||
|
||||
if (isModeValid) {
|
||||
prefsEditor.putInt("pref_input_mode", mode);
|
||||
prefsEditor.apply();
|
||||
public void saveInputMode(InputMode mode) {
|
||||
if (mode == null) {
|
||||
Logger.w("tt9/saveInputMode", "Not saving NULL input mode");
|
||||
return;
|
||||
}
|
||||
|
||||
prefsEditor.putInt("pref_input_mode", mode.getId());
|
||||
prefsEditor.apply();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public class SettingMultiList extends SettingList {
|
|||
public SettingMultiList (Context context, AttributeSet attrs, Object[] isettings) {
|
||||
super(context, attrs, isettings);
|
||||
selectedEntries = new boolean[entries.length];
|
||||
for (int langId : T9Preferences.getInstance(context).getEnabledLanguages()) {
|
||||
for (int langId : T9Preferences.getInstance().getEnabledLanguages()) {
|
||||
selectedEntries[langId - 1] = true; // languages are 1-based, unlike arrays
|
||||
}
|
||||
summary = buildItems();
|
||||
|
|
@ -39,7 +39,7 @@ public class SettingMultiList extends SettingList {
|
|||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (id.equals("pref_lang_support")) {
|
||||
T9Preferences.getInstance(context).saveEnabledLanguages(buildSelection());
|
||||
T9Preferences.getInstance().saveEnabledLanguages(buildSelection());
|
||||
}
|
||||
summary = buildItems();
|
||||
dialog.dismiss();
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class AddWordAct extends Activity {
|
|||
|
||||
View v = getLayoutInflater().inflate(R.layout.addwordview, null);
|
||||
|
||||
EditText et = (EditText) v.findViewById(R.id.add_word_text);
|
||||
EditText et = v.findViewById(R.id.add_word_text);
|
||||
et.setText(word);
|
||||
et.setSelection(word.length());
|
||||
setContentView(v);
|
||||
|
|
@ -46,7 +46,7 @@ public class AddWordAct extends Activity {
|
|||
switch (msg.what) {
|
||||
case 0:
|
||||
Logger.d("onAddedWord", "Added word: '" + word + "'...");
|
||||
T9Preferences.getInstance(main.getContext()).saveLastWord(word);
|
||||
T9Preferences.getInstance().saveLastWord(word);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
|
@ -71,7 +71,7 @@ public class AddWordAct extends Activity {
|
|||
word = ((EditText) main.findViewById(R.id.add_word_text)).getText().toString();
|
||||
Logger.d("addWord", "Attempting to add word: '" + word + "'...");
|
||||
|
||||
DictionaryDb.insertWord(this, onAddedWord, LanguageCollection.getLanguage(lang), word);
|
||||
DictionaryDb.insertWord(onAddedWord, LanguageCollection.getLanguage(lang), word);
|
||||
} catch (InsertBlankWordException e) {
|
||||
Logger.e("AddWordAct.addWord", e.getMessage());
|
||||
UI.toastLong(this, R.string.add_word_blank);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
|
||||
public class CandidateView extends View {
|
||||
|
||||
|
|
@ -200,9 +200,9 @@ public class CandidateView extends View {
|
|||
ArrayList<String> newSuggestions = new ArrayList<>();
|
||||
|
||||
for (String s : mSuggestions) {
|
||||
if (textCase == TraditionalT9.CASE_LOWER) {
|
||||
if (textCase == InputMode.CASE_LOWER) {
|
||||
newSuggestions.add(s.toLowerCase(locale));
|
||||
} else if (textCase == TraditionalT9.CASE_CAPITALIZE) {
|
||||
} else if (textCase == InputMode.CASE_CAPITALIZE) {
|
||||
String cs = s.substring(0, 1).toUpperCase(locale) + s.substring(1).toLowerCase(locale);
|
||||
newSuggestions.add(cs);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -22,17 +22,6 @@ import android.widget.ListView;
|
|||
|
||||
import com.stackoverflow.answer.UnicodeBOMInputStream;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||
import io.github.sspanak.tt9.db.Word;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.preferences.T9Preferences;
|
||||
import io.github.sspanak.tt9.settings_legacy.CustomInflater;
|
||||
import io.github.sspanak.tt9.settings_legacy.Setting;
|
||||
import io.github.sspanak.tt9.settings_legacy.SettingAdapter;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
|
|
@ -47,6 +36,17 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||
import io.github.sspanak.tt9.db.Word;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.preferences.T9Preferences;
|
||||
import io.github.sspanak.tt9.settings_legacy.CustomInflater;
|
||||
import io.github.sspanak.tt9.settings_legacy.Setting;
|
||||
import io.github.sspanak.tt9.settings_legacy.SettingAdapter;
|
||||
|
||||
public class TraditionalT9Settings extends ListActivity implements DialogInterface.OnCancelListener {
|
||||
|
||||
AsyncTask<String, Integer, Reply> task = null;
|
||||
|
|
@ -205,7 +205,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
|
||||
// add characters first, then dictionary:
|
||||
Logger.d("doInBackground", "Adding characters...");
|
||||
processChars(mContext, mSupportedLanguages);
|
||||
processChars(mSupportedLanguages);
|
||||
Logger.d("doInBackground", "Characters added.");
|
||||
|
||||
Logger.d("doInBackground", "Adding dict(s)...");
|
||||
|
|
@ -217,7 +217,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
if (internal) {
|
||||
try {
|
||||
dictstream = getAssets().open(dicts[x]);
|
||||
reply = processFile(mContext, dictstream, reply, mSupportedLanguages.get(x), dicts[x]);
|
||||
reply = processFile(dictstream, reply, mSupportedLanguages.get(x), dicts[x]);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
reply.status = false;
|
||||
|
|
@ -227,7 +227,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
try {
|
||||
dictstream = new FileInputStream(new File(
|
||||
new File(Environment.getExternalStorageDirectory(), sddir), dicts[x]));
|
||||
reply = processFile(mContext, dictstream, reply, mSupportedLanguages.get(x), dicts[x]);
|
||||
reply = processFile(dictstream, reply, mSupportedLanguages.get(x), dicts[x]);
|
||||
} catch (FileNotFoundException e) {
|
||||
reply.status = false;
|
||||
reply.forceMsg("File not found: " + e.getMessage());
|
||||
|
|
@ -264,13 +264,13 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
* processChars
|
||||
* Inserts single characters.
|
||||
*/
|
||||
private void processChars(Context context, List<Language> allLanguages) {
|
||||
private void processChars(List<Language> allLanguages) {
|
||||
ArrayList<Word> list = new ArrayList<>();
|
||||
|
||||
try {
|
||||
for (Language lang : allLanguages) {
|
||||
for (int key = 0; key <= 9; key++) {
|
||||
for (String langChar : lang.getKeyCharacters(key, true)) {
|
||||
for (String langChar : lang.getKeyCharacters(key)) {
|
||||
if (langChar.length() == 1 && langChar.charAt(0) >= '0' && langChar.charAt(0) <= '9') {
|
||||
// We do not want 0-9 as "word suggestions" in Predictive mode. It looks confusing
|
||||
// when trying to type a word and also, one can type them by holding the respective
|
||||
|
|
@ -289,7 +289,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
}
|
||||
}
|
||||
|
||||
DictionaryDb.insertWordsSync(context, list);
|
||||
DictionaryDb.insertWordsSync(list);
|
||||
} catch (Exception e) {
|
||||
Logger.e("processChars", e.getMessage());
|
||||
}
|
||||
|
|
@ -306,7 +306,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
return null;
|
||||
}
|
||||
|
||||
private Reply processFile(Context context, InputStream is, Reply rpl, Language lang, String fname)
|
||||
private Reply processFile(InputStream is, Reply rpl, Language lang, String fname)
|
||||
throws LoadException, IOException {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
|
|
@ -327,7 +327,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
|
||||
try {
|
||||
|
||||
DictionaryDb.beginTransaction(context);
|
||||
DictionaryDb.beginTransaction();
|
||||
|
||||
while (fileWord != null) {
|
||||
if (isCancelled()) {
|
||||
|
|
@ -365,7 +365,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
dbWords.add(word);
|
||||
|
||||
if (linecount % insertChunkSize == 0) {
|
||||
DictionaryDb.insertWordsSync(context, dbWords);
|
||||
DictionaryDb.insertWordsSync(dbWords);
|
||||
dbWords.clear();
|
||||
}
|
||||
|
||||
|
|
@ -376,13 +376,13 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
fileWord = getLine(br, rpl, fname);
|
||||
}
|
||||
|
||||
DictionaryDb.insertWordsSync(context, dbWords);
|
||||
DictionaryDb.endTransaction(context, true);
|
||||
DictionaryDb.insertWordsSync(dbWords);
|
||||
DictionaryDb.endTransaction(true);
|
||||
dbWords.clear();
|
||||
|
||||
publishProgress((int) ((float) pos / size * 10000));
|
||||
} catch (Exception e) {
|
||||
DictionaryDb.endTransaction(context, false);
|
||||
DictionaryDb.endTransaction(false);
|
||||
Logger.e("processFile", e.getMessage());
|
||||
} finally {
|
||||
br.close();
|
||||
|
|
@ -416,7 +416,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
// http://stackoverflow.com/questions/7645880/listview-with-onitemclicklistener-android
|
||||
|
||||
// get settings
|
||||
T9Preferences prefs = new T9Preferences(this);
|
||||
T9Preferences prefs = new T9Preferences(getApplicationContext());
|
||||
Object[] settings = {
|
||||
prefs.getInputMode()
|
||||
};
|
||||
|
|
@ -462,7 +462,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
UI.toast(mContext, R.string.dictionary_truncated);
|
||||
}
|
||||
};
|
||||
DictionaryDb.truncateWords(mContext, afterTruncate);
|
||||
DictionaryDb.truncateWords(afterTruncate);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -472,7 +472,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
task = new LoadDictTask(
|
||||
msgid,
|
||||
internal,
|
||||
LanguageCollection.getAll(T9Preferences.getInstance(mContext).getEnabledLanguages())
|
||||
LanguageCollection.getAll(T9Preferences.getInstance().getEnabledLanguages())
|
||||
);
|
||||
task.execute();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import android.widget.Toast;
|
|||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
|
||||
public class UI {
|
||||
|
|
@ -34,21 +35,16 @@ public class UI {
|
|||
* Set the status icon that is appropriate in current mode (based on
|
||||
* openwmm-legacy)
|
||||
*/
|
||||
public static void updateStatusIcon(TraditionalT9 tt9, Language inputLanguage, int inputMode, int textCase) {
|
||||
switch (inputMode) {
|
||||
case TraditionalT9.MODE_ABC:
|
||||
tt9.showStatusIcon(inputLanguage.getAbcIcon(textCase == TraditionalT9.CASE_LOWER));
|
||||
break;
|
||||
case TraditionalT9.MODE_PREDICTIVE:
|
||||
tt9.showStatusIcon(inputLanguage.getIcon());
|
||||
break;
|
||||
case TraditionalT9.MODE_123:
|
||||
tt9.showStatusIcon(R.drawable.ime_number);
|
||||
break;
|
||||
default:
|
||||
Logger.w("tt9.UI", "Unknown inputMode mode: " + inputMode + ". Hiding status icon.");
|
||||
tt9.hideStatusIcon();
|
||||
break;
|
||||
public static void updateStatusIcon(TraditionalT9 tt9, Language inputLanguage, InputMode inputMode, int textCase) {
|
||||
if (inputMode.isABC()) {
|
||||
tt9.showStatusIcon(inputLanguage.getAbcIcon(textCase == InputMode.CASE_LOWER));
|
||||
} else if (inputMode.isPredictive()) {
|
||||
tt9.showStatusIcon(inputLanguage.getIcon());
|
||||
} else if (inputMode.is123()) {
|
||||
tt9.showStatusIcon(R.drawable.ime_number);
|
||||
} else {
|
||||
Logger.w("tt9.UI", "Unknown inputMode mode: " + inputMode + ". Hiding status icon.");
|
||||
tt9.hideStatusIcon();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue