separated the Language class into smaller files and reorganized the languages package
This commit is contained in:
parent
25657d12a8
commit
58f5123bdb
61 changed files with 456 additions and 387 deletions
|
|
@ -10,9 +10,9 @@ import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.Timer;
|
import io.github.sspanak.tt9.util.Timer;
|
||||||
import io.github.sspanak.tt9.db.entities.WordBatch;
|
import io.github.sspanak.tt9.db.entities.WordBatch;
|
||||||
import io.github.sspanak.tt9.db.entities.WordFile;
|
import io.github.sspanak.tt9.db.entities.WordFile;
|
||||||
import io.github.sspanak.tt9.db.exceptions.DictionaryImportAbortedException;
|
import io.github.sspanak.tt9.db.exceptions.DictionaryImportAbortedException;
|
||||||
|
|
@ -23,8 +23,8 @@ import io.github.sspanak.tt9.db.sqlite.SQLiteOpener;
|
||||||
import io.github.sspanak.tt9.db.sqlite.Tables;
|
import io.github.sspanak.tt9.db.sqlite.Tables;
|
||||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||||
import io.github.sspanak.tt9.languages.EmojiLanguage;
|
import io.github.sspanak.tt9.languages.EmojiLanguage;
|
||||||
import io.github.sspanak.tt9.languages.InvalidLanguageCharactersException;
|
import io.github.sspanak.tt9.languages.exceptions.InvalidLanguageCharactersException;
|
||||||
import io.github.sspanak.tt9.languages.InvalidLanguageException;
|
import io.github.sspanak.tt9.languages.exceptions.InvalidLanguageException;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
import io.github.sspanak.tt9.ui.DictionaryLoadingBar;
|
import io.github.sspanak.tt9.ui.DictionaryLoadingBar;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import android.app.Activity;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
|
||||||
public class LegacyDb extends SQLiteOpenHelper {
|
public class LegacyDb extends SQLiteOpenHelper {
|
||||||
private final String LOG_TAG = getClass().getSimpleName();
|
private final String LOG_TAG = getClass().getSimpleName();
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ package io.github.sspanak.tt9.db;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.TextTools;
|
import io.github.sspanak.tt9.util.TextTools;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
public class SlowQueryStats {
|
public class SlowQueryStats {
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.Timer;
|
import io.github.sspanak.tt9.util.Timer;
|
||||||
import io.github.sspanak.tt9.db.entities.Word;
|
import io.github.sspanak.tt9.db.entities.Word;
|
||||||
import io.github.sspanak.tt9.db.entities.WordList;
|
import io.github.sspanak.tt9.db.entities.WordList;
|
||||||
import io.github.sspanak.tt9.db.sqlite.DeleteOps;
|
import io.github.sspanak.tt9.db.sqlite.DeleteOps;
|
||||||
|
|
@ -18,7 +18,8 @@ import io.github.sspanak.tt9.db.sqlite.UpdateOps;
|
||||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||||
import io.github.sspanak.tt9.languages.EmojiLanguage;
|
import io.github.sspanak.tt9.languages.EmojiLanguage;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.Text;
|
import io.github.sspanak.tt9.languages.NullLanguage;
|
||||||
|
import io.github.sspanak.tt9.util.Text;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
import io.github.sspanak.tt9.ui.dialogs.AddWordDialog;
|
import io.github.sspanak.tt9.ui.dialogs.AddWordDialog;
|
||||||
|
|
||||||
|
|
@ -68,7 +69,7 @@ public class WordStore {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (language == null) {
|
if (language == null || language instanceof NullLanguage) {
|
||||||
Logger.w(LOG_TAG, "Attempting to get words for NULL language.");
|
Logger.w(LOG_TAG, "Attempting to get words for NULL language.");
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
@ -93,12 +94,12 @@ public class WordStore {
|
||||||
|
|
||||||
|
|
||||||
@NonNull public ArrayList<String> getSimilarCustom(Language language, String wordFilter) {
|
@NonNull public ArrayList<String> getSimilarCustom(Language language, String wordFilter) {
|
||||||
return language != null && checkOrNotify() ? readOps.getCustomWords(sqlite.getDb(), language, wordFilter) : new ArrayList<>();
|
return language != null && !(language instanceof NullLanguage) && checkOrNotify() ? readOps.getCustomWords(sqlite.getDb(), language, wordFilter) : new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NonNull public String getLanguageFileHash(Language language) {
|
@NonNull public String getLanguageFileHash(Language language) {
|
||||||
return language != null && checkOrNotify() ? readOps.getLanguageFileHash(sqlite.getDb(), language.getId()) : "";
|
return language != null && !(language instanceof NullLanguage) && checkOrNotify() ? readOps.getLanguageFileHash(sqlite.getDb(), language.getId()) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -126,7 +127,7 @@ public class WordStore {
|
||||||
|
|
||||||
|
|
||||||
public void removeCustomWord(Language language, String word) {
|
public void removeCustomWord(Language language, String word) {
|
||||||
if (language == null || !checkOrNotify()) {
|
if (language == null || language instanceof NullLanguage || !checkOrNotify()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,7 +149,7 @@ public class WordStore {
|
||||||
return AddWordDialog.CODE_BLANK_WORD;
|
return AddWordDialog.CODE_BLANK_WORD;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (language == null) {
|
if (language == null || language instanceof NullLanguage) {
|
||||||
return AddWordDialog.CODE_INVALID_LANGUAGE;
|
return AddWordDialog.CODE_INVALID_LANGUAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,7 +192,7 @@ public class WordStore {
|
||||||
|
|
||||||
|
|
||||||
public void makeTopWord(@NonNull Language language, @NonNull String word, @NonNull String sequence) {
|
public void makeTopWord(@NonNull Language language, @NonNull String word, @NonNull String sequence) {
|
||||||
if (!checkOrNotify() || word.isEmpty() || sequence.isEmpty()) {
|
if (!checkOrNotify() || word.isEmpty() || sequence.isEmpty() || language instanceof NullLanguage) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -258,7 +259,7 @@ public class WordStore {
|
||||||
|
|
||||||
|
|
||||||
public void scheduleNormalization(Language language) {
|
public void scheduleNormalization(Language language) {
|
||||||
if (language != null && checkOrNotify()) {
|
if (language != null && !(language instanceof NullLanguage) && checkOrNotify()) {
|
||||||
UpdateOps.scheduleNormalization(sqlite.getDb(), language);
|
UpdateOps.scheduleNormalization(sqlite.getDb(), language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
||||||
public class WordStoreAsync {
|
public class WordStoreAsync {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.languages.InvalidLanguageCharactersException;
|
import io.github.sspanak.tt9.languages.exceptions.InvalidLanguageCharactersException;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
||||||
public class WordBatch {
|
public class WordBatch {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
|
||||||
public class WordFile {
|
public class WordFile {
|
||||||
private static final String LOG_TAG = WordFile.class.getSimpleName();
|
private static final String LOG_TAG = WordFile.class.getSimpleName();
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
|
|
||||||
public abstract class AbstractExporter {
|
public abstract class AbstractExporter {
|
||||||
final protected static String FILE_EXTENSION = ".csv";
|
final protected static String FILE_EXTENSION = ".csv";
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.Timer;
|
import io.github.sspanak.tt9.util.Timer;
|
||||||
import io.github.sspanak.tt9.db.sqlite.ReadOps;
|
import io.github.sspanak.tt9.db.sqlite.ReadOps;
|
||||||
import io.github.sspanak.tt9.db.sqlite.SQLiteOpener;
|
import io.github.sspanak.tt9.db.sqlite.SQLiteOpener;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.db.SlowQueryStats;
|
import io.github.sspanak.tt9.db.SlowQueryStats;
|
||||||
import io.github.sspanak.tt9.db.entities.WordList;
|
import io.github.sspanak.tt9.db.entities.WordList;
|
||||||
import io.github.sspanak.tt9.db.entities.WordPositionsStringBuilder;
|
import io.github.sspanak.tt9.db.entities.WordPositionsStringBuilder;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.BuildConfig;
|
import io.github.sspanak.tt9.BuildConfig;
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.languages.EmojiLanguage;
|
import io.github.sspanak.tt9.languages.EmojiLanguage;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import android.database.sqlite.SQLiteStatement;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.Text;
|
import io.github.sspanak.tt9.util.Text;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import android.view.View;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.view.inputmethod.InputConnection;
|
import android.view.inputmethod.InputConnection;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.Timer;
|
import io.github.sspanak.tt9.util.Timer;
|
||||||
import io.github.sspanak.tt9.ime.helpers.Key;
|
import io.github.sspanak.tt9.ime.helpers.Key;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
import io.github.sspanak.tt9.preferences.screens.debug.ItemInputHandlingMode;
|
import io.github.sspanak.tt9.preferences.screens.debug.ItemInputHandlingMode;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import androidx.annotation.NonNull;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.DictionaryLoader;
|
import io.github.sspanak.tt9.db.DictionaryLoader;
|
||||||
import io.github.sspanak.tt9.db.WordStoreAsync;
|
import io.github.sspanak.tt9.db.WordStoreAsync;
|
||||||
|
|
@ -30,7 +29,7 @@ import io.github.sspanak.tt9.ime.modes.ModePassthrough;
|
||||||
import io.github.sspanak.tt9.ime.modes.ModePredictive;
|
import io.github.sspanak.tt9.ime.modes.ModePredictive;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||||
import io.github.sspanak.tt9.languages.Text;
|
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
import io.github.sspanak.tt9.preferences.helpers.Hotkeys;
|
import io.github.sspanak.tt9.preferences.helpers.Hotkeys;
|
||||||
import io.github.sspanak.tt9.ui.PopupDialogActivity;
|
import io.github.sspanak.tt9.ui.PopupDialogActivity;
|
||||||
|
|
@ -38,6 +37,8 @@ import io.github.sspanak.tt9.ui.UI;
|
||||||
import io.github.sspanak.tt9.ui.main.MainView;
|
import io.github.sspanak.tt9.ui.main.MainView;
|
||||||
import io.github.sspanak.tt9.ui.tray.StatusBar;
|
import io.github.sspanak.tt9.ui.tray.StatusBar;
|
||||||
import io.github.sspanak.tt9.ui.tray.SuggestionsBar;
|
import io.github.sspanak.tt9.ui.tray.SuggestionsBar;
|
||||||
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
import io.github.sspanak.tt9.util.Text;
|
||||||
|
|
||||||
public class TraditionalT9 extends KeyPadHandler {
|
public class TraditionalT9 extends KeyPadHandler {
|
||||||
private InputConnection currentInputConnection = null;
|
private InputConnection currentInputConnection = null;
|
||||||
|
|
@ -469,7 +470,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelAutoAccept();
|
cancelAutoAccept();
|
||||||
backward = systemLanguage.isRTL() != backward;
|
backward = LanguageKind.isRTL(systemLanguage) != backward;
|
||||||
suggestionBar.scrollToSuggestion(backward ? -1 : 1);
|
suggestionBar.scrollToSuggestion(backward ? -1 : 1);
|
||||||
mInputMode.setWordStem(suggestionBar.getCurrentSuggestion(), true);
|
mInputMode.setWordStem(suggestionBar.getCurrentSuggestion(), true);
|
||||||
setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion());
|
setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion());
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import android.content.Context;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,11 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.Text;
|
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||||
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
import io.github.sspanak.tt9.util.Text;
|
||||||
|
|
||||||
public class TextField {
|
public class TextField {
|
||||||
public static final int IME_ACTION_ENTER = EditorInfo.IME_MASK_ACTION + 1;
|
public static final int IME_ACTION_ENTER = EditorInfo.IME_MASK_ACTION + 1;
|
||||||
|
|
@ -191,8 +192,8 @@ public class TextField {
|
||||||
boolean keepQuote = false;
|
boolean keepQuote = false;
|
||||||
if (language != null) {
|
if (language != null) {
|
||||||
// Hebrew and Ukrainian use the respective special characters as letters
|
// Hebrew and Ukrainian use the respective special characters as letters
|
||||||
keepApostrophe = language.isHebrew() || language.isUkrainian();
|
keepApostrophe = LanguageKind.isHebrew(language) || LanguageKind.isUkrainian(language);
|
||||||
keepQuote = language.isHebrew();
|
keepQuote = LanguageKind.isHebrew(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
return before.subStringEndingWord(keepApostrophe, keepQuote) + after.subStringStartingWord(keepApostrophe, keepQuote);
|
return before.subStringEndingWord(keepApostrophe, keepQuote) + after.subStringStartingWord(keepApostrophe, keepQuote);
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.ime.helpers.InputType;
|
||||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
import io.github.sspanak.tt9.languages.NaturalLanguage;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
abstract public class InputMode {
|
abstract public class InputMode {
|
||||||
|
|
@ -133,7 +134,7 @@ abstract public class InputMode {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!language.hasUpperCase() || digitSequence.startsWith(Language.PUNCTUATION_KEY) || digitSequence.startsWith(Language.SPECIAL_CHARS_KEY)) {
|
if (!language.hasUpperCase() || digitSequence.startsWith(NaturalLanguage.PUNCTUATION_KEY) || digitSequence.startsWith(NaturalLanguage.SPECIAL_CHARS_KEY)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.ime.helpers.InputType;
|
||||||
import io.github.sspanak.tt9.languages.Characters;
|
import io.github.sspanak.tt9.util.Characters;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
import io.github.sspanak.tt9.languages.NaturalLanguage;
|
||||||
|
|
||||||
public class Mode123 extends ModePassthrough {
|
public class Mode123 extends ModePassthrough {
|
||||||
@Override public int getId() { return MODE_123; }
|
@Override public int getId() { return MODE_123; }
|
||||||
|
|
@ -82,7 +83,7 @@ public class Mode123 extends ModePassthrough {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected boolean nextSpecialCharacters() {
|
@Override protected boolean nextSpecialCharacters() {
|
||||||
return digitSequence.equals(Language.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters();
|
return digitSequence.equals(NaturalLanguage.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean onNumber(int number, boolean hold, int repeat) {
|
@Override public boolean onNumber(int number, boolean hold, int repeat) {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ package io.github.sspanak.tt9.ime.modes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||||
|
import io.github.sspanak.tt9.languages.NaturalLanguage;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
public class ModeABC extends InputMode {
|
public class ModeABC extends InputMode {
|
||||||
|
|
@ -61,7 +63,7 @@ public class ModeABC extends InputMode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean nextSpecialCharacters() {
|
protected boolean nextSpecialCharacters() {
|
||||||
if (digitSequence.equals(Language.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters()) {
|
if (digitSequence.equals(NaturalLanguage.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters()) {
|
||||||
suggestions.add(language.getKeyNumber(digitSequence.charAt(0) - '0'));
|
suggestions.add(language.getKeyNumber(digitSequence.charAt(0) - '0'));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +104,7 @@ public class ModeABC extends InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
String langCode = "";
|
String langCode = "";
|
||||||
if (language.isLatinBased() || language.isCyrillic()) {
|
if (LanguageKind.isLatinBased(language) || LanguageKind.isCyrillic(language)) {
|
||||||
// There are many languages written using the same alphabet, so if the user has enabled multiple,
|
// There are many languages written using the same alphabet, so if the user has enabled multiple,
|
||||||
// make it clear which one is it, by appending the country code to "ABC" or "АБВ".
|
// make it clear which one is it, by appending the country code to "ABC" or "АБВ".
|
||||||
langCode = language.getLocale().getCountry();
|
langCode = language.getLocale().getCountry();
|
||||||
|
|
@ -110,7 +112,7 @@ public class ModeABC extends InputMode {
|
||||||
langCode = langCode.isEmpty() ? language.getName() : langCode;
|
langCode = langCode.isEmpty() ? language.getName() : langCode;
|
||||||
langCode = " / " + langCode;
|
langCode = " / " + langCode;
|
||||||
}
|
}
|
||||||
String modeString = language.getAbcString() + langCode.toUpperCase();
|
String modeString = language.getAbcString() + langCode.toUpperCase();
|
||||||
|
|
||||||
return (textCase == CASE_LOWER) ? modeString.toLowerCase(language.getLocale()) : modeString.toUpperCase(language.getLocale());
|
return (textCase == CASE_LOWER) ? modeString.toLowerCase(language.getLocale()) : modeString.toUpperCase(language.getLocale());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
|
||||||
import io.github.sspanak.tt9.db.WordStoreAsync;
|
import io.github.sspanak.tt9.db.WordStoreAsync;
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.ime.helpers.InputType;
|
||||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||||
|
|
@ -13,8 +12,11 @@ import io.github.sspanak.tt9.ime.modes.helpers.AutoTextCase;
|
||||||
import io.github.sspanak.tt9.ime.modes.helpers.Predictions;
|
import io.github.sspanak.tt9.ime.modes.helpers.Predictions;
|
||||||
import io.github.sspanak.tt9.languages.EmojiLanguage;
|
import io.github.sspanak.tt9.languages.EmojiLanguage;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.Text;
|
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||||
|
import io.github.sspanak.tt9.languages.NaturalLanguage;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
import io.github.sspanak.tt9.util.Text;
|
||||||
|
|
||||||
public class ModePredictive extends InputMode {
|
public class ModePredictive extends InputMode {
|
||||||
private final String LOG_TAG = getClass().getSimpleName();
|
private final String LOG_TAG = getClass().getSimpleName();
|
||||||
|
|
@ -91,7 +93,7 @@ public class ModePredictive extends InputMode {
|
||||||
digitSequence = EmojiLanguage.validateEmojiSequence(digitSequence, number);
|
digitSequence = EmojiLanguage.validateEmojiSequence(digitSequence, number);
|
||||||
disablePredictions = false;
|
disablePredictions = false;
|
||||||
|
|
||||||
if (digitSequence.equals(Language.PREFERRED_CHAR_SEQUENCE)) {
|
if (digitSequence.equals(NaturalLanguage.PREFERRED_CHAR_SEQUENCE)) {
|
||||||
autoAcceptTimeout = 0;
|
autoAcceptTimeout = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -248,7 +250,7 @@ public class ModePredictive extends InputMode {
|
||||||
* options for the current digitSequence.
|
* options for the current digitSequence.
|
||||||
*/
|
*/
|
||||||
private boolean loadStaticSuggestions(Runnable onLoad) {
|
private boolean loadStaticSuggestions(Runnable onLoad) {
|
||||||
if (digitSequence.equals(Language.PUNCTUATION_KEY) || digitSequence.equals(Language.SPECIAL_CHARS_KEY)) {
|
if (digitSequence.equals(NaturalLanguage.PUNCTUATION_KEY) || digitSequence.equals(NaturalLanguage.SPECIAL_CHARS_KEY)) {
|
||||||
super.loadSpecialCharacters(language);
|
super.loadSpecialCharacters(language);
|
||||||
onLoad.run();
|
onLoad.run();
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -257,7 +259,7 @@ public class ModePredictive extends InputMode {
|
||||||
suggestions.addAll(new EmojiLanguage().getKeyCharacters(digitSequence.charAt(0) - '0', digitSequence.length() - 2));
|
suggestions.addAll(new EmojiLanguage().getKeyCharacters(digitSequence.charAt(0) - '0', digitSequence.length() - 2));
|
||||||
onLoad.run();
|
onLoad.run();
|
||||||
return true;
|
return true;
|
||||||
} else if (digitSequence.startsWith(Language.PREFERRED_CHAR_SEQUENCE)) {
|
} else if (digitSequence.startsWith(NaturalLanguage.PREFERRED_CHAR_SEQUENCE)) {
|
||||||
suggestions.clear();
|
suggestions.clear();
|
||||||
suggestions.add(settings.getDoubleZeroChar());
|
suggestions.add(settings.getDoubleZeroChar());
|
||||||
onLoad.run();
|
onLoad.run();
|
||||||
|
|
@ -313,7 +315,7 @@ public class ModePredictive extends InputMode {
|
||||||
|
|
||||||
// emoji and punctuation are not in the database, so there is no point in
|
// emoji and punctuation are not in the database, so there is no point in
|
||||||
// running queries that would update nothing
|
// running queries that would update nothing
|
||||||
if (!sequence.startsWith(Language.PUNCTUATION_KEY) && !sequence.startsWith(Language.SPECIAL_CHARS_KEY)) {
|
if (!sequence.startsWith(NaturalLanguage.PUNCTUATION_KEY) && !sequence.startsWith(NaturalLanguage.SPECIAL_CHARS_KEY)) {
|
||||||
WordStoreAsync.makeTopWord(language, currentWord, sequence);
|
WordStoreAsync.makeTopWord(language, currentWord, sequence);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -340,7 +342,7 @@ public class ModePredictive extends InputMode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean nextSpecialCharacters() {
|
protected boolean nextSpecialCharacters() {
|
||||||
return digitSequence.equals(Language.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters();
|
return digitSequence.equals(NaturalLanguage.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -379,22 +381,22 @@ public class ModePredictive extends InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
// special characters always break words
|
// special characters always break words
|
||||||
if (autoAcceptTimeout == 0 && !digitSequence.startsWith(Language.SPECIAL_CHARS_KEY)) {
|
if (autoAcceptTimeout == 0 && !digitSequence.startsWith(NaturalLanguage.SPECIAL_CHARS_KEY)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow apostrophes in the middle or at the end of Hebrew and Ukrainian words
|
// allow apostrophes in the middle or at the end of Hebrew and Ukrainian words
|
||||||
if (language.isHebrew() || language.isUkrainian()) {
|
if (LanguageKind.isHebrew(language) || LanguageKind.isUkrainian(language)) {
|
||||||
return
|
return
|
||||||
predictions.noDbWords()
|
predictions.noDbWords()
|
||||||
&& digitSequence.equals(Language.PUNCTUATION_KEY);
|
&& digitSequence.equals(NaturalLanguage.PUNCTUATION_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// punctuation breaks words, unless there are database matches ('s, qu', по-, etc...)
|
// punctuation breaks words, unless there are database matches ('s, qu', по-, etc...)
|
||||||
return
|
return
|
||||||
!digitSequence.isEmpty()
|
!digitSequence.isEmpty()
|
||||||
&& predictions.noDbWords()
|
&& predictions.noDbWords()
|
||||||
&& digitSequence.contains(Language.PUNCTUATION_KEY)
|
&& digitSequence.contains(NaturalLanguage.PUNCTUATION_KEY)
|
||||||
&& !digitSequence.startsWith(EmojiLanguage.EMOJI_SEQUENCE)
|
&& !digitSequence.startsWith(EmojiLanguage.EMOJI_SEQUENCE)
|
||||||
&& Text.containsOtherThan1(digitSequence);
|
&& Text.containsOtherThan1(digitSequence);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package io.github.sspanak.tt9.ime.modes.helpers;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.ime.helpers.InputType;
|
||||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||||
import io.github.sspanak.tt9.languages.Text;
|
import io.github.sspanak.tt9.util.Text;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
public class AutoSpace {
|
public class AutoSpace {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package io.github.sspanak.tt9.ime.modes.helpers;
|
package io.github.sspanak.tt9.ime.modes.helpers;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.languages.Text;
|
import io.github.sspanak.tt9.util.Text;
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@ import androidx.annotation.NonNull;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.util.Characters;
|
||||||
|
import io.github.sspanak.tt9.util.TextTools;
|
||||||
|
|
||||||
public class EmojiLanguage extends Language {
|
public class EmojiLanguage extends Language {
|
||||||
final public static String EMOJI_SEQUENCE = "11";
|
final public static String EMOJI_SEQUENCE = "11";
|
||||||
final private static int CUSTOM_EMOJI_KEY = 3;
|
final private static int CUSTOM_EMOJI_KEY = 3;
|
||||||
|
|
@ -17,14 +20,21 @@ public class EmojiLanguage extends Language {
|
||||||
name = "Emoji";
|
name = "Emoji";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String getDigitSequenceForWord(String word) {
|
public String getDigitSequenceForWord(String word) {
|
||||||
return TextTools.isGraphic(word) ? CUSTOM_EMOJI_SEQUENCE : null;
|
return TextTools.isGraphic(word) ? CUSTOM_EMOJI_SEQUENCE : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ArrayList<String> getKeyCharacters(int key, int characterGroup) {
|
||||||
|
return key == 1 && characterGroup >= 0 ? Characters.getEmoji(characterGroup) : new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<String> getKeyCharacters(int key, int characterGroup) {
|
public boolean isValidWord(String word) {
|
||||||
return key == 1 && characterGroup >= 0 ? new ArrayList<>(Characters.getEmoji(characterGroup)) : super.getKeyCharacters(key, characterGroup);
|
return TextTools.isGraphic(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String validateEmojiSequence(@NonNull String sequence, int next) {
|
public static String validateEmojiSequence(@NonNull String sequence, int next) {
|
||||||
|
|
|
||||||
|
|
@ -3,303 +3,73 @@ package io.github.sspanak.tt9.languages;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.languages.exceptions.InvalidLanguageCharactersException;
|
||||||
|
|
||||||
public class Language implements Comparable<Language> {
|
abstract public class Language {
|
||||||
final public static String SPECIAL_CHARS_KEY = "0";
|
|
||||||
final public static String PUNCTUATION_KEY = "1";
|
|
||||||
final public static String PREFERRED_CHAR_SEQUENCE = "00";
|
|
||||||
|
|
||||||
protected int id;
|
protected int id;
|
||||||
protected String name;
|
|
||||||
protected Locale locale;
|
|
||||||
protected String dictionaryFile;
|
|
||||||
protected boolean hasUpperCase = true;
|
|
||||||
protected String abcString;
|
protected String abcString;
|
||||||
protected final ArrayList<ArrayList<String>> layout = new ArrayList<>();
|
protected String dictionaryFile;
|
||||||
private final HashMap<Character, String> characterKeyMap = new HashMap<>();
|
protected Locale locale = Locale.ROOT;
|
||||||
|
protected String name;
|
||||||
|
protected boolean hasUpperCase = true;
|
||||||
|
|
||||||
|
|
||||||
public static Language fromDefinition(LanguageDefinition definition) throws Exception {
|
public int getId() {
|
||||||
if (definition.dictionaryFile.isEmpty()) {
|
|
||||||
throw new Exception("Invalid definition. Dictionary file must be set.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (definition.locale.isEmpty()) {
|
|
||||||
throw new Exception("Invalid definition. Locale cannot be empty.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Locale definitionLocale;
|
|
||||||
if (definition.locale.equals("en")) {
|
|
||||||
definitionLocale = Locale.ENGLISH;
|
|
||||||
} else {
|
|
||||||
String[] parts = definition.locale.split("-", 2);
|
|
||||||
if (parts.length == 2) {
|
|
||||||
definitionLocale = new Locale(parts[0], parts[1]);
|
|
||||||
} else if (parts.length == 1) {
|
|
||||||
definitionLocale = new Locale(parts[0]);
|
|
||||||
} else {
|
|
||||||
throw new Exception("Unrecognized locale format: '" + definition.locale + "'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Language lang = new Language();
|
|
||||||
lang.abcString = definition.abcString.isEmpty() ? null : definition.abcString;
|
|
||||||
lang.dictionaryFile = definition.getDictionaryFile();
|
|
||||||
lang.hasUpperCase = definition.hasUpperCase;
|
|
||||||
lang.locale = definitionLocale;
|
|
||||||
lang.name = definition.name.isEmpty() ? lang.name : definition.name;
|
|
||||||
|
|
||||||
for (int key = 0; key <= 9 && key < definition.layout.size(); key++) {
|
|
||||||
lang.layout.add(keyCharsFromDefinition(key, definition.layout.get(key)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return lang;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static ArrayList<String> keyCharsFromDefinition(int key, ArrayList<String> definitionChars) {
|
|
||||||
if (key > 1) {
|
|
||||||
return definitionChars;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String specialCharsPlaceholder = "SPECIAL";
|
|
||||||
final String punctuationPlaceholder = "PUNCTUATION";
|
|
||||||
final String arabicStylePlaceholder = punctuationPlaceholder + "_AR";
|
|
||||||
final String germanStylePlaceholder = punctuationPlaceholder + "_DE";
|
|
||||||
final String frenchStylePlaceholder = punctuationPlaceholder + "_FR";
|
|
||||||
|
|
||||||
ArrayList<String> keyChars = new ArrayList<>();
|
|
||||||
for (String defChar : definitionChars) {
|
|
||||||
switch (defChar) {
|
|
||||||
case specialCharsPlaceholder:
|
|
||||||
keyChars.addAll(Characters.Special);
|
|
||||||
break;
|
|
||||||
case punctuationPlaceholder:
|
|
||||||
keyChars.addAll(Characters.PunctuationEnglish);
|
|
||||||
break;
|
|
||||||
case arabicStylePlaceholder:
|
|
||||||
keyChars.addAll(Characters.PunctuationArabic);
|
|
||||||
break;
|
|
||||||
case germanStylePlaceholder:
|
|
||||||
keyChars.addAll(Characters.PunctuationGerman);
|
|
||||||
break;
|
|
||||||
case frenchStylePlaceholder:
|
|
||||||
keyChars.addAll(Characters.PunctuationFrench);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
keyChars.add(defChar);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return keyChars;
|
|
||||||
}
|
|
||||||
|
|
||||||
final public int getId() {
|
|
||||||
if (id == 0) {
|
|
||||||
id = generateId();
|
|
||||||
}
|
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
final public Locale getLocale() {
|
@NonNull public String getAbcString() {
|
||||||
return locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
final public String getName() {
|
|
||||||
if (name == null) {
|
|
||||||
name = new Text(this, locale.getDisplayLanguage(locale)).capitalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
final public String getDictionaryFile() {
|
|
||||||
return dictionaryFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
final public String getAbcString() {
|
|
||||||
if (abcString == null) {
|
|
||||||
ArrayList<String> lettersList = getKeyCharacters(2);
|
|
||||||
|
|
||||||
abcString = "";
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (int i = 0; i < lettersList.size() && i < 3; i++) {
|
|
||||||
sb.append(lettersList.get(i));
|
|
||||||
}
|
|
||||||
abcString = sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return abcString;
|
return abcString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull final public String getDictionaryFile() {
|
||||||
|
return dictionaryFile;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasUpperCase() {
|
@NonNull final public Locale getLocale() {
|
||||||
return hasUpperCase;
|
return locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* isLatinBased
|
* Returns the characters that the key would type in ABC or Predictive mode. For example,
|
||||||
* Returns "true" when the language is based on the Latin alphabet or "false" otherwise.
|
* the key 2 in English would return A-B-C.
|
||||||
|
* Keys that have special characters assigned, may have more than one group assigned. The specific
|
||||||
|
* group is selected by the characterGroup parameter. By default, group 0 is returned.
|
||||||
*/
|
*/
|
||||||
public boolean isLatinBased() {
|
@NonNull abstract public ArrayList<String> getKeyCharacters(int key, int characterGroup);
|
||||||
return getKeyCharacters(2).contains("a");
|
@NonNull public ArrayList<String> getKeyCharacters(int key) {
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCyrillic() {
|
|
||||||
return getKeyCharacters(2).contains("а");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRTL() {
|
|
||||||
return isArabic() || isHebrew();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGreek() {
|
|
||||||
return getKeyCharacters(2).contains("α");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isArabic() {
|
|
||||||
return getKeyCharacters(3).contains("ا");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUkrainian() {
|
|
||||||
return getKeyCharacters(3).contains("є");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isHebrew() {
|
|
||||||
return getKeyCharacters(3).contains("א");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ************ utility ************ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* generateId
|
|
||||||
* Uses the letters of the Locale to generate an ID for the language.
|
|
||||||
* Each letter is converted to uppercase and used as a 5-bit integer. Then the 5-bits
|
|
||||||
* are packed to form a 10-bit or a 20-bit integer, depending on the Locale length.
|
|
||||||
*
|
|
||||||
* Example (2-letter Locale)
|
|
||||||
* "en"
|
|
||||||
* -> "E" | "N"
|
|
||||||
* -> 5 | 448 (shift the 2nd number by 5 bits, so its bits would not overlap with the 1st one)
|
|
||||||
* -> 543
|
|
||||||
*
|
|
||||||
* Example (4-letter Locale)
|
|
||||||
* "bg-BG"
|
|
||||||
* -> "B" | "G" | "B" | "G"
|
|
||||||
* -> 2 | 224 | 2048 | 229376 (shift each 5-bit number, not overlap with the previous ones)
|
|
||||||
* -> 231650
|
|
||||||
*
|
|
||||||
* Minimum ID: "aa" -> 33
|
|
||||||
* Maximum ID: "zz-ZZ" -> 879450
|
|
||||||
*/
|
|
||||||
private int generateId() {
|
|
||||||
String idString = (locale.getLanguage() + locale.getCountry()).toUpperCase();
|
|
||||||
int idInt = 0;
|
|
||||||
for (int i = 0; i < idString.length(); i++) {
|
|
||||||
idInt |= ((idString.codePointAt(i) & 31) << (i * 5));
|
|
||||||
}
|
|
||||||
|
|
||||||
return idInt;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateCharacterKeyMap() {
|
|
||||||
characterKeyMap.clear();
|
|
||||||
for (int digit = 0; digit <= 9; digit++) {
|
|
||||||
for (String keyChar : getKeyCharacters(digit)) {
|
|
||||||
characterKeyMap.put(keyChar.charAt(0), String.valueOf(digit));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<String> getKeyCharacters(int key, int characterGroup) {
|
|
||||||
if (key < 0 || key >= layout.size()) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<String> chars = layout.get(key);
|
|
||||||
if (key == 0) {
|
|
||||||
if (characterGroup > 1) {
|
|
||||||
chars = new ArrayList<>();
|
|
||||||
} else if (characterGroup == 1) {
|
|
||||||
chars = new ArrayList<>(Characters.Currency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<String> getKeyCharacters(int key) {
|
|
||||||
return getKeyCharacters(key, 0);
|
return getKeyCharacters(key, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getKeyNumber(int key) {
|
@NonNull public String getKeyNumber(int key) {
|
||||||
if (key > 10 || key < 0) {
|
return String.valueOf(key);
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return isArabic() ? Characters.ArabicNumbers.get(key) : String.valueOf(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDigitSequenceForWord(String word) throws InvalidLanguageCharactersException {
|
@NonNull public String getName() {
|
||||||
StringBuilder sequence = new StringBuilder();
|
return name;
|
||||||
String lowerCaseWord = word.toLowerCase(locale);
|
}
|
||||||
|
|
||||||
if (characterKeyMap.isEmpty()) {
|
final public boolean hasUpperCase() {
|
||||||
generateCharacterKeyMap();
|
return hasUpperCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < lowerCaseWord.length(); i++) {
|
@NonNull
|
||||||
char letter = lowerCaseWord.charAt(i);
|
@Override
|
||||||
if (!characterKeyMap.containsKey(letter)) {
|
final public String toString() {
|
||||||
throw new InvalidLanguageCharactersException(this, "Failed generating digit sequence for word: '" + word);
|
return getName();
|
||||||
}
|
|
||||||
|
|
||||||
sequence.append(characterKeyMap.get(letter));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sequence.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the given word contains characters outside of the language alphabet.
|
* Checks whether the given word contains characters outside of the language alphabet.
|
||||||
*/
|
*/
|
||||||
public boolean isValidWord(String word) {
|
abstract public boolean isValidWord(String word);
|
||||||
if (word == null || word.isEmpty() || (word.length() == 1 && Character.isDigit(word.charAt(0)))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String lowerCaseWord = word.toLowerCase(locale);
|
/**
|
||||||
if (characterKeyMap.isEmpty()) {
|
* Converts a word to a sequence of digits based on the language's keyboard layout.
|
||||||
generateCharacterKeyMap();
|
* For example: "food" -> "3663"
|
||||||
}
|
*/
|
||||||
|
@NonNull abstract public String getDigitSequenceForWord(String word) throws InvalidLanguageCharactersException;
|
||||||
for (int i = 0; i < lowerCaseWord.length(); i++) {
|
|
||||||
if (!characterKeyMap.containsKey(lowerCaseWord.charAt(i))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(Language other) {
|
|
||||||
String key = getName().equals("Suomi") ? "su" : getLocale().toString();
|
|
||||||
String otherKey = other.getName().equals("Suomi") ? "su" : other.getLocale().toString();
|
|
||||||
return key.compareTo(otherKey);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,18 +9,18 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.ime.helpers.SystemSettings;
|
import io.github.sspanak.tt9.ime.helpers.SystemSettings;
|
||||||
|
|
||||||
public class LanguageCollection {
|
public class LanguageCollection {
|
||||||
private static LanguageCollection self;
|
private static LanguageCollection self;
|
||||||
|
|
||||||
private final HashMap<Integer, Language> languages = new HashMap<>();
|
private final HashMap<Integer, NaturalLanguage> languages = new HashMap<>();
|
||||||
|
|
||||||
private LanguageCollection(Context context) {
|
private LanguageCollection(Context context) {
|
||||||
for (String file : LanguageDefinition.getAllFiles(context.getAssets())) {
|
for (String file : LanguageDefinition.getAllFiles(context.getAssets())) {
|
||||||
try {
|
try {
|
||||||
Language lang = Language.fromDefinition(LanguageDefinition.fromFile(context.getAssets(), file));
|
NaturalLanguage lang = NaturalLanguage.fromDefinition(LanguageDefinition.fromFile(context.getAssets(), file));
|
||||||
languages.put(lang.getId(), lang);
|
languages.put(lang.getId(), lang);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.e("tt9.LanguageCollection", "Skipping invalid language: '" + file + "'. " + e.getMessage());
|
Logger.e("tt9.LanguageCollection", "Skipping invalid language: '" + file + "'. " + e.getMessage());
|
||||||
|
|
@ -38,7 +38,7 @@ public class LanguageCollection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Language getLanguage(Context context, int langId) {
|
public static NaturalLanguage getLanguage(Context context, int langId) {
|
||||||
if (getInstance(context).languages.containsKey(langId)) {
|
if (getInstance(context).languages.containsKey(langId)) {
|
||||||
return getInstance(context).languages.get(langId);
|
return getInstance(context).languages.get(langId);
|
||||||
}
|
}
|
||||||
|
|
@ -53,8 +53,8 @@ public class LanguageCollection {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Language getByLocale(Context context, String locale) {
|
public static NaturalLanguage getByLocale(Context context, String locale) {
|
||||||
for (Language lang : getInstance(context).languages.values()) {
|
for (NaturalLanguage lang : getInstance(context).languages.values()) {
|
||||||
if (lang.getLocale().toString().equals(locale)) {
|
if (lang.getLocale().toString().equals(locale)) {
|
||||||
return lang;
|
return lang;
|
||||||
}
|
}
|
||||||
|
|
@ -64,14 +64,13 @@ public class LanguageCollection {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<Language> getAll(Context context, ArrayList<Integer> languageIds, boolean sort) {
|
public static ArrayList<Language> getAll(Context context, ArrayList<Integer> languageIds, boolean sort) {
|
||||||
ArrayList<Language> langList = new ArrayList<>();
|
|
||||||
|
|
||||||
if (languageIds == null) {
|
if (languageIds == null) {
|
||||||
return langList;
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayList<NaturalLanguage> langList = new ArrayList<>();
|
||||||
for (int languageId : languageIds) {
|
for (int languageId : languageIds) {
|
||||||
Language lang = getLanguage(context, languageId);
|
NaturalLanguage lang = getLanguage(context, languageId);
|
||||||
if (lang != null) {
|
if (lang != null) {
|
||||||
langList.add(lang);
|
langList.add(lang);
|
||||||
}
|
}
|
||||||
|
|
@ -81,8 +80,7 @@ public class LanguageCollection {
|
||||||
Collections.sort(langList);
|
Collections.sort(langList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>(langList);
|
||||||
return langList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<Language> getAll(Context context, ArrayList<Integer> languageIds) {
|
public static ArrayList<Language> getAll(Context context, ArrayList<Integer> languageIds) {
|
||||||
|
|
@ -90,13 +88,13 @@ public class LanguageCollection {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<Language> getAll(Context context, boolean sort) {
|
public static ArrayList<Language> getAll(Context context, boolean sort) {
|
||||||
ArrayList<Language> langList = new ArrayList<>(getInstance(context).languages.values());
|
ArrayList<NaturalLanguage> langList = new ArrayList<>(getInstance(context).languages.values());
|
||||||
|
|
||||||
if (sort) {
|
if (sort) {
|
||||||
Collections.sort(langList);
|
Collections.sort(langList);
|
||||||
}
|
}
|
||||||
|
|
||||||
return langList;
|
return new ArrayList<>(langList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<Language> getAll(Context context) {
|
public static ArrayList<Language> getAll(Context context) {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
|
||||||
public class LanguageDefinition {
|
public class LanguageDefinition {
|
||||||
private static final String languagesDir = "languages";
|
private static final String languagesDir = "languages";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package io.github.sspanak.tt9.languages;
|
||||||
|
|
||||||
|
public class LanguageKind {
|
||||||
|
public static boolean isArabic(Language language) { return language != null && language.getKeyCharacters(3).contains("ا"); }
|
||||||
|
public static boolean isCyrillic(Language language) { return language != null && language.getKeyCharacters(2).contains("а"); }
|
||||||
|
public static boolean isHebrew(Language language) { return language != null && language.getKeyCharacters(3).contains("א"); }
|
||||||
|
public static boolean isGreek(Language language) { return language != null && language.getKeyCharacters(2).contains("α"); }
|
||||||
|
public static boolean isLatinBased(Language language) { return language != null && language.getKeyCharacters(2).contains("a"); }
|
||||||
|
public static boolean isRTL(Language language) { return isArabic(language) || isHebrew(language); }
|
||||||
|
public static boolean isUkrainian(Language language) { return language != null && language.getKeyCharacters(3).contains("є"); }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,247 @@
|
||||||
|
package io.github.sspanak.tt9.languages;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.languages.exceptions.InvalidLanguageCharactersException;
|
||||||
|
import io.github.sspanak.tt9.util.Characters;
|
||||||
|
import io.github.sspanak.tt9.util.Text;
|
||||||
|
|
||||||
|
|
||||||
|
public class NaturalLanguage extends Language implements Comparable<NaturalLanguage> {
|
||||||
|
final public static String SPECIAL_CHARS_KEY = "0";
|
||||||
|
final public static String PUNCTUATION_KEY = "1";
|
||||||
|
final public static String PREFERRED_CHAR_SEQUENCE = "00";
|
||||||
|
|
||||||
|
|
||||||
|
protected final ArrayList<ArrayList<String>> layout = new ArrayList<>();
|
||||||
|
private final HashMap<Character, String> characterKeyMap = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
public static NaturalLanguage fromDefinition(LanguageDefinition definition) throws Exception {
|
||||||
|
if (definition.dictionaryFile.isEmpty()) {
|
||||||
|
throw new Exception("Invalid definition. Dictionary file must be set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
NaturalLanguage lang = new NaturalLanguage();
|
||||||
|
lang.abcString = definition.abcString.isEmpty() ? null : definition.abcString;
|
||||||
|
lang.dictionaryFile = definition.getDictionaryFile();
|
||||||
|
lang.hasUpperCase = definition.hasUpperCase;
|
||||||
|
lang.name = definition.name.isEmpty() ? lang.name : definition.name;
|
||||||
|
lang.setLocale(definition);
|
||||||
|
lang.setLayout(definition);
|
||||||
|
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setLocale(LanguageDefinition definition) throws Exception {
|
||||||
|
if (definition.locale.isEmpty()) {
|
||||||
|
throw new Exception("Invalid definition. Locale cannot be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (definition.locale.equals("en")) {
|
||||||
|
locale = Locale.ENGLISH;
|
||||||
|
} else {
|
||||||
|
String[] parts = definition.locale.split("-", 2);
|
||||||
|
if (parts.length == 2) {
|
||||||
|
locale = new Locale(parts[0], parts[1]);
|
||||||
|
} else if (parts.length == 1) {
|
||||||
|
locale = new Locale(parts[0]);
|
||||||
|
} else {
|
||||||
|
throw new Exception("Unrecognized locale format: '" + definition.locale + "'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setLayout(LanguageDefinition definition) {
|
||||||
|
for (int key = 0; key <= 9 && key < definition.layout.size(); key++) {
|
||||||
|
layout.add(
|
||||||
|
key,
|
||||||
|
key > 1 ? definition.layout.get(key) : generateSpecialChars(definition.layout.get(key))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
generateCharacterKeyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ArrayList<String> generateSpecialChars(ArrayList<String> definitionChars) {
|
||||||
|
final String SPECIAL_CHARS_PLACEHOLDER = "SPECIAL";
|
||||||
|
final String PUNCTUATION_PLACEHOLDER = "PUNCTUATION";
|
||||||
|
final String ARABIC_PUNCTUATION_STYLE = PUNCTUATION_PLACEHOLDER + "_AR";
|
||||||
|
final String GERMAN_PUNCTUATION_STYLE = PUNCTUATION_PLACEHOLDER + "_DE";
|
||||||
|
final String FRENCH_PUNCTUATION_STYLE = PUNCTUATION_PLACEHOLDER + "_FR";
|
||||||
|
|
||||||
|
ArrayList<String> keyChars = new ArrayList<>();
|
||||||
|
for (String defChar : definitionChars) {
|
||||||
|
switch (defChar) {
|
||||||
|
case SPECIAL_CHARS_PLACEHOLDER:
|
||||||
|
keyChars.addAll(Characters.Special);
|
||||||
|
break;
|
||||||
|
case PUNCTUATION_PLACEHOLDER:
|
||||||
|
keyChars.addAll(Characters.PunctuationEnglish);
|
||||||
|
break;
|
||||||
|
case ARABIC_PUNCTUATION_STYLE:
|
||||||
|
keyChars.addAll(Characters.PunctuationArabic);
|
||||||
|
break;
|
||||||
|
case GERMAN_PUNCTUATION_STYLE:
|
||||||
|
keyChars.addAll(Characters.PunctuationGerman);
|
||||||
|
break;
|
||||||
|
case FRENCH_PUNCTUATION_STYLE:
|
||||||
|
keyChars.addAll(Characters.PunctuationFrench);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
keyChars.add(defChar);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyChars;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generateId
|
||||||
|
* Uses the letters of the Locale to generate an ID for the language.
|
||||||
|
* Each letter is converted to uppercase and used as a 5-bit integer. Then the 5-bits
|
||||||
|
* are packed to form a 10-bit or a 20-bit integer, depending on the Locale length.
|
||||||
|
*
|
||||||
|
* Example (2-letter Locale)
|
||||||
|
* "en"
|
||||||
|
* -> "E" | "N"
|
||||||
|
* -> 5 | 448 (shift the 2nd number by 5 bits, so its bits would not overlap with the 1st one)
|
||||||
|
* -> 543
|
||||||
|
*
|
||||||
|
* Example (4-letter Locale)
|
||||||
|
* "bg-BG"
|
||||||
|
* -> "B" | "G" | "B" | "G"
|
||||||
|
* -> 2 | 224 | 2048 | 229376 (shift each 5-bit number, not overlap with the previous ones)
|
||||||
|
* -> 231650
|
||||||
|
*
|
||||||
|
* Minimum ID: "aa" -> 33
|
||||||
|
* Maximum ID: "zz-ZZ" -> 879450
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
if (id == 0) {
|
||||||
|
String idString = (locale.getLanguage() + locale.getCountry()).toUpperCase();
|
||||||
|
for (int i = 0; i < idString.length(); i++) {
|
||||||
|
id |= (idString.codePointAt(i) & 31) << (i * 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getAbcString() {
|
||||||
|
if (abcString == null) {
|
||||||
|
ArrayList<String> lettersList = getKeyCharacters(2);
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < lettersList.size() && i < 3; i++) {
|
||||||
|
sb.append(lettersList.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
abcString = sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return abcString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
if (name == null) {
|
||||||
|
name = new Text(this, locale.getDisplayLanguage(locale)).capitalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void generateCharacterKeyMap() {
|
||||||
|
characterKeyMap.clear();
|
||||||
|
for (int digit = 0; digit <= 9; digit++) {
|
||||||
|
for (String keyChar : getKeyCharacters(digit)) {
|
||||||
|
characterKeyMap.put(keyChar.charAt(0), String.valueOf(digit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public ArrayList<String> getKeyCharacters(int key, int characterGroup) {
|
||||||
|
if (key < 0 || key >= layout.size()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<String> chars = layout.get(key);
|
||||||
|
if (key == 0) {
|
||||||
|
if (characterGroup > 1) {
|
||||||
|
chars = new ArrayList<>();
|
||||||
|
} else if (characterGroup == 1) {
|
||||||
|
chars = new ArrayList<>(Characters.Currency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String getKeyNumber(int key) {
|
||||||
|
return key >= 0 && key < 10 && LanguageKind.isArabic(this) ? Characters.ArabicNumbers.get(key) : super.getKeyNumber(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String getDigitSequenceForWord(String word) throws InvalidLanguageCharactersException {
|
||||||
|
StringBuilder sequence = new StringBuilder();
|
||||||
|
String lowerCaseWord = word.toLowerCase(locale);
|
||||||
|
|
||||||
|
for (int i = 0; i < lowerCaseWord.length(); i++) {
|
||||||
|
char letter = lowerCaseWord.charAt(i);
|
||||||
|
if (!characterKeyMap.containsKey(letter)) {
|
||||||
|
throw new InvalidLanguageCharactersException(this, "Failed generating digit sequence for word: '" + word);
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence.append(characterKeyMap.get(letter));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sequence.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isValidWord(String word) {
|
||||||
|
if (word == null || word.isEmpty() || (word.length() == 1 && Character.isDigit(word.charAt(0)))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String lowerCaseWord = word.toLowerCase(locale);
|
||||||
|
|
||||||
|
for (int i = 0; i < lowerCaseWord.length(); i++) {
|
||||||
|
if (!characterKeyMap.containsKey(lowerCaseWord.charAt(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(NaturalLanguage other) {
|
||||||
|
String key = getName().equals("Suomi") ? "su" : getLocale().toString();
|
||||||
|
String otherKey = other.getName().equals("Suomi") ? "su" : other.getLocale().toString();
|
||||||
|
return key.compareTo(otherKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,9 @@ package io.github.sspanak.tt9.languages;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
|
|
@ -10,6 +13,24 @@ public class NullLanguage extends Language {
|
||||||
public NullLanguage(Context context) {
|
public NullLanguage(Context context) {
|
||||||
locale = Locale.ROOT;
|
locale = Locale.ROOT;
|
||||||
name = context.getString(R.string.no_language);
|
name = context.getString(R.string.no_language);
|
||||||
abcString = "abc";
|
abcString = "ABC";
|
||||||
|
hasUpperCase = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ArrayList<String> getKeyCharacters(int key, int characterGroup) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidWord(String word) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getDigitSequenceForWord(String word) {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
package io.github.sspanak.tt9.languages;
|
package io.github.sspanak.tt9.languages.exceptions;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
||||||
public class InvalidLanguageCharactersException extends Exception {
|
public class InvalidLanguageCharactersException extends Exception {
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package io.github.sspanak.tt9.languages;
|
package io.github.sspanak.tt9.languages.exceptions;
|
||||||
|
|
||||||
public class InvalidLanguageException extends Exception {
|
public class InvalidLanguageException extends Exception {
|
||||||
public InvalidLanguageException() { super("Invalid Language"); }
|
public InvalidLanguageException() { super("Invalid Language"); }
|
||||||
|
|
@ -13,7 +13,7 @@ import androidx.fragment.app.FragmentTransaction;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.LegacyDb;
|
import io.github.sspanak.tt9.db.LegacyDb;
|
||||||
import io.github.sspanak.tt9.db.WordStoreAsync;
|
import io.github.sspanak.tt9.db.WordStoreAsync;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||||
import io.github.sspanak.tt9.preferences.screens.debug.ItemInputHandlingMode;
|
import io.github.sspanak.tt9.preferences.screens.debug.ItemInputHandlingMode;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import androidx.preference.Preference;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
abstract public class ItemClickable {
|
abstract public class ItemClickable {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import androidx.preference.Preference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
|
||||||
public class ItemDropDown {
|
public class ItemDropDown {
|
||||||
private final DropDownPreference item;
|
private final DropDownPreference item;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import android.view.MenuItem;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
|
|
||||||
abstract public class BaseScreenFragment extends PreferenceFragmentCompat {
|
abstract public class BaseScreenFragment extends PreferenceFragmentCompat {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import java.util.Arrays;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.BuildConfig;
|
import io.github.sspanak.tt9.BuildConfig;
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.ime.helpers.SystemSettings;
|
import io.github.sspanak.tt9.ime.helpers.SystemSettings;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
import io.github.sspanak.tt9.preferences.screens.BaseScreenFragment;
|
import io.github.sspanak.tt9.preferences.screens.BaseScreenFragment;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import androidx.preference.Preference;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.preferences.items.ItemDropDown;
|
import io.github.sspanak.tt9.preferences.items.ItemDropDown;
|
||||||
|
|
||||||
class ItemLogLevel extends ItemDropDown {
|
class ItemLogLevel extends ItemDropDown {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ import androidx.preference.PreferenceViewHolder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.WordStoreAsync;
|
import io.github.sspanak.tt9.db.WordStoreAsync;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import android.text.TextWatcher;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
class TextChangeListener implements TextWatcher {
|
class TextChangeListener implements TextWatcher {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package io.github.sspanak.tt9.preferences.screens.hotkeys;
|
package io.github.sspanak.tt9.preferences.screens.hotkeys;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
import io.github.sspanak.tt9.preferences.helpers.Hotkeys;
|
import io.github.sspanak.tt9.preferences.helpers.Hotkeys;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import androidx.preference.DropDownPreference;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
|
|
||||||
class ItemSelectZeroKeyCharacter {
|
class ItemSelectZeroKeyCharacter {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package io.github.sspanak.tt9.preferences.screens.languages;
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.db.exporter.DictionaryExporter;
|
import io.github.sspanak.tt9.db.exporter.DictionaryExporter;
|
||||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ import java.util.Locale;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.exceptions.DictionaryImportException;
|
import io.github.sspanak.tt9.db.exceptions.DictionaryImportException;
|
||||||
import io.github.sspanak.tt9.languages.InvalidLanguageCharactersException;
|
import io.github.sspanak.tt9.languages.exceptions.InvalidLanguageCharactersException;
|
||||||
import io.github.sspanak.tt9.languages.InvalidLanguageException;
|
import io.github.sspanak.tt9.languages.exceptions.InvalidLanguageException;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||||
import io.github.sspanak.tt9.ui.dialogs.AddWordDialog;
|
import io.github.sspanak.tt9.ui.dialogs.AddWordDialog;
|
||||||
import io.github.sspanak.tt9.ui.dialogs.ConfirmDictionaryUpdateDialog;
|
import io.github.sspanak.tt9.ui.dialogs.ConfirmDictionaryUpdateDialog;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import android.content.Intent;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.WordStoreAsync;
|
import io.github.sspanak.tt9.db.WordStoreAsync;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import android.content.Intent;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.DictionaryLoader;
|
import io.github.sspanak.tt9.db.DictionaryLoader;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import android.content.Intent;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
import io.github.sspanak.tt9.ui.UI;
|
import io.github.sspanak.tt9.ui.UI;
|
||||||
|
|
||||||
abstract public class PopupDialog {
|
abstract public class PopupDialog {
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ package io.github.sspanak.tt9.ui.main.keys;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.languages.Characters;
|
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.util.Characters;
|
||||||
|
|
||||||
public class SoftBackspaceKey extends SoftKey {
|
public class SoftBackspaceKey extends SoftKey {
|
||||||
|
|
||||||
|
|
@ -41,7 +41,6 @@ public class SoftBackspaceKey extends SoftKey {
|
||||||
return "Del";
|
return "Del";
|
||||||
}
|
}
|
||||||
|
|
||||||
Language language = getCurrentLanguage();
|
return LanguageKind.isRTL(getCurrentLanguage()) ? "⌦" : "⌫";
|
||||||
return language != null && language.isRTL() ? "⌦" : "⌫";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import android.view.View;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,13 @@ import android.view.KeyEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.ime.helpers.Key;
|
import io.github.sspanak.tt9.ime.helpers.Key;
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
|
||||||
public class SoftNumberKey extends SoftKey {
|
public class SoftNumberKey extends SoftKey {
|
||||||
public SoftNumberKey(Context context) {
|
public SoftNumberKey(Context context) {
|
||||||
|
|
@ -58,7 +59,7 @@ public class SoftNumberKey extends SoftKey {
|
||||||
int number = getNumber(getId());
|
int number = getNumber(getId());
|
||||||
|
|
||||||
Language language = getCurrentLanguage();
|
Language language = getCurrentLanguage();
|
||||||
if (language != null && language.isArabic() && tt9 != null && !tt9.isInputModeNumeric()) {
|
if (LanguageKind.isArabic(language) && tt9 != null && !tt9.isInputModeNumeric()) {
|
||||||
complexLabelTitleSize = SettingsStore.SOFT_KEY_COMPLEX_LABEL_ARABIC_TITLE_SIZE;
|
complexLabelTitleSize = SettingsStore.SOFT_KEY_COMPLEX_LABEL_ARABIC_TITLE_SIZE;
|
||||||
return language.getKeyNumber(number);
|
return language.getKeyNumber(number);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -106,8 +107,8 @@ public class SoftNumberKey extends SoftKey {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isLatinBased = language.isLatinBased();
|
boolean isLatinBased = LanguageKind.isLatinBased(language);
|
||||||
boolean isGreekBased = language.isGreek();
|
boolean isGreekBased = LanguageKind.isGreek(language);
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
ArrayList<String> chars = language.getKeyCharacters(number);
|
ArrayList<String> chars = language.getKeyCharacters(number);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||||
|
|
||||||
public class SoftPunctuationKey extends SoftKey {
|
public class SoftPunctuationKey extends SoftKey {
|
||||||
public SoftPunctuationKey(Context context) {
|
public SoftPunctuationKey(Context context) {
|
||||||
|
|
@ -52,8 +52,7 @@ public class SoftPunctuationKey extends SoftKey {
|
||||||
} else {
|
} else {
|
||||||
if (keyId == R.id.soft_key_punctuation_1) return "!";
|
if (keyId == R.id.soft_key_punctuation_1) return "!";
|
||||||
if (keyId == R.id.soft_key_punctuation_2) {
|
if (keyId == R.id.soft_key_punctuation_2) {
|
||||||
Language language = getCurrentLanguage();
|
return LanguageKind.isArabic(getCurrentLanguage()) ? "؟" : "?";
|
||||||
return language != null && language.isArabic() ? "؟" : "?";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
|
|
||||||
public class StatusBar {
|
public class StatusBar {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package io.github.sspanak.tt9.languages;
|
package io.github.sspanak.tt9.util;
|
||||||
|
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package io.github.sspanak.tt9;
|
package io.github.sspanak.tt9.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConsumerCompat
|
* ConsumerCompat
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package io.github.sspanak.tt9;
|
package io.github.sspanak.tt9.util;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.BuildConfig;
|
||||||
|
|
||||||
public class Logger {
|
public class Logger {
|
||||||
public static final String TAG_PREFIX = "tt9/";
|
public static final String TAG_PREFIX = "tt9/";
|
||||||
public static int LEVEL = BuildConfig.DEBUG ? Log.DEBUG : Log.ERROR;
|
public static int LEVEL = BuildConfig.DEBUG ? Log.DEBUG : Log.ERROR;
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
package io.github.sspanak.tt9.languages;
|
package io.github.sspanak.tt9.util;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
||||||
public class Text extends TextTools {
|
public class Text extends TextTools {
|
||||||
private final Language language;
|
private final Language language;
|
||||||
private final String text;
|
private final String text;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package io.github.sspanak.tt9.languages;
|
package io.github.sspanak.tt9.util;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package io.github.sspanak.tt9;
|
package io.github.sspanak.tt9.util;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue