From b446e41120eebedf796855d1fc7b372a4733b44b Mon Sep 17 00:00:00 2001 From: sspanak Date: Sat, 12 Apr 2025 16:09:59 +0300 Subject: [PATCH] added Bopomofo support (without an actual dictionary) --- .../definitions/ChineseBopomofo.hidden | 60 +++++++++ app/languages/dictionaries/zh-bopomofo.hidden | 37 ++++++ .../sspanak/tt9/ime/MainViewHandler.java | 6 + .../sspanak/tt9/ime/modes/InputMode.java | 3 +- .../github/sspanak/tt9/ime/modes/ModeABC.java | 2 +- .../sspanak/tt9/ime/modes/ModeBopomofo.java | 118 ++++++++++++++++++ .../sspanak/tt9/ime/modes/ModePinyin.java | 2 +- .../sspanak/tt9/ime/modes/ModeWords.java | 2 +- .../sspanak/tt9/languages/LanguageKind.java | 4 +- .../sspanak/tt9/ui/main/MainLayoutNumpad.java | 3 +- .../sspanak/tt9/ui/main/keys/SoftKey.java | 15 +++ .../tt9/ui/main/keys/SoftKeyFilter.java | 21 ++-- .../sspanak/tt9/ui/main/keys/SoftKeyLF4.java | 2 +- .../tt9/ui/main/keys/SoftKeyNumber.java | 2 + .../tt9/ui/main/keys/SoftKeyNumber0.java | 49 ++++---- .../tt9/ui/main/keys/SoftKeyNumber1.java | 30 +++-- .../tt9/ui/main/keys/SoftKeyNumber2to9.java | 6 + .../tt9/ui/main/keys/SoftKeyPunctuation.java | 2 +- .../io/github/sspanak/tt9/util/TextTools.java | 12 ++ .../sspanak/tt9/util/chars/Punctuation.java | 2 + 20 files changed, 319 insertions(+), 59 deletions(-) create mode 100644 app/languages/definitions/ChineseBopomofo.hidden create mode 100644 app/languages/dictionaries/zh-bopomofo.hidden create mode 100644 app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeBopomofo.java diff --git a/app/languages/definitions/ChineseBopomofo.hidden b/app/languages/definitions/ChineseBopomofo.hidden new file mode 100644 index 00000000..8eb268cc --- /dev/null +++ b/app/languages/definitions/ChineseBopomofo.hidden @@ -0,0 +1,60 @@ +locale: zh-TW +dictionaryFile: zh-bopomofo.csv +name: 中文 / 繁體 +abcString: ㄅㄆㄇ +hasSpaceBetweenWords: no +hasUpperCase: no +layout: + - [ㄧ, ㄨ, ㄩ, SPECIAL] # 0 + - [ㄅ, ㄆ, ㄇ, ㄈ, PUNCTUATION_ZH] # 1 + - [ㄉ, ㄊ, ㄋ, ㄌ] # 2 + - [ㄍ, ㄎ, ㄏ] # 3 + - [ㄐ, ㄑ, ㄒ] # 4 + - [ㄓ, ㄔ, ㄕ, ㄖ] # 5 + - [ㄗ, ㄘ, ㄙ] # 6 + - [ㄚ, ㄛ, ㄜ, ㄝ] # 7 + - [ㄞ, ㄟ, ㄠ, ㄡ] # 8 + - [ㄢ, ㄣ, ㄤ, ㄥ, ㄦ] # 9 +sounds: + - [I,0] # ㄧ + - [Yi,0] # ㄧ, probably unnecessary + - [Y,0] # ㄧ, probably unnecessary + - [U,0] # ㄨ + - [Wu,0] # ㄨ, probably unnecessary + - [W,0] # ㄨ, probably unnecessary + - [Yu,0] # ㄩ + - [Uu,0] # ㄩ, actually "ü", probably unnecessary + - [B,1] # ㄅ + - [P,1] # ㄆ + - [M,1] # ㄇ + - [F,1] # ㄈ + - [D,2] # ㄉ + - [T,2] # ㄊ + - [N,2] # ㄋ + - [L,2] # ㄌ + - [G,3] # ㄍ + - [K,3] # ㄎ + - [H,3] # ㄏ + - [J,4] # ㄐ + - [Q,4] # ㄑ + - [X,4] # ㄒ + - [Zh,5] # ㄓ + - [Ch,5] # ㄔ + - [Sh,5] # ㄕ + - [R,5] # ㄖ + - [Z,6] # ㄗ + - [C,6] # ㄘ + - [S,6] # ㄙ + - [A,7] # ㄚ + - [O,7] # ㄛ + - [E,7] # ㄜ + - [Ie,7] # ㄝ + - [Ai,8] # ㄞ + - [Ei,8] # ㄟ + - [Ao,8] # ㄠ + - [Ou,8] # ㄡ + - [An,9] # ㄢ + - [En,9] # ㄣ + - [Ang,9] # ㄤ + - [Eng,9] # ㄥ + - [Er,9] # ㄦ diff --git a/app/languages/dictionaries/zh-bopomofo.hidden b/app/languages/dictionaries/zh-bopomofo.hidden new file mode 100644 index 00000000..851da768 --- /dev/null +++ b/app/languages/dictionaries/zh-bopomofo.hidden @@ -0,0 +1,37 @@ +ㄧ I +ㄨ U +ㄩ Yu +ㄅ B +ㄆ P +ㄇ M +ㄈ F +ㄉ D +ㄊ T +ㄋ N +ㄌ L +ㄍ G +ㄎ K +ㄏ H +ㄐ J +ㄑ Q +ㄒ X +ㄓ Zh +ㄔ Ch +ㄕ Sh +ㄖ R +ㄗ Z +ㄘ C +ㄙ S +ㄚ A +ㄛ O +ㄜ E +ㄝ Ie +ㄞ Ai +ㄟ Ei +ㄠ Ao +ㄡ Ou +ㄢ An +ㄣ En +ㄤ Ang +ㄥ Eng +ㄦ Er \ No newline at end of file diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/MainViewHandler.java b/app/src/main/java/io/github/sspanak/tt9/ime/MainViewHandler.java index 8b9a9fbd..db682b1f 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/MainViewHandler.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/MainViewHandler.java @@ -10,6 +10,7 @@ import io.github.sspanak.tt9.ime.helpers.OrientationListener; import io.github.sspanak.tt9.ime.modes.InputModeKind; import io.github.sspanak.tt9.ime.voice.VoiceInputOps; import io.github.sspanak.tt9.languages.Language; +import io.github.sspanak.tt9.languages.LanguageKind; import io.github.sspanak.tt9.preferences.settings.SettingsStore; import io.github.sspanak.tt9.ui.main.ResizableMainView; @@ -191,6 +192,11 @@ abstract public class MainViewHandler extends HotkeyHandler { } + public boolean hasLettersOnAllKeys() { + return LanguageKind.isKorean(mLanguage) || LanguageKind.isChineseBopomofo(mLanguage); + } + + private void resetNormalizedDimensions() { normalizedWidth = -1; normalizedHeight = -1; diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java index a8d98f86..ecc8e5da 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java @@ -53,7 +53,8 @@ abstract public class InputMode { public static InputMode getInstance(SettingsStore settings, @Nullable Language language, InputType inputType, TextField textField, int mode) { switch (mode) { case MODE_PREDICTIVE: - if (LanguageKind.isChinese(language)) return new ModePinyin(settings, language, inputType, textField); + if (LanguageKind.isChineseBopomofo(language)) return new ModeBopomofo(settings, language, inputType, textField); + if (LanguageKind.isChinesePinyin(language)) return new ModePinyin(settings, language, inputType, textField); if (LanguageKind.isJapanese(language)) return new ModeKanji(settings, language, inputType, textField); if (LanguageKind.isKorean(language)) return new ModeCheonjiin(settings, inputType, textField); if (language != null && language.isTranscribed()) return new ModeIdeograms(settings, language, inputType, textField); diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeABC.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeABC.java index fbd69559..999d828d 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeABC.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeABC.java @@ -92,7 +92,7 @@ class ModeABC extends InputMode { @Override public boolean changeLanguage(@Nullable Language newLanguage) { - if (newLanguage != null && newLanguage.isTranscribed()) { + if (newLanguage != null && !newLanguage.hasABC()) { return false; } diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeBopomofo.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeBopomofo.java new file mode 100644 index 00000000..3370f4ee --- /dev/null +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeBopomofo.java @@ -0,0 +1,118 @@ +package io.github.sspanak.tt9.ime.modes; + +import androidx.annotation.Nullable; + +import io.github.sspanak.tt9.hacks.InputType; +import io.github.sspanak.tt9.ime.helpers.TextField; +import io.github.sspanak.tt9.languages.EmojiLanguage; +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.settings.SettingsStore; +import io.github.sspanak.tt9.util.TextTools; +import io.github.sspanak.tt9.util.chars.Characters; + +public class ModeBopomofo extends ModePinyin { + private static final String SPECIAL_CHAR_SEQUENCE_PREFIX = "S0"; + private static final String PUNCTUATION_SEQUENCE_PREFIX = "S1"; + + protected ModeBopomofo(SettingsStore settings, Language lang, InputType inputType, TextField textField) { + super(settings, lang, inputType, textField); + } + + + @Override + public boolean changeLanguage(@Nullable Language newLanguage) { + if (LanguageKind.isChineseBopomofo(newLanguage)) { + setLanguage(newLanguage); + return true; + } + + return false; + } + + + /* **************************** LOAD SUGGESTIONS *********************************/ + + /** + * Not possible in Bopomofo mode, because 0-key is used for typing letters. + */ + @Override protected boolean loadPreferredChar() { return false; } + + + /** + * setCustomSpecialCharacters + * Filter out the letters from the 0-key list and add "0", because there is no other way of + * typing it. + */ + protected void setCustomSpecialCharacters() { + // special + KEY_CHARACTERS.add(TextTools.removeLettersFromList(applyPunctuationOrder(Characters.Special, 0))); + KEY_CHARACTERS.get(0).add(0, "0"); + + // punctuation + KEY_CHARACTERS.add( + TextTools.removeLettersFromList(applyPunctuationOrder(Characters.PunctuationChinese, 1)) + ); + } + + + protected void setSpecialCharacterConstants() { + CUSTOM_EMOJI_SEQUENCE = PUNCTUATION_SEQUENCE_PREFIX + EmojiLanguage.CUSTOM_EMOJI_SEQUENCE; + EMOJI_SEQUENCE = PUNCTUATION_SEQUENCE_PREFIX + EmojiLanguage.EMOJI_SEQUENCE; + PUNCTUATION_SEQUENCE = PUNCTUATION_SEQUENCE_PREFIX + NaturalLanguage.PUNCTUATION_KEY; + SPECIAL_CHAR_SEQUENCE = SPECIAL_CHAR_SEQUENCE_PREFIX + NaturalLanguage.SPECIAL_CHAR_KEY; + } + + + /***************************** TYPING *********************************/ + + @Override + public boolean onBackspace() { + if (digitSequence.equals(PUNCTUATION_SEQUENCE) || digitSequence.equals(SPECIAL_CHAR_SEQUENCE)) { + digitSequence = ""; + return false; + } else { + return super.onBackspace(); + } + } + + + @Override + protected void onNumberPress(int nextNumber) { + if (digitSequence.startsWith(PUNCTUATION_SEQUENCE)) { + digitSequence = PUNCTUATION_SEQUENCE_PREFIX + EmojiLanguage.validateEmojiSequence(digitSequence.substring(PUNCTUATION_SEQUENCE_PREFIX.length()), nextNumber); + } else { + digitSequence += String.valueOf(nextNumber); + } + } + + + @Override + protected void onNumberHold(int number) { + if (number == 0) { + disablePredictions = false; + digitSequence = SPECIAL_CHAR_SEQUENCE; + } else if (number == 1) { + disablePredictions = false; + digitSequence = PUNCTUATION_SEQUENCE; + } else { + autoAcceptTimeout = 0; + suggestions.add(language.getKeyNumeral(number)); + } + } + + + /******************************* ACCEPT WORDS *********************************/ + + /** + * In Bopomofo mode, the 0-key is not Spacebar, so we do not rely on the parents to handle accepting + */ + @Override + public boolean shouldAcceptPreviousSuggestion(int nextKey, boolean hold) { + String newSequence = digitSequence + (char)(nextKey + '0'); + return hold + || newSequence.startsWith(SPECIAL_CHAR_SEQUENCE) + || (newSequence.startsWith(PUNCTUATION_SEQUENCE) && nextKey != NaturalLanguage.PUNCTUATION_KEY.charAt(0) - '0'); + } +} diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModePinyin.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModePinyin.java index eb36759f..1065d12f 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModePinyin.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModePinyin.java @@ -22,7 +22,7 @@ public class ModePinyin extends ModeIdeograms { @Override public boolean changeLanguage(@Nullable Language newLanguage) { - if (LanguageKind.isChinese(newLanguage)) { + if (LanguageKind.isChinesePinyin(newLanguage)) { setLanguage(newLanguage); return true; } diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java index 775aa5af..0fe61d9f 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java @@ -290,7 +290,7 @@ class ModeWords extends ModeCheonjiin { } - private boolean loadPreferredChar() { + protected boolean loadPreferredChar() { if (digitSequence.startsWith(NaturalLanguage.PREFERRED_CHAR_SEQUENCE)) { suggestions.clear(); suggestions.add(getPreferredChar()); diff --git a/app/src/main/java/io/github/sspanak/tt9/languages/LanguageKind.java b/app/src/main/java/io/github/sspanak/tt9/languages/LanguageKind.java index 8152ee40..84265227 100644 --- a/app/src/main/java/io/github/sspanak/tt9/languages/LanguageKind.java +++ b/app/src/main/java/io/github/sspanak/tt9/languages/LanguageKind.java @@ -12,7 +12,9 @@ public class LanguageKind { public static boolean isArabic(Language language) { return language != null && language.getId() == 502337; } public static boolean isEnglish(Language language) { return language != null && language.getLocale().equals(Locale.ENGLISH); } - public static boolean isChinese(Language language) { return language != null && language.getId() == 462106; } + public static boolean isChinese(Language language) { return isChineseBopomofo(language) || isChinesePinyin(language); } + public static boolean isChineseBopomofo(Language language) { return language != null && language.getId() == 774426; } + public static boolean isChinesePinyin(Language language) { return language != null && language.getId() == 462106; } public static boolean isFarsi(Language language) { return language != null && language.getId() == 599078; } public static boolean isFrench(Language language) { return language != null && language.getId() == 596550; } public static boolean isJapanese(Language language) { return language != null && language.getId() == 534570; } diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java index b4f8bf77..139904a8 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java @@ -10,7 +10,6 @@ import java.util.ArrayList; import io.github.sspanak.tt9.R; import io.github.sspanak.tt9.ime.TraditionalT9; -import io.github.sspanak.tt9.languages.LanguageKind; import io.github.sspanak.tt9.preferences.settings.SettingsStore; import io.github.sspanak.tt9.ui.main.keys.SoftKey; import io.github.sspanak.tt9.ui.main.keys.SoftKeySettings; @@ -283,7 +282,7 @@ class MainLayoutNumpad extends BaseMainLayout { setKeyColumnWidth(tt9.getSettings().getNumpadFnKeyScale()); setBackgroundBlending(); showLongSpace( - tt9.getSettings().isNumpadShapeLongSpace() && !tt9.isInputModeNumeric() && !LanguageKind.isKorean(tt9.getLanguage()), + tt9.getSettings().isNumpadShapeLongSpace() && !tt9.isInputModeNumeric() && !tt9.hasLettersOnAllKeys(), defaultKeyHeight ); for (SoftKey key : getKeys()) { diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKey.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKey.java index 5a2e0f08..4f167850 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKey.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKey.java @@ -13,6 +13,7 @@ import android.widget.TextView; import androidx.annotation.Nullable; +import io.github.sspanak.tt9.languages.LanguageKind; import io.github.sspanak.tt9.preferences.settings.SettingsStore; import io.github.sspanak.tt9.util.Text; import io.github.sspanak.tt9.util.chars.Characters; @@ -30,6 +31,20 @@ public class SoftKey extends BaseClickableKey { public SoftKey(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } + /** + * Bopomofo letters are very large, so we need to scale them down a bit in some keys. Hence, + * the convenience method. + */ + protected boolean isBopomofo() { + return tt9 != null && !tt9.isInputModeNumeric() && LanguageKind.isChineseBopomofo(tt9.getLanguage()); + } + + + protected boolean hasLettersOnAllKeys() { + return tt9 != null && tt9.hasLettersOnAllKeys(); + } + + /** * Returns a scale factor for the screen width, used to adjust the key size and text size. Mostly, * useful for tablets or larger devices, where the keys are too big but the text remains small. diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyFilter.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyFilter.java index 24d6fcdd..4fd7e435 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyFilter.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyFilter.java @@ -4,7 +4,6 @@ import android.content.Context; import android.util.AttributeSet; import io.github.sspanak.tt9.R; -import io.github.sspanak.tt9.languages.LanguageKind; import io.github.sspanak.tt9.ui.Vibration; public class SoftKeyFilter extends BaseSoftKeyWithIcons { @@ -12,13 +11,9 @@ public class SoftKeyFilter extends BaseSoftKeyWithIcons { public SoftKeyFilter(Context context, AttributeSet attrs) { super(context, attrs); } public SoftKeyFilter(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } - private boolean isKorean() { - return tt9 != null && LanguageKind.isKorean(tt9.getLanguage()); - } - @Override protected void handleHold() { - if (isKorean()) { + if (hasLettersOnAllKeys()) { handleRelease(); return; } @@ -37,7 +32,7 @@ public class SoftKeyFilter extends BaseSoftKeyWithIcons { return false; } - if (isKorean()) { + if (hasLettersOnAllKeys()) { return tt9.onKeySpaceKorean(false); } else { return tt9.onKeyFilterSuggestions(false, getLastPressedKey() == getId()); @@ -45,21 +40,21 @@ public class SoftKeyFilter extends BaseSoftKeyWithIcons { } - @Override protected String getTitle() { return isKorean() ? "␣" : ""; } - @Override protected int getCentralIcon() { return isKorean() ? 0 : R.drawable.ic_fn_filter; } - @Override protected int getHoldIcon() { return isKorean() ? 0 : R.drawable.ic_fn_filter_off; } + @Override protected String getTitle() { return hasLettersOnAllKeys() ? "␣" : ""; } + @Override protected int getCentralIcon() { return hasLettersOnAllKeys() ? 0 : R.drawable.ic_fn_filter; } + @Override protected int getHoldIcon() { return hasLettersOnAllKeys() ? 0 : R.drawable.ic_fn_filter_off; } - @Override protected float getTitleScale() { return isKorean() ? 1.3f * Math.min(1, getTT9Height()) * getScreenScaleY() : super.getTitleScale(); } + @Override protected float getTitleScale() { return hasLettersOnAllKeys() ? 1.3f * Math.min(1, getTT9Height()) * getScreenScaleY() : super.getTitleScale(); } @Override public void render() { if (tt9 != null) { setEnabled( !tt9.isInputModeNumeric() - && !tt9.isInputModeABC() && !tt9.isVoiceInputActive() + && (!tt9.isInputModeABC() || hasLettersOnAllKeys()) && ( - LanguageKind.isKorean(tt9.getLanguage()) + hasLettersOnAllKeys() || (tt9.isFilteringSupported() && !tt9.isTextEditingActive()) ) ); diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyLF4.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyLF4.java index c61eb4fd..e1f6f661 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyLF4.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyLF4.java @@ -55,7 +55,7 @@ public class SoftKeyLF4 extends BaseSwipeableKey { @Override protected float getTitleScale() { - return super.getTitleScale() * 0.9f; + return super.getTitleScale() * (isBopomofo() && tt9.isInputModeABC() ? 0.63f : 0.9f); } @Override diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber.java index f8af53b8..c922086d 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber.java @@ -11,6 +11,8 @@ import io.github.sspanak.tt9.languages.LanguageKind; import io.github.sspanak.tt9.ui.Vibration; public class SoftKeyNumber extends BaseSoftKeyWithIcons { + protected static final float TITLE_SCALE_BOPOMOFO = 0.7f; + private final static SparseArray NUMBERS = new SparseArray<>() {{ put(R.id.soft_key_0, 0); put(R.id.soft_key_1, 1); diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber0.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber0.java index 2b57350c..4d864f24 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber0.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber0.java @@ -4,6 +4,7 @@ import android.content.Context; import android.util.AttributeSet; import io.github.sspanak.tt9.languages.LanguageKind; +import io.github.sspanak.tt9.util.TextTools; public class SoftKeyNumber0 extends SoftKeyNumber { private static final String CHARS_NUMERIC_MODE = "+%$"; @@ -13,8 +14,13 @@ public class SoftKeyNumber0 extends SoftKeyNumber { public SoftKeyNumber0(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } + private boolean isKorean() { + return tt9 != null && !tt9.isInputModeNumeric() && LanguageKind.isKorean(tt9.getLanguage()); + } + + private boolean isTransparentWhenTextEditing() { - return tt9 != null && LanguageKind.isKorean(tt9.getLanguage()) && tt9.isTextEditingActive(); + return tt9 != null && tt9.isTextEditingActive() && hasLettersOnAllKeys(); } @@ -22,7 +28,7 @@ public class SoftKeyNumber0 extends SoftKeyNumber { return tt9 != null && tt9.getSettings().isNumpadShapeLongSpace() && !tt9.isInputModeNumeric() - && !LanguageKind.isKorean(tt9.getLanguage()); + && !hasLettersOnAllKeys(); } @@ -44,7 +50,7 @@ public class SoftKeyNumber0 extends SoftKeyNumber { return "+/-"; } else if (tt9.isInputModePhone()) { return "+"; - } else if (tt9.isInputModeNumeric() || LanguageKind.isKorean(tt9.getLanguage())) { + } else if (tt9.isInputModeNumeric() || hasLettersOnAllKeys()) { return CHARS_NUMERIC_MODE; } @@ -58,33 +64,26 @@ public class SoftKeyNumber0 extends SoftKeyNumber { return "0"; } - return (LanguageKind.isKorean(tt9.getLanguage())) ? getKoreanCharList() : "␣"; - } - - - private String getKoreanCharList() { - if (tt9 == null || tt9.getLanguage() == null) { - return null; + if (hasLettersOnAllKeys() && tt9.getLanguage() != null) { + return TextTools.removeNonLettersFromListAndJoin(tt9.getLanguage().getKeyCharacters(0)); } - StringBuilder list = new StringBuilder(); - for (String character : tt9.getLanguage().getKeyCharacters(0)) { - if (Character.isAlphabetic(character.charAt(0))) { - list.append(character); - } - } - - return list.toString(); + return "␣"; } @Override protected float getTitleScale() { - if (tt9 != null && !tt9.isInputModeNumeric() && !LanguageKind.isKorean(tt9.getLanguage())) { - return 1.3f * Math.min(1, getTT9Height()) * getScreenScaleY(); + if (isBopomofo()) { + return super.getTitleScale() * TITLE_SCALE_BOPOMOFO; } - return super.getTitleScale(); + if (isKorean()) { + return super.getTitleScale(); + } + + // scale up the space character, because it is too small + return 1.3f * Math.min(1, getTT9Height()) * getScreenScaleY(); } @@ -101,13 +100,7 @@ public class SoftKeyNumber0 extends SoftKeyNumber { private void setEnabled() { - setEnabled( - tt9 != null - && ( - !tt9.isTextEditingActive() - || (!LanguageKind.isKorean(tt9.getLanguage()) && !tt9.isInputModeNumeric()) - ) - ); + setEnabled(tt9 != null && !(tt9.isTextEditingActive() && hasLettersOnAllKeys())); } diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber1.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber1.java index b757c650..f0f75401 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber1.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber1.java @@ -3,26 +3,38 @@ package io.github.sspanak.tt9.ui.main.keys; import android.content.Context; import android.util.AttributeSet; -import io.github.sspanak.tt9.languages.LanguageKind; +import io.github.sspanak.tt9.util.TextTools; public class SoftKeyNumber1 extends SoftKeyNumber { - private static final String DEFAULT_LARGE_LABEL = ",:-)"; - private static final String KOREAN_SMALL_LABEL = "1 :-)"; - private static final String KOREAN_LARGE_LABEL = "ㅣ"; + private static final String LARGE_LABEL_NUMERIC = "1"; + private static final String LARGE_LABEL_TEXT = ",:-)"; + private static final String HOLD_LABEL_NUMERIC_WHEN_LETTERS = "1 :-)"; public SoftKeyNumber1(Context context) { super(context); } public SoftKeyNumber1(Context context, AttributeSet attrs) { super(context, attrs); } public SoftKeyNumber1(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } + @Override protected String getTitle() { if (tt9 == null || tt9.isInputModeNumeric()) { - return "1"; + return LARGE_LABEL_NUMERIC; } - return LanguageKind.isKorean(tt9.getLanguage()) ? KOREAN_LARGE_LABEL : DEFAULT_LARGE_LABEL; + if (hasLettersOnAllKeys() && tt9.getLanguage() != null) { + return TextTools.removeNonLettersFromListAndJoin(tt9.getLanguage().getKeyCharacters(1)); + } + + return LARGE_LABEL_TEXT; } + + @Override + protected float getTitleScale() { + return super.getTitleScale() * (isBopomofo() ? TITLE_SCALE_BOPOMOFO : 1); + } + + @Override protected String getHoldText() { if (tt9 == null || tt9.isNumericModeStrict()) { @@ -30,11 +42,11 @@ public class SoftKeyNumber1 extends SoftKeyNumber { } if (tt9.isInputModeNumeric()) { - return DEFAULT_LARGE_LABEL; + return LARGE_LABEL_TEXT; } - if (LanguageKind.isKorean(tt9.getLanguage())) { - return KOREAN_SMALL_LABEL; + if (hasLettersOnAllKeys() && !(tt9.isInputModeABC() && isBopomofo())) { + return HOLD_LABEL_NUMERIC_WHEN_LETTERS; } return super.getLocalizedNumber(getNumber(getId())); diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber2to9.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber2to9.java index 85854d3b..cb649652 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber2to9.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyNumber2to9.java @@ -43,6 +43,12 @@ public class SoftKeyNumber2to9 extends SoftKeyNumber { } + @Override + protected float getTitleScale() { + return super.getTitleScale() * (isBopomofo() ? TITLE_SCALE_BOPOMOFO : 1); + } + + private String getKeyChars(@NonNull TraditionalT9 tt9, int number) { Language language = tt9.getLanguage(); if (language == null) { diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyPunctuation.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyPunctuation.java index 588a54ed..1a152ffd 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyPunctuation.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyPunctuation.java @@ -18,7 +18,7 @@ public class SoftKeyPunctuation extends SoftKey { tt9 != null && tt9.getSettings().isNumpadShapeLongSpace() && !tt9.isInputModeNumeric() - && !LanguageKind.isKorean(tt9.getLanguage()); + && !hasLettersOnAllKeys(); } protected boolean isTransparentWhenTextEditing() { diff --git a/app/src/main/java/io/github/sspanak/tt9/util/TextTools.java b/app/src/main/java/io/github/sspanak/tt9/util/TextTools.java index 2ed4cf01..609a261c 100644 --- a/app/src/main/java/io/github/sspanak/tt9/util/TextTools.java +++ b/app/src/main/java/io/github/sspanak/tt9/util/TextTools.java @@ -127,4 +127,16 @@ public class TextTools { return cleanList; } + + + public static String removeNonLettersFromListAndJoin(ArrayList list) { + StringBuilder cleanList = new StringBuilder(); + for (String ch : list) { + if (Character.isAlphabetic(ch.codePointAt(0))) { + cleanList.append(ch); + } + } + + return cleanList.toString(); + } } diff --git a/app/src/main/java/io/github/sspanak/tt9/util/chars/Punctuation.java b/app/src/main/java/io/github/sspanak/tt9/util/chars/Punctuation.java index 1e23bd5b..0479d7c0 100644 --- a/app/src/main/java/io/github/sspanak/tt9/util/chars/Punctuation.java +++ b/app/src/main/java/io/github/sspanak/tt9/util/chars/Punctuation.java @@ -51,6 +51,8 @@ class Punctuation { ",", ZH_COMMA_LIST, ZH_FULL_STOP, "—", "~", "゠", "(", ")", ".", "「", "」", "『", "』", "•", "《", "》", "〈", "〉", "'", "“", "”", ";", ":", ZH_EXCLAMATION_MARK, ZH_QUESTION_MARK )); + final public static ArrayList PunctuationChineseBopomofo = insertChar(PunctuationChinese, "1", ZH_FULL_STOP); + final public static ArrayList PunctuationEnglish = new ArrayList<>(Arrays.asList( ",", ".", "-", "(", ")", "&", "~", "`", ";", ":", "'", "\"", "!", "?" ));