diff --git a/src/io/github/sspanak/tt9/ime/TraditionalT9.java b/src/io/github/sspanak/tt9/ime/TraditionalT9.java
index a490d1df..cdbc259a 100644
--- a/src/io/github/sspanak/tt9/ime/TraditionalT9.java
+++ b/src/io/github/sspanak/tt9/ime/TraditionalT9.java
@@ -63,8 +63,20 @@ public class TraditionalT9 extends KeyPadHandler {
return settings;
}
- public int getInputMode() {
- return mInputMode != null ? mInputMode.getId() : InputMode.MODE_UNDEFINED;
+ public boolean isInputModeNumeric() {
+ return mInputMode != null && mInputMode.is123();
+ }
+
+ public boolean isNumericModeStrict() {
+ return mInputMode != null && mInputMode.is123() && inputType.isNumeric() && !inputType.isPhoneNumber();
+ }
+
+ public boolean isNumericModeSigned() {
+ return mInputMode != null && mInputMode.is123() && inputType.isSignedNumber();
+ }
+
+ public boolean isInputModePhone() {
+ return mInputMode != null && mInputMode.is123() && inputType.isPhoneNumber();
}
public int getTextCase() {
@@ -96,7 +108,7 @@ public class TraditionalT9 extends KeyPadHandler {
private void determineInputMode() {
allowedInputModes = textField.determineInputModes(inputType);
int validModeId = InputModeValidator.validateMode(settings.getInputMode(), allowedInputModes);
- mInputMode = InputMode.getInstance(settings, mLanguage, validModeId);
+ mInputMode = InputMode.getInstance(settings, mLanguage, inputType, validModeId);
}
@@ -669,7 +681,7 @@ public class TraditionalT9 extends KeyPadHandler {
if (mInputMode.isPassthrough()) {
return;
} else if (allowedInputModes.size() == 1 && allowedInputModes.contains(InputMode.MODE_123)) {
- mInputMode = !mInputMode.is123() ? InputMode.getInstance(settings, mLanguage, InputMode.MODE_123) : mInputMode;
+ mInputMode = !mInputMode.is123() ? InputMode.getInstance(settings, mLanguage, inputType, InputMode.MODE_123) : mInputMode;
}
// when typing a word or viewing scrolling the suggestions, only change the case
else if (!isSuggestionViewHidden()) {
@@ -693,7 +705,7 @@ public class TraditionalT9 extends KeyPadHandler {
mInputMode.nextTextCase();
} else {
int nextModeIndex = (allowedInputModes.indexOf(mInputMode.getId()) + 1) % allowedInputModes.size();
- mInputMode = InputMode.getInstance(settings, mLanguage, allowedInputModes.get(nextModeIndex));
+ mInputMode = InputMode.getInstance(settings, mLanguage, inputType, allowedInputModes.get(nextModeIndex));
mInputMode.setTextFieldCase(textField.determineTextCase(inputType));
mInputMode.determineNextWordTextCase(textField.isThereText(), textField.getTextBeforeCursor());
diff --git a/src/io/github/sspanak/tt9/ime/helpers/InputType.java b/src/io/github/sspanak/tt9/ime/helpers/InputType.java
index 660f4400..c7f97a0d 100644
--- a/src/io/github/sspanak/tt9/ime/helpers/InputType.java
+++ b/src/io/github/sspanak/tt9/ime/helpers/InputType.java
@@ -24,7 +24,7 @@ public class InputType {
* isLimited
* Special or limited input type means the input connection is not rich,
* or it can not process or show things like candidate text, nor retrieve the current text.
- *
+ *
* More info: android docs.
*/
public boolean isLimited() {
@@ -36,24 +36,44 @@ public class InputType {
* isSpecialNumeric
* Calculator and Dialer fields seem to take care of numbers and backspace on their own,
* so we need to be aware of them.
- *
+ *
* NOTE: A Dialer field is not the same as Phone field. Dialer is where you
* actually dial and call a phone number. While the Phone field is a text
* field in any app or a webpage, intended for typing phone numbers.
- *
+ *
* More info: in this Github issue
* and the PR about calculators.
*/
public boolean isSpecialNumeric() {
- if (field == null) {
- return false;
- }
-
- int inputType = field.inputType & android.text.InputType.TYPE_MASK_CLASS;
-
return
- inputType == android.text.InputType.TYPE_CLASS_PHONE && field.packageName.equals("com.android.dialer")
- || inputType == android.text.InputType.TYPE_CLASS_NUMBER && field.packageName.contains("com.android.calculator");
+ isPhoneNumber() && field.packageName.equals("com.android.dialer")
+ || isNumeric() && field.packageName.contains("com.android.calculator");
+ }
+
+
+ public boolean isPhoneNumber() {
+ return
+ field != null
+ && (field.inputType & android.text.InputType.TYPE_MASK_CLASS) == android.text.InputType.TYPE_CLASS_PHONE;
+ }
+
+ public boolean isNumeric() {
+ return
+ field != null
+ && (field.inputType & android.text.InputType.TYPE_MASK_CLASS) == android.text.InputType.TYPE_CLASS_NUMBER;
+ }
+
+ public boolean isDecimal() {
+ return
+ isNumeric()
+ && (field.inputType & android.text.InputType.TYPE_MASK_FLAGS) == android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL;
+ }
+
+
+ public boolean isSignedNumber() {
+ return
+ isNumeric()
+ && (field.inputType & android.text.InputType.TYPE_MASK_FLAGS) == android.text.InputType.TYPE_NUMBER_FLAG_SIGNED;
}
diff --git a/src/io/github/sspanak/tt9/ime/modes/InputMode.java b/src/io/github/sspanak/tt9/ime/modes/InputMode.java
index 6639e593..aaf5b3f0 100644
--- a/src/io/github/sspanak/tt9/ime/modes/InputMode.java
+++ b/src/io/github/sspanak/tt9/ime/modes/InputMode.java
@@ -12,7 +12,6 @@ import io.github.sspanak.tt9.preferences.SettingsStore;
abstract public class InputMode {
// typing mode
- public static final int MODE_UNDEFINED = -1;
public static final int MODE_PREDICTIVE = 0;
public static final int MODE_ABC = 1;
public static final int MODE_123 = 2;
@@ -34,7 +33,7 @@ abstract public class InputMode {
protected final ArrayList suggestions = new ArrayList<>();
- public static InputMode getInstance(SettingsStore settings, Language language, int mode) {
+ public static InputMode getInstance(SettingsStore settings, Language language, InputType inputType, int mode) {
switch (mode) {
case MODE_PREDICTIVE:
return new ModePredictive(settings, language);
@@ -45,7 +44,7 @@ abstract public class InputMode {
default:
Logger.w("InputMode", "Defaulting to mode: " + Mode123.class.getName() + " for unknown InputMode: " + mode);
case MODE_123:
- return new Mode123();
+ return new Mode123(inputType);
}
}
diff --git a/src/io/github/sspanak/tt9/ime/modes/Mode123.java b/src/io/github/sspanak/tt9/ime/modes/Mode123.java
index 367412ea..c3f50de5 100644
--- a/src/io/github/sspanak/tt9/ime/modes/Mode123.java
+++ b/src/io/github/sspanak/tt9/ime/modes/Mode123.java
@@ -3,8 +3,10 @@ package io.github.sspanak.tt9.ime.modes;
import androidx.annotation.NonNull;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
+import io.github.sspanak.tt9.ime.helpers.InputType;
import io.github.sspanak.tt9.languages.Characters;
public class Mode123 extends ModePassthrough {
@@ -18,7 +20,47 @@ public class Mode123 extends ModePassthrough {
private final ArrayList> KEY_CHARACTERS = new ArrayList<>();
- public Mode123() {
+
+ public Mode123(InputType inputType) {
+ if (inputType.isPhoneNumber()) {
+ getPhoneSpecialCharacters();
+ } else if (inputType.isNumeric()) {
+ getNumberSpecialCharacters(inputType.isDecimal(), inputType.isSignedNumber());
+ } else {
+ getDefaultSpecialCharacters();
+ }
+ }
+
+
+ /**
+ * getPhoneSpecialCharacters
+ * Special characters for phone number fields, including both characters for conveniently typing a phone number: "()-",
+ * as well as command characters such as "," = "slight pause" and ";" = "wait" used in Japan and some other countries.
+ */
+ private void getPhoneSpecialCharacters() {
+ KEY_CHARACTERS.add(new ArrayList<>(Arrays.asList("+", " ")));
+ KEY_CHARACTERS.add(new ArrayList<>(Arrays.asList("-", "(", ")", ".", ";", ",")));
+ }
+
+
+ /**
+ * getNumberSpecialCharacters
+ * Special characters for all kinds of numeric fields: integer, decimal with +/- included as necessary.
+ */
+ private void getNumberSpecialCharacters(boolean decimal, boolean signed) {
+ KEY_CHARACTERS.add(signed ? new ArrayList<>(Arrays.asList("-", "+")) : new ArrayList<>());
+ if (decimal) {
+ KEY_CHARACTERS.add(new ArrayList<>(Arrays.asList(".", ",")));
+ }
+ }
+
+
+ /**
+ * getDefaultSpecialCharacters
+ * Special characters for when the user has selected 123 mode in a text field. In this case, we just
+ * use the default list, but reorder it a bit for convenience.
+ */
+ private void getDefaultSpecialCharacters() {
// 0-key
KEY_CHARACTERS.add(new ArrayList<>(Collections.singletonList("+")));
for (String character : Characters.Special) {
@@ -36,10 +78,11 @@ public class Mode123 extends ModePassthrough {
}
}
+
@Override public boolean onNumber(int number, boolean hold, int repeat) {
reset();
- if (hold && number < KEY_CHARACTERS.size()) {
+ if (hold && number < KEY_CHARACTERS.size() && KEY_CHARACTERS.get(number).size() > 0) {
suggestions.addAll(KEY_CHARACTERS.get(number));
} else {
autoAcceptTimeout = 0;
@@ -49,6 +92,7 @@ public class Mode123 extends ModePassthrough {
return true;
}
+
/**
* shouldIgnoreText
* Since this is a numeric mode, we allow typing only numbers and:
diff --git a/src/io/github/sspanak/tt9/ui/main/keys/SoftNumberKey.java b/src/io/github/sspanak/tt9/ui/main/keys/SoftNumberKey.java
index 4ec78d1f..5b09c481 100644
--- a/src/io/github/sspanak/tt9/ui/main/keys/SoftNumberKey.java
+++ b/src/io/github/sspanak/tt9/ui/main/keys/SoftNumberKey.java
@@ -64,8 +64,13 @@ public class SoftNumberKey extends SoftKey {
int number = getNumber(getId());
+ // 0
if (number == 0) {
- if (tt9.getInputMode() == InputMode.MODE_123) {
+ if (tt9.isNumericModeSigned()) {
+ return "+/-";
+ } else if (tt9.isNumericModeStrict()) {
+ return null;
+ } else if (tt9.isInputModeNumeric()) {
return "+";
} else {
COMPLEX_LABEL_SUB_TITLE_SIZE = 1;
@@ -75,11 +80,11 @@ public class SoftNumberKey extends SoftKey {
// 1
if (number == 1) {
- return ",:-)";
+ return tt9.isNumericModeStrict() ? null : ",:-)";
}
// no other special labels in 123 mode
- if (tt9.getInputMode() == InputMode.MODE_123) {
+ if (tt9.isInputModeNumeric()) {
return null;
}
diff --git a/src/io/github/sspanak/tt9/ui/main/keys/SoftPunctuationKey.java b/src/io/github/sspanak/tt9/ui/main/keys/SoftPunctuationKey.java
index 734e0a9d..294b655a 100644
--- a/src/io/github/sspanak/tt9/ui/main/keys/SoftPunctuationKey.java
+++ b/src/io/github/sspanak/tt9/ui/main/keys/SoftPunctuationKey.java
@@ -4,7 +4,6 @@ import android.content.Context;
import android.util.AttributeSet;
import io.github.sspanak.tt9.R;
-import io.github.sspanak.tt9.ime.modes.InputMode;
public class SoftPunctuationKey extends SoftKey {
public SoftPunctuationKey(Context context) {
@@ -21,37 +20,39 @@ public class SoftPunctuationKey extends SoftKey {
@Override
protected boolean handleRelease() {
- if (!validateTT9Handler()) {
- return false;
- }
-
- int keyId = getId();
- if (tt9.getInputMode() == InputMode.MODE_123) {
- if (keyId == R.id.soft_key_punctuation_1) return tt9.onText("*");
- if (keyId == R.id.soft_key_punctuation_2) return tt9.onText("#");
- } else {
- if (keyId == R.id.soft_key_punctuation_1) return tt9.onText("!");
- if (keyId == R.id.soft_key_punctuation_2) return tt9.onText("?");
- }
-
- return true;
+ return tt9.onText(getKeyChar());
}
@Override
protected String getTitle() {
- if (tt9 == null) {
- return "PUNC";
+ String keyChar = getKeyChar();
+ switch (keyChar) {
+ case "":
+ return "PUNC";
+ case "*":
+ return "✱";
+ default:
+ return keyChar;
+ }
+ }
+
+ private String getKeyChar() {
+ if (!validateTT9Handler()) {
+ return "";
}
int keyId = getId();
- if (tt9.getInputMode() == InputMode.MODE_123) {
- if (keyId == R.id.soft_key_punctuation_1) return "✱";
+ if (tt9.isInputModePhone()) {
+ if (keyId == R.id.soft_key_punctuation_1) return "*";
if (keyId == R.id.soft_key_punctuation_2) return "#";
+ } else if (tt9.isInputModeNumeric()) {
+ if (keyId == R.id.soft_key_punctuation_1) return ",";
+ if (keyId == R.id.soft_key_punctuation_2) return ".";
} else {
if (keyId == R.id.soft_key_punctuation_1) return "!";
if (keyId == R.id.soft_key_punctuation_2) return "?";
}
- return "PUNC";
+ return "";
}
}