Copy pasta (#566)
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:tools="http://schemas.android.com/tools"
|
||||
android:versionCode="599"
|
||||
android:versionName="35.0"
|
||||
android:versionCode="611"
|
||||
android:versionName="35.12"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <!-- allows displaying notifications on Android >= 13 -->
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import androidx.annotation.NonNull;
|
|||
import io.github.sspanak.tt9.ime.helpers.CursorOps;
|
||||
import io.github.sspanak.tt9.ime.helpers.SuggestionOps;
|
||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||
import io.github.sspanak.tt9.ime.helpers.TextSelection;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||
|
||||
|
|
@ -16,13 +17,15 @@ public class AppHacks {
|
|||
private final InputType inputType;
|
||||
private final SettingsStore settings;
|
||||
private final TextField textField;
|
||||
private final TextSelection textSelection;
|
||||
|
||||
|
||||
public AppHacks(SettingsStore settings, InputConnection inputConnection, InputType inputType, TextField textField) {
|
||||
public AppHacks(SettingsStore settings, InputConnection inputConnection, InputType inputType, TextField textField, TextSelection textSelection) {
|
||||
this.inputConnection = inputConnection;
|
||||
this.inputType = inputType;
|
||||
this.settings = settings;
|
||||
this.textField = textField;
|
||||
this.textSelection = textSelection;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -51,8 +54,12 @@ public class AppHacks {
|
|||
return false;
|
||||
}
|
||||
|
||||
// When there is no text, allow double function keys to function normally (e.g. "Back" navigates back)
|
||||
return inputMode.getSuggestions().isEmpty() && textField.getStringBeforeCursor(1).isEmpty();
|
||||
// When no text is selected and the cursor is at the beginning,
|
||||
// allow double function keys to function normally (e.g. "Back" navigates back)
|
||||
return
|
||||
inputMode.getSuggestions().isEmpty()
|
||||
&& textSelection.isEmpty()
|
||||
&& textField.getStringBeforeCursor(1).isEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -63,7 +70,7 @@ public class AppHacks {
|
|||
*/
|
||||
public boolean onAction(int action) {
|
||||
if (inputType.isSonimSearchField(action)) {
|
||||
return sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
|
||||
return textField.sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -76,7 +83,7 @@ public class AppHacks {
|
|||
*/
|
||||
public boolean onMoveCursor(boolean backward) {
|
||||
if (inputType.isRustDesk() || inputType.isTermux()) {
|
||||
return sendDownUpKeyEvents(backward ? KeyEvent.KEYCODE_DPAD_LEFT : KeyEvent.KEYCODE_DPAD_RIGHT);
|
||||
return textField.sendDownUpKeyEvents(backward ? KeyEvent.KEYCODE_DPAD_LEFT : KeyEvent.KEYCODE_DPAD_RIGHT);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -119,7 +126,7 @@ public class AppHacks {
|
|||
// Termux supports only ENTER, so we convert DPAD_CENTER for it.
|
||||
// Any extra installed apps are likely not designed for hardware keypads, so again,
|
||||
// we don't want to send DPAD_CENTER to them.
|
||||
return sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
|
||||
return textField.sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
|
||||
}
|
||||
|
||||
// The rest of the cases are probably system apps or numeric fields, which should
|
||||
|
|
@ -138,30 +145,14 @@ public class AppHacks {
|
|||
return false;
|
||||
}
|
||||
|
||||
sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
|
||||
sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
|
||||
sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
|
||||
sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB, true);
|
||||
sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB, true);
|
||||
sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB, true);
|
||||
sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB, true);
|
||||
textField.sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
|
||||
textField.sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
|
||||
textField.sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
|
||||
textField.sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB, true, false);
|
||||
textField.sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB, true, false);
|
||||
textField.sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB, true, false);
|
||||
textField.sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB, true, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private boolean sendDownUpKeyEvents(int keyCode) {
|
||||
return sendDownUpKeyEvents(keyCode, false);
|
||||
}
|
||||
|
||||
|
||||
private boolean sendDownUpKeyEvents(int keyCode, boolean shift) {
|
||||
if (inputConnection != null) {
|
||||
KeyEvent downEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, keyCode, 0, shift ? KeyEvent.META_SHIFT_ON : 0);
|
||||
KeyEvent upEvent = new KeyEvent(0, 0, KeyEvent.ACTION_UP, keyCode, 0, shift ? KeyEvent.META_SHIFT_ON : 0);
|
||||
return inputConnection.sendKeyEvent(downEvent) && inputConnection.sendKeyEvent(upEvent);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@ import android.view.inputmethod.InputConnection;
|
|||
|
||||
import io.github.sspanak.tt9.ime.helpers.SuggestionOps;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.util.Ternary;
|
||||
|
||||
abstract public class AbstractHandler extends InputMethodService {
|
||||
// hardware key handlers
|
||||
abstract protected boolean onBack();
|
||||
abstract protected Ternary onBack();
|
||||
abstract public boolean onBackspace();
|
||||
abstract public boolean onHotkey(int keyCode, boolean repeat, boolean validateOnly);
|
||||
abstract protected boolean onNumber(int key, boolean hold, int repeat);
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@ import io.github.sspanak.tt9.ime.modes.ModeABC;
|
|||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.ui.UI;
|
||||
import io.github.sspanak.tt9.ui.dialogs.AddWordDialog;
|
||||
import io.github.sspanak.tt9.util.Clipboard;
|
||||
import io.github.sspanak.tt9.util.Ternary;
|
||||
|
||||
abstract public class CommandHandler extends VoiceHandler {
|
||||
abstract public class CommandHandler extends TextEditingHandler {
|
||||
@Override
|
||||
protected boolean onBack() {
|
||||
return super.onBack() || hideCommandPalette();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onBackspace() {
|
||||
return hideCommandPalette() || super.onBackspace();
|
||||
protected Ternary onBack() {
|
||||
if (hideCommandPalette()) {
|
||||
return Ternary.TRUE;
|
||||
} else {
|
||||
return super.onBack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -44,9 +44,6 @@ abstract public class CommandHandler extends VoiceHandler {
|
|||
|
||||
private void onCommand(int key) {
|
||||
switch (key) {
|
||||
case 0:
|
||||
changeKeyboard();
|
||||
break;
|
||||
case 1:
|
||||
showSettings();
|
||||
break;
|
||||
|
|
@ -56,6 +53,12 @@ abstract public class CommandHandler extends VoiceHandler {
|
|||
case 3:
|
||||
toggleVoiceInput();
|
||||
break;
|
||||
case 5:
|
||||
showTextEditingPalette();
|
||||
break;
|
||||
case 8:
|
||||
changeKeyboard();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -63,6 +66,9 @@ abstract public class CommandHandler extends VoiceHandler {
|
|||
protected void resetStatus() {
|
||||
if (mainView.isCommandPaletteShown()) {
|
||||
statusBar.setText(R.string.commands_select_command);
|
||||
} if (mainView.isTextEditingPaletteShown()) {
|
||||
String preview = Clipboard.getPreview(this);
|
||||
statusBar.setText(preview.isEmpty() ? getString(R.string.commands_select_command) : "[ \"" + preview + "\" ]");
|
||||
} else {
|
||||
statusBar.setText(mInputMode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,15 @@
|
|||
package io.github.sspanak.tt9.ime;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
import io.github.sspanak.tt9.db.DictionaryLoader;
|
||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||
import io.github.sspanak.tt9.ime.modes.ModePredictive;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||
import io.github.sspanak.tt9.preferences.helpers.Hotkeys;
|
||||
import io.github.sspanak.tt9.ui.UI;
|
||||
import io.github.sspanak.tt9.util.Ternary;
|
||||
|
||||
public abstract class HotkeyHandler extends CommandHandler {
|
||||
private boolean isSystemRTL;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onInit() {
|
||||
super.onInit();
|
||||
|
|
@ -26,15 +20,14 @@ public abstract class HotkeyHandler extends CommandHandler {
|
|||
|
||||
|
||||
@Override
|
||||
protected boolean onStart(InputConnection connection, EditorInfo field) {
|
||||
isSystemRTL = LanguageKind.isRTL(LanguageCollection.getDefault(this));
|
||||
return super.onStart(connection, field);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onBack() {
|
||||
return super.onBack() || settings.isMainLayoutNumpad();
|
||||
public Ternary onBack() {
|
||||
if (super.onBack() == Ternary.TRUE) {
|
||||
return Ternary.TRUE;
|
||||
} else if (settings.isMainLayoutNumpad()) {
|
||||
return Ternary.ALTERNATIVE;
|
||||
} else {
|
||||
return Ternary.FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -102,7 +95,12 @@ public abstract class HotkeyHandler extends CommandHandler {
|
|||
|
||||
|
||||
public boolean onKeyMoveCursor(boolean backward) {
|
||||
return appHacks.onMoveCursor(backward) || textField.moveCursor(backward);
|
||||
if (textSelection.isEmpty()) {
|
||||
return appHacks.onMoveCursor(backward) || textField.moveCursor(backward);
|
||||
} else {
|
||||
textSelection.clear(backward);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -76,8 +76,13 @@ abstract class KeyPadHandler extends UiHandler {
|
|||
event.startTracking();
|
||||
}
|
||||
|
||||
// on many devices there is a default back handler, so we must fall back to it when we don't
|
||||
// perform any operation
|
||||
if (Key.isBack(keyCode)) {
|
||||
return onBack() && super.onKeyDown(keyCode, event);
|
||||
Key.setHandled(keyCode, onBack());
|
||||
return Key.isHandledInSuper(keyCode) ? super.onKeyDown(keyCode, event) : Key.isHandled(keyCode);
|
||||
} else {
|
||||
Key.setHandled(KeyEvent.KEYCODE_BACK, false);
|
||||
}
|
||||
|
||||
return
|
||||
|
|
@ -169,11 +174,11 @@ abstract class KeyPadHandler extends UiHandler {
|
|||
}
|
||||
|
||||
if (Key.isBack(keyCode)) {
|
||||
return onBack() && super.onKeyUp(keyCode, event);
|
||||
return Key.isHandledInSuper(keyCode) ? super.onKeyUp(keyCode, event) : Key.isHandled(keyCode);
|
||||
}
|
||||
|
||||
return
|
||||
(Key.isOK(KeyEvent.KEYCODE_ENTER) && Key.isHandled(keyCode))
|
||||
(Key.isOK(keyCode) && Key.isHandled(KeyEvent.KEYCODE_ENTER))
|
||||
|| handleHotkey(keyCode, false, keyRepeatCounter > 0, false)
|
||||
|| Key.isPoundOrStar(keyCode) && onText(String.valueOf((char) event.getUnicodeChar()), false)
|
||||
|| super.onKeyUp(keyCode, event); // let the system handle the keys we don't care about (usually, the touch "buttons")
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ abstract public class MainViewHandler extends HotkeyHandler {
|
|||
return mInputMode.getTextCase();
|
||||
}
|
||||
|
||||
public boolean isInputLimited() {
|
||||
return inputType.isLimited();
|
||||
}
|
||||
|
||||
public boolean isInputModeABC() {
|
||||
return mInputMode.getClass().equals(ModeABC.class);
|
||||
}
|
||||
|
|
@ -49,6 +53,10 @@ abstract public class MainViewHandler extends HotkeyHandler {
|
|||
return mInputMode.is123() && inputType.isPhoneNumber();
|
||||
}
|
||||
|
||||
public boolean isTextEditingActive() {
|
||||
return mainView != null && mainView.isTextEditingPaletteShown();
|
||||
}
|
||||
|
||||
public boolean isVoiceInputActive() {
|
||||
return voiceInputOps != null && voiceInputOps.isListening();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
package io.github.sspanak.tt9.ime;
|
||||
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||
import io.github.sspanak.tt9.util.Clipboard;
|
||||
import io.github.sspanak.tt9.util.Ternary;
|
||||
|
||||
abstract public class TextEditingHandler extends VoiceHandler {
|
||||
protected boolean isSystemRTL;
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean onStart(InputConnection connection, EditorInfo field) {
|
||||
isSystemRTL = LanguageKind.isRTL(LanguageCollection.getDefault(this));
|
||||
return super.onStart(connection, field);
|
||||
}
|
||||
|
||||
|
||||
protected boolean onNumber(int key, boolean hold, int repeat) {
|
||||
if (!shouldBeOff() && mainView.isTextEditingPaletteShown()) {
|
||||
onCommand(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onNumber(key, hold, repeat);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Ternary onBack() {
|
||||
if (hideTextEditingPalette()) {
|
||||
return Ternary.TRUE;
|
||||
} else {
|
||||
return super.onBack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void onCommand(int key) {
|
||||
switch (key) {
|
||||
case 0:
|
||||
if (!mInputMode.isNumeric()) {
|
||||
textField.setText(" ");
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
textSelection.selectNextChar(!isSystemRTL);
|
||||
break;
|
||||
case 2:
|
||||
textSelection.clear();
|
||||
break;
|
||||
case 3:
|
||||
textSelection.selectNextChar(isSystemRTL);
|
||||
break;
|
||||
case 4:
|
||||
textSelection.selectNextWord(!isSystemRTL);
|
||||
break;
|
||||
case 5:
|
||||
textSelection.selectAll();
|
||||
break;
|
||||
case 6:
|
||||
textSelection.selectNextWord(isSystemRTL);
|
||||
break;
|
||||
case 7:
|
||||
textSelection.cut(textField);
|
||||
break;
|
||||
case 8:
|
||||
textSelection.copy();
|
||||
break;
|
||||
case 9:
|
||||
textSelection.paste(textField);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void showTextEditingPalette() {
|
||||
if (inputType.isLimited() || mainView.isTextEditingPaletteShown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
suggestionOps.cancelDelayedAccept();
|
||||
suggestionOps.acceptIncomplete();
|
||||
mInputMode.reset();
|
||||
stopVoiceInput();
|
||||
|
||||
mainView.showTextEditingPalette();
|
||||
Clipboard.setOnChangeListener(this, this::resetStatus);
|
||||
resetStatus();
|
||||
}
|
||||
|
||||
|
||||
public boolean hideTextEditingPalette() {
|
||||
if (!mainView.isTextEditingPaletteShown()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (settings.isMainLayoutNumpad() || settings.isMainLayoutStealth()) {
|
||||
mainView.hideTextEditingPalette();
|
||||
} else {
|
||||
mainView.showCommandPalette();
|
||||
}
|
||||
|
||||
Clipboard.setOnChangeListener(this, null);
|
||||
resetStatus();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ import io.github.sspanak.tt9.ime.helpers.CursorOps;
|
|||
import io.github.sspanak.tt9.ime.helpers.InputModeValidator;
|
||||
import io.github.sspanak.tt9.ime.helpers.SuggestionOps;
|
||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||
import io.github.sspanak.tt9.ime.helpers.TextSelection;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.ime.modes.ModePredictive;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
|
|
@ -26,10 +27,11 @@ import io.github.sspanak.tt9.util.Text;
|
|||
|
||||
public abstract class TypingHandler extends KeyPadHandler {
|
||||
// internal settings/data
|
||||
@NonNull protected AppHacks appHacks = new AppHacks(null,null, null, null);
|
||||
@NonNull protected AppHacks appHacks = new AppHacks(null,null, null, null, null);
|
||||
protected InputConnection currentInputConnection = null;
|
||||
@NonNull protected InputType inputType = new InputType(null, null);
|
||||
@NonNull protected TextField textField = new TextField(null, null);
|
||||
@NonNull protected TextSelection textSelection = new TextSelection(this,null);
|
||||
protected SuggestionOps suggestionOps;
|
||||
boolean isEnabled = false;
|
||||
|
||||
|
|
@ -94,9 +96,10 @@ public abstract class TypingHandler extends KeyPadHandler {
|
|||
currentInputConnection = connection;
|
||||
inputType = new InputType(currentInputConnection, field);
|
||||
textField = new TextField(currentInputConnection, field);
|
||||
textSelection = new TextSelection(this, currentInputConnection);
|
||||
|
||||
// changing the TextField and notifying all interested classes is an atomic operation
|
||||
appHacks = new AppHacks(settings, connection, inputType, textField);
|
||||
appHacks = new AppHacks(settings, connection, inputType, textField, textSelection);
|
||||
suggestionOps.setTextField(textField);
|
||||
}
|
||||
|
||||
|
|
@ -288,6 +291,7 @@ public abstract class TypingHandler extends KeyPadHandler {
|
|||
// Logger.d("onUpdateSelection", "oldSelStart: " + oldSelStart + " oldSelEnd: " + oldSelEnd + " newSelStart: " + newSelStart + " oldSelEnd: " + oldSelEnd + " candidatesStart: " + candidatesStart + " candidatesEnd: " + candidatesEnd);
|
||||
|
||||
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd);
|
||||
textSelection.onSelectionUpdate(newSelStart, newSelEnd);
|
||||
|
||||
// in case the app has modified the InputField and moved the cursor without notifiying us...
|
||||
if (appHacks.onUpdateSelection(mInputMode, suggestionOps, oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd)) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import io.github.sspanak.tt9.ime.voice.VoiceInputError;
|
|||
import io.github.sspanak.tt9.ime.voice.VoiceInputOps;
|
||||
import io.github.sspanak.tt9.ui.dialogs.RequestPermissionDialog;
|
||||
import io.github.sspanak.tt9.util.Logger;
|
||||
import io.github.sspanak.tt9.util.Ternary;
|
||||
|
||||
abstract class VoiceHandler extends TypingHandler {
|
||||
private final static String LOG_TAG = VoiceHandler.class.getSimpleName();
|
||||
|
|
@ -24,9 +25,9 @@ abstract class VoiceHandler extends TypingHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean onBack() {
|
||||
protected Ternary onBack() {
|
||||
stopVoiceInput();
|
||||
return false; // we don't want to abort other operations, we just silently stop voice input
|
||||
return Ternary.FALSE; // we don't want to abort other operations, we just silently stop voice input
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -5,19 +5,30 @@ import android.view.KeyEvent;
|
|||
import java.util.HashMap;
|
||||
|
||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||
import io.github.sspanak.tt9.util.Ternary;
|
||||
|
||||
public class Key {
|
||||
private static final HashMap<Integer, Boolean> handledKeys = new HashMap<>();
|
||||
private static final HashMap<Integer, Ternary> handledKeys = new HashMap<>();
|
||||
|
||||
|
||||
public static void setHandled(int keyCode, Ternary handled) {
|
||||
handledKeys.put(keyCode, handled);
|
||||
}
|
||||
|
||||
|
||||
public static boolean setHandled(int keyCode, boolean handled) {
|
||||
handledKeys.put(keyCode, handled);
|
||||
handledKeys.put(keyCode, handled ? Ternary.TRUE : Ternary.FALSE);
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isHandled(int keyCode) {
|
||||
return Boolean.TRUE.equals(handledKeys.get(keyCode));
|
||||
return handledKeys.containsKey(keyCode) && handledKeys.get(keyCode) == Ternary.TRUE;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isHandledInSuper(int keyCode) {
|
||||
return handledKeys.containsKey(keyCode) && handledKeys.get(keyCode) == Ternary.ALTERNATIVE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +1,35 @@
|
|||
package io.github.sspanak.tt9.ime.helpers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class OrientationListener extends android.view.OrientationEventListener {
|
||||
private static final short ORIENTATION_LANDSCAPE = 1;
|
||||
private static final short ORIENTATION_UNKNOWN = 0;
|
||||
private static final short ORIENTATION_PORTRAIT = -1;
|
||||
|
||||
private short previousOrientation = ORIENTATION_UNKNOWN;
|
||||
private final Configuration configuration;
|
||||
private final Runnable onChange;
|
||||
|
||||
private int previousOrientation = Configuration.ORIENTATION_UNDEFINED;
|
||||
|
||||
public OrientationListener(@NonNull Context context, @NonNull Runnable onChange) {
|
||||
super(context);
|
||||
configuration = context.getResources().getConfiguration();
|
||||
this.onChange = onChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOrientationChanged(int orientation) {
|
||||
short currentOrientation;
|
||||
|
||||
if (orientation > 345 || orientation < 15 || (orientation > 165 && orientation < 195)) {
|
||||
currentOrientation = ORIENTATION_PORTRAIT;
|
||||
} else if ((orientation > 75 && orientation < 105) || (orientation > 255 && orientation < 285)) {
|
||||
currentOrientation = ORIENTATION_LANDSCAPE;
|
||||
} else {
|
||||
if (
|
||||
(orientation > 15 && orientation < 75)
|
||||
|| (orientation > 105 && orientation < 165)
|
||||
|| (orientation > 195 && orientation < 255)
|
||||
|| (orientation > 285 && orientation < 345)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentOrientation != previousOrientation) {
|
||||
previousOrientation = currentOrientation;
|
||||
if (previousOrientation != configuration.orientation) {
|
||||
previousOrientation = configuration.orientation;
|
||||
onChange.run();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,10 +245,26 @@ public class TextField extends InputField {
|
|||
return false;
|
||||
}
|
||||
|
||||
int keyCode = backward ? KeyEvent.KEYCODE_DPAD_LEFT : KeyEvent.KEYCODE_DPAD_RIGHT;
|
||||
connection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
|
||||
connection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
|
||||
sendDownUpKeyEvents(backward ? KeyEvent.KEYCODE_DPAD_LEFT : KeyEvent.KEYCODE_DPAD_RIGHT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public boolean sendDownUpKeyEvents(int keyCode) {
|
||||
return sendDownUpKeyEvents(keyCode, false, false);
|
||||
}
|
||||
|
||||
|
||||
public boolean sendDownUpKeyEvents(int keyCode, boolean shift, boolean ctrl) {
|
||||
if (connection != null) {
|
||||
int metaState = shift ? KeyEvent.META_SHIFT_ON : 0;
|
||||
metaState |= ctrl ? KeyEvent.META_CTRL_ON : 0;
|
||||
KeyEvent downEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, keyCode, 0, metaState);
|
||||
KeyEvent upEvent = new KeyEvent(0, 0, KeyEvent.ACTION_UP, keyCode, 0, metaState);
|
||||
return connection.sendKeyEvent(downEvent) && connection.sendKeyEvent(upEvent);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,160 @@
|
|||
package io.github.sspanak.tt9.ime.helpers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.inputmethod.ExtractedText;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import io.github.sspanak.tt9.util.Clipboard;
|
||||
|
||||
public class TextSelection {
|
||||
@Nullable private final InputConnection connection;
|
||||
private final Context context;
|
||||
private int currentStart = 0;
|
||||
private int currentEnd = 0;
|
||||
|
||||
|
||||
public TextSelection(Context context, @Nullable InputConnection connection) {
|
||||
this.context = context;
|
||||
this.connection = connection;
|
||||
detectCursorPosition();
|
||||
}
|
||||
|
||||
|
||||
public void onSelectionUpdate(int start, int end) {
|
||||
currentStart = start;
|
||||
currentEnd = end;
|
||||
}
|
||||
|
||||
|
||||
public boolean isEmpty() {
|
||||
return currentStart == currentEnd;
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
if (connection != null) {
|
||||
connection.setSelection(currentEnd, currentEnd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clear(boolean backward) {
|
||||
if (connection != null) {
|
||||
connection.setSelection(
|
||||
backward ? Math.min(currentStart, currentEnd) : Math.max(currentStart, currentEnd),
|
||||
backward ? Math.min(currentStart, currentEnd) : Math.max(currentStart, currentEnd)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void selectAll() {
|
||||
if (connection != null) {
|
||||
connection.performContextMenuAction(android.R.id.selectAll);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void selectNextChar(boolean backward) {
|
||||
if (connection != null) {
|
||||
connection.setSelection(currentStart, currentEnd + (backward ? -1 : 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void selectNextWord(boolean backward) {
|
||||
if (connection == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
connection.setSelection(currentStart, getNextWordPosition(backward));
|
||||
}
|
||||
|
||||
|
||||
public boolean copy() {
|
||||
CharSequence selectedText = getSelectedText();
|
||||
if (selectedText.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Clipboard.copy(context, selectedText);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void cut(@NonNull TextField textField) {
|
||||
if (copy()) {
|
||||
textField.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void paste(@NonNull TextField textField) {
|
||||
String clipboardText = Clipboard.paste(context);
|
||||
if (!clipboardText.isEmpty()) {
|
||||
textField.setText(clipboardText);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int getNextWordPosition(boolean backward) {
|
||||
if (connection == null) {
|
||||
return currentEnd + (backward ? -1 : 1);
|
||||
}
|
||||
|
||||
ExtractedText extractedText = connection.getExtractedText(new ExtractedTextRequest(), 0);
|
||||
if (extractedText == null) {
|
||||
return currentEnd + (backward ? -1 : 1);
|
||||
}
|
||||
|
||||
int increment = backward ? -1 : 1;
|
||||
int textLength = extractedText.text.length();
|
||||
for (int ch = currentEnd + increment; ch >= 0 && ch < textLength; ch += increment) {
|
||||
if (!Character.isWhitespace(extractedText.text.charAt(ch))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch >= currentStart) {
|
||||
return ch;
|
||||
} else if (ch + 1 != currentEnd) {
|
||||
return ch + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return backward ? 0 : textLength;
|
||||
}
|
||||
|
||||
|
||||
private void detectCursorPosition() {
|
||||
if (connection == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ExtractedText extractedText = connection.getExtractedText(new ExtractedTextRequest(), 0);
|
||||
if (extractedText != null) {
|
||||
currentStart = extractedText.startOffset + extractedText.selectionStart;
|
||||
currentEnd = extractedText.startOffset + extractedText.selectionEnd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private CharSequence getSelectedText() {
|
||||
if (connection == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
ExtractedText extractedText = connection.getExtractedText(new ExtractedTextRequest(), 0);
|
||||
if (extractedText == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
int start = Math.min(extractedText.selectionStart, extractedText.selectionEnd);
|
||||
int end = Math.max(extractedText.selectionStart, extractedText.selectionEnd);
|
||||
return extractedText.text.subSequence(start, end);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,5 @@
|
|||
package io.github.sspanak.tt9.preferences.items;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
|
@ -10,6 +7,7 @@ import androidx.preference.Preference;
|
|||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||
import io.github.sspanak.tt9.ui.UI;
|
||||
import io.github.sspanak.tt9.util.Clipboard;
|
||||
|
||||
public class ItemText extends ItemClickable {
|
||||
private final PreferencesActivity activity;
|
||||
|
|
@ -21,16 +19,18 @@ public class ItemText extends ItemClickable {
|
|||
|
||||
@Override
|
||||
protected boolean onClick(Preference p) {
|
||||
if (activity == null) {
|
||||
if (activity == null || p.getSummary() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
String label = activity.getString(R.string.app_name_short) + " / " + item.getTitle();
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label , p.getSummary()));
|
||||
Clipboard.copy(
|
||||
activity,
|
||||
activity.getString(R.string.app_name_short) + " / " + item.getTitle(),
|
||||
p.getSummary()
|
||||
);
|
||||
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
|
||||
UI.toast(activity, "Text copied.");
|
||||
UI.toast(activity, "\"" + Clipboard.getPreview(activity) + "\" copied.");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -43,6 +43,4 @@ public class ItemText extends ItemClickable {
|
|||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ import android.content.Context;
|
|||
public class SettingsStore extends SettingsUI {
|
||||
public SettingsStore(Context context) { super(context); }
|
||||
|
||||
/************* internal settings *************/
|
||||
/************* internal settings *************/
|
||||
public final static int CLIPBOARD_PREVIEW_LENGTH = 20;
|
||||
public final static int DELETE_WORDS_SEARCH_DELAY = 500; // ms
|
||||
public final static int DICTIONARY_AUTO_LOAD_COOLDOWN_TIME = 1200000; // 20 minutes in ms
|
||||
public final static int DICTIONARY_DOWNLOAD_CONNECTION_TIMEOUT = 10000; // ms
|
||||
|
|
|
|||
|
|
@ -77,15 +77,23 @@ abstract class BaseMainLayout {
|
|||
}
|
||||
|
||||
|
||||
int getHeight() {
|
||||
int getHeight(boolean forceRecalculate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resetHeight() {}
|
||||
|
||||
int getHeight() {
|
||||
return getHeight(false);
|
||||
}
|
||||
|
||||
|
||||
abstract void showCommandPalette();
|
||||
abstract void hideCommandPalette();
|
||||
abstract boolean isCommandPaletteShown();
|
||||
abstract void showTextEditingPalette();
|
||||
abstract void hideTextEditingPalette();
|
||||
abstract boolean isTextEditingPaletteShown();
|
||||
|
||||
|
||||
/**
|
||||
* render
|
||||
|
|
|
|||
|
|
@ -15,10 +15,14 @@ import java.util.Arrays;
|
|||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.hacks.DeviceInfo;
|
||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||
import io.github.sspanak.tt9.ui.main.keys.SoftCommandKey;
|
||||
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
|
||||
import io.github.sspanak.tt9.ui.main.keys.SoftKeySettings;
|
||||
import io.github.sspanak.tt9.ui.main.keys.SoftNumberKey;
|
||||
import io.github.sspanak.tt9.ui.main.keys.SoftPunctuationKey;
|
||||
|
||||
class MainLayoutNumpad extends BaseMainLayout {
|
||||
private boolean isTextEditingShown = false;
|
||||
private int height;
|
||||
|
||||
|
||||
|
|
@ -82,6 +86,80 @@ class MainLayoutNumpad extends BaseMainLayout {
|
|||
@Override boolean isCommandPaletteShown() { return false; }
|
||||
|
||||
|
||||
@Override
|
||||
void showTextEditingPalette() {
|
||||
isTextEditingShown = true;
|
||||
|
||||
for (SoftKey key : getKeys()) {
|
||||
int keyId = key.getId();
|
||||
|
||||
if (keyId == R.id.soft_key_0) {
|
||||
key.setEnabled(tt9 != null && !tt9.isInputModeNumeric());
|
||||
} else if (key.getClass().equals(SoftNumberKey.class)) {
|
||||
key.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (key.getClass().equals(SoftPunctuationKey.class)) {
|
||||
key.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if (key.getClass().equals(SoftCommandKey.class)) {
|
||||
key.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (keyId == R.id.soft_key_rf3) {
|
||||
key.render();
|
||||
}
|
||||
|
||||
if (
|
||||
keyId == R.id.soft_key_add_word
|
||||
|| keyId == R.id.soft_key_input_mode
|
||||
|| keyId == R.id.soft_key_language
|
||||
|| keyId == R.id.soft_key_filter_suggestions
|
||||
) {
|
||||
key.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void hideTextEditingPalette() {
|
||||
isTextEditingShown = false;
|
||||
|
||||
for (SoftKey key : getKeys()) {
|
||||
if (key.getClass().equals(SoftNumberKey.class) || key.getClass().equals(SoftPunctuationKey.class)) {
|
||||
key.setVisibility(View.VISIBLE);
|
||||
key.setEnabled(true);
|
||||
}
|
||||
|
||||
if (key.getClass().equals(SoftCommandKey.class)) {
|
||||
key.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
int keyId = key.getId();
|
||||
|
||||
if (keyId == R.id.soft_key_rf3) {
|
||||
key.render();
|
||||
}
|
||||
|
||||
if (
|
||||
keyId == R.id.soft_key_add_word
|
||||
|| keyId == R.id.soft_key_input_mode
|
||||
|| keyId == R.id.soft_key_language
|
||||
|| keyId == R.id.soft_key_filter_suggestions
|
||||
) {
|
||||
key.setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isTextEditingPaletteShown() {
|
||||
return isTextEditingShown;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Uses the key height from the settings, but if it takes up too much of the screen, it will
|
||||
* be adjusted so that the entire Main View would take up around 50% of the screen in landscape mode
|
||||
|
|
@ -120,8 +198,8 @@ class MainLayoutNumpad extends BaseMainLayout {
|
|||
}
|
||||
|
||||
|
||||
int getHeight() {
|
||||
if (height <= 0) {
|
||||
int getHeight(boolean forceRecalculate) {
|
||||
if (height <= 0 || forceRecalculate) {
|
||||
Resources resources = tt9.getResources();
|
||||
height = getKeyHeightCompat() * 4
|
||||
+ resources.getDimensionPixelSize(R.dimen.numpad_candidate_height)
|
||||
|
|
@ -132,11 +210,6 @@ class MainLayoutNumpad extends BaseMainLayout {
|
|||
}
|
||||
|
||||
|
||||
void resetHeight() {
|
||||
height = 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void render() {
|
||||
getView();
|
||||
|
|
@ -178,8 +251,7 @@ class MainLayoutNumpad extends BaseMainLayout {
|
|||
}
|
||||
}
|
||||
|
||||
ViewGroup statusBarContainer = view.findViewById(R.id.status_bar_container);
|
||||
keys.addAll(getKeysFromContainer(statusBarContainer));
|
||||
keys.addAll(getKeysFromContainer(view.findViewById(R.id.status_bar_container)));
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package io.github.sspanak.tt9.ui.main;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
|
|
@ -14,19 +13,20 @@ import io.github.sspanak.tt9.ui.main.keys.SoftKey;
|
|||
import io.github.sspanak.tt9.ui.main.keys.SoftKeyCommandPalette;
|
||||
|
||||
class MainLayoutSmall extends MainLayoutTray {
|
||||
private int height;
|
||||
|
||||
MainLayoutSmall(TraditionalT9 tt9) {
|
||||
super(tt9);
|
||||
}
|
||||
|
||||
int getHeight() {
|
||||
if (height <= 0) {
|
||||
Resources resources = tt9.getResources();
|
||||
height =
|
||||
resources.getDimensionPixelSize(R.dimen.soft_key_height) +
|
||||
resources.getDimensionPixelSize(R.dimen.candidate_height);
|
||||
@Override
|
||||
int getHeight(boolean forceRecalculate) {
|
||||
if (height <= 0 || forceRecalculate) {
|
||||
height = super.getHeight(forceRecalculate);
|
||||
|
||||
if (!isCommandPaletteShown() && !isTextEditingPaletteShown()) {
|
||||
height += tt9.getResources().getDimensionPixelSize(R.dimen.soft_key_height);
|
||||
}
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,11 +5,23 @@ import io.github.sspanak.tt9.ime.TraditionalT9;
|
|||
|
||||
class MainLayoutStealth extends BaseMainLayout {
|
||||
private boolean isCommandPaletteShown = false;
|
||||
private boolean isTextEditingPaletteShown = false;
|
||||
|
||||
MainLayoutStealth(TraditionalT9 tt9) { super(tt9, R.layout.main_stealth); }
|
||||
|
||||
@Override void showCommandPalette() { isCommandPaletteShown = true; }
|
||||
@Override void showCommandPalette() {
|
||||
isCommandPaletteShown = true;
|
||||
isTextEditingPaletteShown = false;
|
||||
}
|
||||
@Override void hideCommandPalette() { isCommandPaletteShown = false; }
|
||||
@Override boolean isCommandPaletteShown() { return isCommandPaletteShown; }
|
||||
|
||||
@Override void showTextEditingPalette() {
|
||||
isTextEditingPaletteShown = true;
|
||||
isCommandPaletteShown = false;
|
||||
}
|
||||
@Override void hideTextEditingPalette() { isTextEditingPaletteShown = false; }
|
||||
@Override boolean isTextEditingPaletteShown() { return isTextEditingPaletteShown; }
|
||||
|
||||
@Override void render() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,17 +16,22 @@ import io.github.sspanak.tt9.ime.TraditionalT9;
|
|||
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
|
||||
|
||||
class MainLayoutTray extends BaseMainLayout {
|
||||
private int height;
|
||||
protected int height;
|
||||
|
||||
MainLayoutTray(TraditionalT9 tt9) {
|
||||
super(tt9, R.layout.main_small);
|
||||
}
|
||||
|
||||
int getHeight() {
|
||||
if (height <= 0) {
|
||||
int getHeight(boolean forceRecalculate) {
|
||||
if (height <= 0 || forceRecalculate) {
|
||||
Resources resources = tt9.getResources();
|
||||
height = resources.getDimensionPixelSize(R.dimen.candidate_height);
|
||||
|
||||
if (isCommandPaletteShown() || isTextEditingPaletteShown()) {
|
||||
height += resources.getDimensionPixelSize(R.dimen.numpad_key_height);
|
||||
}
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
|
|
@ -37,16 +42,46 @@ class MainLayoutTray extends BaseMainLayout {
|
|||
}
|
||||
|
||||
void showCommandPalette() {
|
||||
view.findViewById(R.id.main_command_keys).setVisibility(LinearLayout.VISIBLE);
|
||||
view.findViewById(R.id.text_editing_container).setVisibility(LinearLayout.GONE);
|
||||
view.findViewById(R.id.main_soft_keys).setVisibility(LinearLayout.GONE);
|
||||
view.findViewById(R.id.main_command_keys).setVisibility(LinearLayout.VISIBLE);
|
||||
|
||||
height = 0;
|
||||
getHeight();
|
||||
}
|
||||
|
||||
void hideCommandPalette() {
|
||||
view.findViewById(R.id.main_command_keys).setVisibility(LinearLayout.GONE);
|
||||
|
||||
height = 0;
|
||||
getHeight();
|
||||
}
|
||||
|
||||
boolean isCommandPaletteShown() {
|
||||
return view.findViewById(R.id.main_command_keys).getVisibility() == LinearLayout.VISIBLE;
|
||||
return view != null && view.findViewById(R.id.main_command_keys).getVisibility() == LinearLayout.VISIBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
void showTextEditingPalette() {
|
||||
view.findViewById(R.id.main_command_keys).setVisibility(LinearLayout.GONE);
|
||||
view.findViewById(R.id.main_soft_keys).setVisibility(LinearLayout.GONE);
|
||||
view.findViewById(R.id.text_editing_container).setVisibility(LinearLayout.VISIBLE);
|
||||
|
||||
height = 0;
|
||||
getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
void hideTextEditingPalette() {
|
||||
view.findViewById(R.id.text_editing_container).setVisibility(LinearLayout.GONE);
|
||||
|
||||
height = 0;
|
||||
getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isTextEditingPaletteShown() {
|
||||
return view != null && view.findViewById(R.id.text_editing_container).getVisibility() == LinearLayout.VISIBLE;
|
||||
}
|
||||
|
||||
protected Drawable getBackgroundColor(@NonNull View contextView, boolean dark) {
|
||||
|
|
@ -71,6 +106,7 @@ class MainLayoutTray extends BaseMainLayout {
|
|||
|
||||
// background
|
||||
view.findViewById(R.id.main_command_keys).setBackground(getBackgroundColor(view, dark));
|
||||
view.findViewById(R.id.text_editing_container).setBackground(getBackgroundColor(view, dark));
|
||||
|
||||
// text
|
||||
for (SoftKey key : getKeys()) {
|
||||
|
|
@ -100,6 +136,7 @@ class MainLayoutTray extends BaseMainLayout {
|
|||
protected ArrayList<SoftKey> getKeys() {
|
||||
if (view != null && keys.isEmpty()) {
|
||||
keys.addAll(getKeysFromContainer(view.findViewById(R.id.main_command_keys)));
|
||||
keys.addAll(getKeysFromContainer(view.findViewById(R.id.text_editing_keys_small)));
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
|
@ -108,9 +145,19 @@ class MainLayoutTray extends BaseMainLayout {
|
|||
return new ArrayList<>(Arrays.asList(
|
||||
view.findViewById(R.id.separator_top),
|
||||
view.findViewById(R.id.separator_candidates_bottom),
|
||||
view.findViewById(R.id.separator_1_1),
|
||||
view.findViewById(R.id.separator_1_2),
|
||||
view.findViewById(R.id.separator_2_1),
|
||||
view.findViewById(R.id.separator_2_2),
|
||||
view.findViewById(R.id.separator_3_1)
|
||||
view.findViewById(R.id.separator_10_1),
|
||||
view.findViewById(R.id.separator_10_2),
|
||||
view.findViewById(R.id.separator_10_2),
|
||||
view.findViewById(R.id.separator_10_3),
|
||||
view.findViewById(R.id.separator_10_4),
|
||||
view.findViewById(R.id.separator_10_5),
|
||||
view.findViewById(R.id.separator_10_6),
|
||||
view.findViewById(R.id.separator_10_7),
|
||||
view.findViewById(R.id.separator_10_8)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ public class MainView {
|
|||
}
|
||||
|
||||
public void render() {
|
||||
main.hideCommandPalette();
|
||||
main.hideTextEditingPalette();
|
||||
main.render();
|
||||
}
|
||||
|
||||
|
|
@ -72,4 +74,20 @@ public class MainView {
|
|||
public boolean isCommandPaletteShown() {
|
||||
return main != null && main.isCommandPaletteShown();
|
||||
}
|
||||
|
||||
public void showTextEditingPalette() {
|
||||
if (main != null) {
|
||||
main.showTextEditingPalette();
|
||||
}
|
||||
}
|
||||
|
||||
public void hideTextEditingPalette() {
|
||||
if (main != null) {
|
||||
main.hideTextEditingPalette();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTextEditingPaletteShown() {
|
||||
return main != null && main.isTextEditingPaletteShown();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha
|
|||
|
||||
public ResizableMainView(TraditionalT9 tt9) {
|
||||
super(tt9);
|
||||
resetHeight();
|
||||
calculateSnapHeights();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -35,27 +35,9 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha
|
|||
}
|
||||
|
||||
|
||||
private void calculateInitialHeight() {
|
||||
if (main == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tt9.getSettings().isMainLayoutNumpad()) {
|
||||
height = heightNumpad;
|
||||
} else if (tt9.getSettings().isMainLayoutSmall()) {
|
||||
height = heightSmall;
|
||||
} else {
|
||||
height = heightTray;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean createInputView() {
|
||||
|
||||
if (!super.createInputView()) {
|
||||
// recalculate the total height in case the user has changed the key height in the settings
|
||||
resetHeight();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -79,8 +61,6 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha
|
|||
|
||||
|
||||
public void onOrientationChanged() {
|
||||
calculateSnapHeights();
|
||||
calculateInitialHeight();
|
||||
hideCommandPalette();
|
||||
render();
|
||||
}
|
||||
|
|
@ -211,14 +191,51 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha
|
|||
return true;
|
||||
}
|
||||
|
||||
private void fitMain() {
|
||||
calculateSnapHeights();
|
||||
int heightLow, heightHigh, heightMain = main.getHeight(true);
|
||||
|
||||
private void resetHeight() {
|
||||
if (main != null) {
|
||||
main.resetHeight();
|
||||
if (main instanceof MainLayoutNumpad) {
|
||||
heightLow = heightSmall;
|
||||
heightHigh = heightNumpad;
|
||||
} else if (main instanceof MainLayoutSmall) {
|
||||
heightLow = 0;
|
||||
heightHigh = Math.max(heightSmall, heightMain); // make room for the command palette
|
||||
} else {
|
||||
heightLow = 0;
|
||||
heightHigh = Math.max(heightTray, heightMain); // make room for the command palette
|
||||
}
|
||||
|
||||
calculateSnapHeights();
|
||||
calculateInitialHeight();
|
||||
setHeight(height, heightSmall, heightNumpad);
|
||||
setHeight(heightMain, heightLow, heightHigh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCommandPalette() {
|
||||
super.showCommandPalette();
|
||||
fitMain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideCommandPalette() {
|
||||
super.hideCommandPalette();
|
||||
fitMain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTextEditingPalette() {
|
||||
super.showTextEditingPalette();
|
||||
fitMain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideTextEditingPalette() {
|
||||
super.hideTextEditingPalette();
|
||||
fitMain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
super.render();
|
||||
fitMain();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
package io.github.sspanak.tt9.ui.main.keys;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
import androidx.core.widget.TextViewCompat;
|
||||
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||
import io.github.sspanak.tt9.util.Characters;
|
||||
|
|
@ -12,46 +18,73 @@ public class SoftCommandKey extends SoftNumberKey {
|
|||
public SoftCommandKey(Context context, AttributeSet attrs) { super(context, attrs);}
|
||||
public SoftCommandKey(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);}
|
||||
|
||||
|
||||
@Override protected void handleHold() {}
|
||||
|
||||
|
||||
@Override
|
||||
public void setDarkTheme(boolean darkEnabled) {
|
||||
super.setDarkTheme(darkEnabled);
|
||||
|
||||
final int color = darkEnabled ? R.color.dark_button_text : R.color.button_text;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
TextViewCompat.setCompoundDrawableTintList(this, ColorStateList.valueOf(getContext().getColor(color)));
|
||||
} else {
|
||||
setDarkThemeLegacy(color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setDarkThemeLegacy(int color) {
|
||||
Drawable[] icons = getCompoundDrawables();
|
||||
|
||||
if (icons.length >= 4 && icons[3] != null) {
|
||||
Drawable icon = DrawableCompat.wrap(icons[3]);
|
||||
DrawableCompat.setTint(icon, getResources().getColor(color));
|
||||
setCompoundDrawables(null, null, null, icon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected String getTextSubTitle(int resId) {
|
||||
setTextSize(SettingsStore.SOFT_KEY_TITLE_SIZE);
|
||||
return getContext().getString(resId);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return getNumber(getId()) + "";
|
||||
}
|
||||
|
||||
private String getTextSubTitle(int resId) {
|
||||
setTextSize(SettingsStore.SOFT_KEY_TITLE_SIZE);
|
||||
return getContext().getString(resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubTitle() {
|
||||
int number = getNumber(getId());
|
||||
|
||||
boolean noIconSupport = Characters.noEmojiSupported();
|
||||
int keyId = getId();
|
||||
|
||||
switch (number) {
|
||||
case 0:
|
||||
return noIconSupport ? getTextSubTitle(R.string.virtual_key_change_keyboard) : "⌨";
|
||||
case 1:
|
||||
return noIconSupport ? getTextSubTitle(R.string.virtual_key_settings) : "⚙";
|
||||
case 2:
|
||||
return "+";
|
||||
case 3:
|
||||
return "🎤";
|
||||
// case 5:
|
||||
// return "✂";
|
||||
}
|
||||
// command palette
|
||||
if (keyId == R.id.soft_key_1) return noIconSupport ? getTextSubTitle(R.string.virtual_key_settings) : "⚙";
|
||||
if (keyId == R.id.soft_key_2) return "+";
|
||||
if (keyId == R.id.soft_key_8) return noIconSupport ? getTextSubTitle(R.string.virtual_key_change_keyboard) : "⌨";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
if (tt9 != null && tt9.isVoiceInputMissing() && getNumber(getId()) == 3) {
|
||||
setVisibility(GONE);
|
||||
} else {
|
||||
super.render();
|
||||
}
|
||||
protected int getNumber(int keyId) {
|
||||
if (keyId == R.id.soft_key_101) return 1;
|
||||
if (keyId == R.id.soft_key_102) return 2;
|
||||
if (keyId == R.id.soft_key_103) return 3;
|
||||
if (keyId == R.id.soft_key_104) return 4;
|
||||
if (keyId == R.id.soft_key_105) return 5;
|
||||
if (keyId == R.id.soft_key_106) return 6;
|
||||
if (keyId == R.id.soft_key_107) return 7;
|
||||
if (keyId == R.id.soft_key_108) return 8;
|
||||
if (keyId == R.id.soft_key_109) return 9;
|
||||
|
||||
return super.getNumber(keyId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,13 +155,6 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
|||
|
||||
|
||||
protected boolean handleRelease() {
|
||||
if (!validateTT9Handler()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int keyId = getId();
|
||||
if (keyId == R.id.soft_key_voice_input) { tt9.toggleVoiceInput(); return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package io.github.sspanak.tt9.ui.main.keys;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class SoftKeyF3 extends SoftCommandKey {
|
||||
public SoftKeyF3(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SoftKeyF3(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SoftKeyF3(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubTitle() {
|
||||
return "🎤";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
setVisibility(tt9 != null && tt9.isVoiceInputMissing() ? GONE : VISIBLE);
|
||||
super.render();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package io.github.sspanak.tt9.ui.main.keys;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.util.Characters;
|
||||
|
||||
public class SoftKeyF5 extends SoftCommandKey {
|
||||
public SoftKeyF5(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SoftKeyF5(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SoftKeyF5(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubTitle() {
|
||||
return Characters.noEmojiSupported() ? getTextSubTitle(R.string.virtual_key_text_editing) : "✂";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
setVisibility(tt9 != null && tt9.isInputLimited() ? GONE : VISIBLE);
|
||||
super.render();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package io.github.sspanak.tt9.ui.main.keys;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||
|
||||
public class SoftKeyRF3 extends SoftKey {
|
||||
public SoftKeyRF3(Context context) { super(context); setFontSize(); }
|
||||
public SoftKeyRF3(Context context, AttributeSet attrs) { super(context, attrs); setFontSize(); }
|
||||
public SoftKeyRF3(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setFontSize(); }
|
||||
|
||||
private void setFontSize() {
|
||||
complexLabelTitleSize = SettingsStore.SOFT_KEY_COMPLEX_LABEL_TITLE_RELATIVE_SIZE / 0.85f;
|
||||
complexLabelSubTitleSize = SettingsStore.SOFT_KEY_COMPLEX_LABEL_SUB_TITLE_RELATIVE_SIZE / 0.85f;
|
||||
}
|
||||
|
||||
private boolean isVoiceInputMissing() {
|
||||
return tt9 != null && tt9.isVoiceInputMissing();
|
||||
}
|
||||
|
||||
private boolean isTextEditingMissing() {
|
||||
return tt9 != null && tt9.isInputLimited();
|
||||
}
|
||||
|
||||
private boolean isTextEdtingActive() {
|
||||
return tt9 != null && tt9.isTextEditingActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleHold() {
|
||||
if (!validateTT9Handler() || isTextEdtingActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
preventRepeat();
|
||||
|
||||
if (tt9.isVoiceInputActive()) {
|
||||
tt9.toggleVoiceInput();
|
||||
} else {
|
||||
tt9.showTextEditingPalette();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean handleRelease() {
|
||||
if (!validateTT9Handler()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isTextEdtingActive()) {
|
||||
tt9.hideTextEditingPalette();
|
||||
} else {
|
||||
tt9.toggleVoiceInput();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
if (isTextEdtingActive()) {
|
||||
if (tt9 == null) {
|
||||
return "ABC";
|
||||
} else if (tt9.isInputModeNumeric()) {
|
||||
return "123";
|
||||
} else if (tt9.getLanguage() != null) {
|
||||
return tt9.getLanguage().getAbcString().toUpperCase(tt9.getLanguage().getLocale());
|
||||
}
|
||||
}
|
||||
|
||||
return isTextEditingMissing() && !isVoiceInputMissing() ? "🎤" : getContext().getString(R.string.virtual_key_text_editing).toUpperCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubTitle() {
|
||||
return isTextEdtingActive() || (!isVoiceInputMissing() && isTextEditingMissing()) ? null : "🎤";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
if (isVoiceInputMissing() && isTextEditingMissing()) {
|
||||
setVisibility(INVISIBLE);
|
||||
} else {
|
||||
super.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package io.github.sspanak.tt9.ui.main.keys;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
import androidx.core.widget.TextViewCompat;
|
||||
|
||||
import io.github.sspanak.tt9.R;
|
||||
|
||||
public class SoftKeyTextEdit extends SoftNumberKey {
|
||||
public SoftKeyTextEdit(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SoftKeyTextEdit(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SoftKeyTextEdit(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDarkTheme(boolean darkEnabled) {
|
||||
super.setDarkTheme(darkEnabled);
|
||||
|
||||
final int color = darkEnabled ? R.color.dark_button_text : R.color.button_text;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
TextViewCompat.setCompoundDrawableTintList(this, ColorStateList.valueOf(getContext().getColor(color)));
|
||||
} else {
|
||||
setDarkThemeLegacy(color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setDarkThemeLegacy(int color) {
|
||||
Drawable[] icons = getCompoundDrawables();
|
||||
|
||||
if (icons.length >= 4 && icons[3] != null) {
|
||||
Drawable icon = DrawableCompat.wrap(icons[3]);
|
||||
DrawableCompat.setTint(icon, getResources().getColor(color));
|
||||
setCompoundDrawables(null, null, null, icon);
|
||||
}
|
||||
}
|
||||
|
||||
private Drawable getIcon(int resId) {
|
||||
return getResources().getDrawable(resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubTitle() {
|
||||
return super.getSubTitle();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package io.github.sspanak.tt9.ui.main.keys;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class SoftVoiceInputKey extends SoftKey {
|
||||
public SoftVoiceInputKey(Context context) { super(context); }
|
||||
public SoftVoiceInputKey(Context context, AttributeSet attrs) { super(context, attrs); }
|
||||
public SoftVoiceInputKey(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return "🎤";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
if (tt9 != null && tt9.isVoiceInputMissing()) {
|
||||
setVisibility(INVISIBLE);
|
||||
} else {
|
||||
super.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
75
app/src/main/java/io/github/sspanak/tt9/util/Clipboard.java
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package io.github.sspanak.tt9.util;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||
|
||||
public class Clipboard {
|
||||
private static Runnable externalChangeListener;
|
||||
private static boolean ignoreNextChange = false;
|
||||
|
||||
@NonNull private static CharSequence lastText = "";
|
||||
|
||||
public static void copy(@NonNull Context context, @NonNull CharSequence label, @NonNull CharSequence text) {
|
||||
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, text));
|
||||
|
||||
// Android clipboard works unreliably on all versions from 5 to 14, even when invoked from
|
||||
// the context menu. So, just in case, we keep a backup of the text.
|
||||
lastText = text;
|
||||
|
||||
ignoreNextChange = true;
|
||||
}
|
||||
|
||||
public static void copy(@NonNull Context context, @NonNull CharSequence text) {
|
||||
String label = context.getString(R.string.app_name_short) + " / text";
|
||||
copy(context, label, text);
|
||||
}
|
||||
|
||||
@NonNull public static String paste(@NonNull Context context) {
|
||||
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = clipboard.getPrimaryClip();
|
||||
|
||||
// Try using the shared clipboard, but if Android has failed preserving it, use our backup.
|
||||
CharSequence text = clip != null && clip.getItemCount() > 0 ? clip.getItemAt(0).getText() : "";
|
||||
text = text == null || text.length() == 0 ? lastText : text;
|
||||
|
||||
return text.toString();
|
||||
}
|
||||
|
||||
|
||||
@NonNull public static String getPreview(@NonNull Context context) {
|
||||
String text = paste(context);
|
||||
|
||||
if (text.length() > SettingsStore.CLIPBOARD_PREVIEW_LENGTH) {
|
||||
return text.substring(0, SettingsStore.CLIPBOARD_PREVIEW_LENGTH) + "...";
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public static void setOnChangeListener(Context context, Runnable newListener) {
|
||||
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
|
||||
if (newListener != null) {
|
||||
clipboard.addPrimaryClipChangedListener(Clipboard::changeListener);
|
||||
} else if (externalChangeListener != null) {
|
||||
clipboard.removePrimaryClipChangedListener(Clipboard::changeListener);
|
||||
}
|
||||
|
||||
externalChangeListener = newListener;
|
||||
}
|
||||
|
||||
private static void changeListener() {
|
||||
if (ignoreNextChange) {
|
||||
ignoreNextChange = false;
|
||||
} else if (externalChangeListener != null) {
|
||||
externalChangeListener.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package io.github.sspanak.tt9.util;
|
||||
|
||||
public enum Ternary {
|
||||
FALSE,
|
||||
TRUE,
|
||||
ALTERNATIVE
|
||||
}
|
||||
16
app/src/main/res/drawable-anydpi-v24/ic_dpad_left.xml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF"
|
||||
android:autoMirrored="true">
|
||||
<group android:scaleX="2.208"
|
||||
android:scaleY="2.208"
|
||||
android:translateX="-13.392"
|
||||
android:translateY="-14.496">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M14,7l-5,5 5,5V7z"/>
|
||||
</group>
|
||||
</vector>
|
||||
16
app/src/main/res/drawable-anydpi-v24/ic_dpad_right.xml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF"
|
||||
android:autoMirrored="true">
|
||||
<group android:scaleX="2.208"
|
||||
android:scaleY="2.208"
|
||||
android:translateX="-15.6"
|
||||
android:translateY="-14.496">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M10,17l5,-5 -5,-5v10z"/>
|
||||
</group>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable-anydpi-v24/ic_txt_copy.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF">
|
||||
<group android:scaleX="1.0036364"
|
||||
android:scaleY="1.0036364"
|
||||
android:translateX="0.45818183"
|
||||
android:translateY="-0.043636363">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
|
||||
</group>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable-anydpi-v24/ic_txt_cut.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF">
|
||||
<group android:scaleX="1.104"
|
||||
android:scaleY="1.104"
|
||||
android:translateX="-1.248"
|
||||
android:translateY="-1.248">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M9.64,7.64c0.23,-0.5 0.36,-1.05 0.36,-1.64 0,-2.21 -1.79,-4 -4,-4S2,3.79 2,6s1.79,4 4,4c0.59,0 1.14,-0.13 1.64,-0.36L10,12l-2.36,2.36C7.14,14.13 6.59,14 6,14c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4c0,-0.59 -0.13,-1.14 -0.36,-1.64L12,14l7,7h3v-1L9.64,7.64zM6,8c-1.1,0 -2,-0.89 -2,-2s0.9,-2 2,-2 2,0.89 2,2 -0.9,2 -2,2zM6,20c-1.1,0 -2,-0.89 -2,-2s0.9,-2 2,-2 2,0.89 2,2 -0.9,2 -2,2zM12,12.5c-0.28,0 -0.5,-0.22 -0.5,-0.5s0.22,-0.5 0.5,-0.5 0.5,0.22 0.5,0.5 -0.22,0.5 -0.5,0.5zM19,3l-6,6 2,2 7,-7L22,3z"/>
|
||||
</group>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable-anydpi-v24/ic_txt_paste.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF">
|
||||
<group android:scaleX="1.0036364"
|
||||
android:scaleY="1.0036364"
|
||||
android:translateX="-0.043636363"
|
||||
android:translateY="0.96">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,2h-4.18C14.4,0.84 13.3,0 12,0c-1.3,0 -2.4,0.84 -2.82,2L5,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,4c0,-1.1 -0.9,-2 -2,-2zM12,2c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM19,20L5,20L5,4h2v3h10L17,4h2v16z"/>
|
||||
</group>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable-anydpi-v24/ic_txt_select_all.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF">
|
||||
<group android:scaleX="1.2266667"
|
||||
android:scaleY="1.2266667"
|
||||
android:translateX="-2.72"
|
||||
android:translateY="-2.72">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3,5h2L5,3c-1.1,0 -2,0.9 -2,2zM3,13h2v-2L3,11v2zM7,21h2v-2L7,19v2zM3,9h2L5,7L3,7v2zM13,3h-2v2h2L13,3zM19,3v2h2c0,-1.1 -0.9,-2 -2,-2zM5,21v-2L3,19c0,1.1 0.9,2 2,2zM3,17h2v-2L3,15v2zM9,3L7,3v2h2L9,3zM11,21h2v-2h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0 2,-0.9 2,-2h-2v2zM19,9h2L21,7h-2v2zM19,17h2v-2h-2v2zM15,21h2v-2h-2v2zM15,5h2L17,3h-2v2zM7,17h10L17,7L7,7v10zM9,9h6v6L9,15L9,9z"/>
|
||||
</group>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable-anydpi-v24/ic_txt_select_none.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF">
|
||||
<group android:scaleX="1.0514286"
|
||||
android:scaleY="1.0514286"
|
||||
android:translateX="-0.09142857"
|
||||
android:translateY="-1.1428572">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3,13h2v-2H3V13zM7,21h2v-2H7V21zM13,3h-2v2h2V3zM19,3v2h2C21,3.9 20.1,3 19,3zM5,21v-2H3C3,20.1 3.9,21 5,21zM3,17h2v-2H3V17zM11,21h2v-2h-2V21zM19,13h2v-2h-2V13zM19,9h2V7h-2V9zM15,5h2V3h-2V5zM7.83,5L7,4.17V3h2v2H7.83zM19.83,17L19,16.17V15h2v2H19.83zM21.19,21.19L2.81,2.81L1.39,4.22L4.17,7H3v2h2V7.83l2,2V17h7.17l2,2H15v2h2v-1.17l2.78,2.78L21.19,21.19zM9,15v-3.17L12.17,15H9zM15,12.17V9h-3.17l-2,-2H17v7.17L15,12.17z"/>
|
||||
</group>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable-anydpi-v24/ic_txt_word_back.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF">
|
||||
<group android:scaleX="1.2266667"
|
||||
android:scaleY="1.2266667"
|
||||
android:translateX="-1.4933333"
|
||||
android:translateY="-2.72">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
|
||||
</group>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable-anydpi-v24/ic_txt_word_forward.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFF">
|
||||
<group android:scaleX="1.2266667"
|
||||
android:scaleY="1.2266667"
|
||||
android:translateX="-3.9466667"
|
||||
android:translateY="-2.72">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
|
||||
</group>
|
||||
</vector>
|
||||
BIN
app/src/main/res/drawable-hdpi/ic_dpad_left.png
Normal file
|
After Width: | Height: | Size: 282 B |
BIN
app/src/main/res/drawable-hdpi/ic_dpad_right.png
Normal file
|
After Width: | Height: | Size: 270 B |
BIN
app/src/main/res/drawable-hdpi/ic_txt_copy.png
Normal file
|
After Width: | Height: | Size: 324 B |
BIN
app/src/main/res/drawable-hdpi/ic_txt_cut.png
Normal file
|
After Width: | Height: | Size: 613 B |
BIN
app/src/main/res/drawable-hdpi/ic_txt_paste.png
Normal file
|
After Width: | Height: | Size: 351 B |
BIN
app/src/main/res/drawable-hdpi/ic_txt_select_all.png
Normal file
|
After Width: | Height: | Size: 456 B |
BIN
app/src/main/res/drawable-hdpi/ic_txt_select_none.png
Normal file
|
After Width: | Height: | Size: 568 B |
BIN
app/src/main/res/drawable-hdpi/ic_txt_word_back.png
Normal file
|
After Width: | Height: | Size: 407 B |
BIN
app/src/main/res/drawable-hdpi/ic_txt_word_forward.png
Normal file
|
After Width: | Height: | Size: 425 B |
BIN
app/src/main/res/drawable-mdpi/ic_dpad_left.png
Normal file
|
After Width: | Height: | Size: 211 B |
BIN
app/src/main/res/drawable-mdpi/ic_dpad_right.png
Normal file
|
After Width: | Height: | Size: 218 B |
BIN
app/src/main/res/drawable-mdpi/ic_txt_copy.png
Normal file
|
After Width: | Height: | Size: 224 B |
BIN
app/src/main/res/drawable-mdpi/ic_txt_cut.png
Normal file
|
After Width: | Height: | Size: 401 B |
BIN
app/src/main/res/drawable-mdpi/ic_txt_paste.png
Normal file
|
After Width: | Height: | Size: 221 B |
BIN
app/src/main/res/drawable-mdpi/ic_txt_select_all.png
Normal file
|
After Width: | Height: | Size: 339 B |
BIN
app/src/main/res/drawable-mdpi/ic_txt_select_none.png
Normal file
|
After Width: | Height: | Size: 493 B |
BIN
app/src/main/res/drawable-mdpi/ic_txt_word_back.png
Normal file
|
After Width: | Height: | Size: 313 B |
BIN
app/src/main/res/drawable-mdpi/ic_txt_word_forward.png
Normal file
|
After Width: | Height: | Size: 288 B |
BIN
app/src/main/res/drawable-xhdpi/ic_dpad_left.png
Normal file
|
After Width: | Height: | Size: 333 B |
BIN
app/src/main/res/drawable-xhdpi/ic_dpad_right.png
Normal file
|
After Width: | Height: | Size: 320 B |
BIN
app/src/main/res/drawable-xhdpi/ic_txt_copy.png
Normal file
|
After Width: | Height: | Size: 401 B |
BIN
app/src/main/res/drawable-xhdpi/ic_txt_cut.png
Normal file
|
After Width: | Height: | Size: 809 B |
BIN
app/src/main/res/drawable-xhdpi/ic_txt_paste.png
Normal file
|
After Width: | Height: | Size: 440 B |
BIN
app/src/main/res/drawable-xhdpi/ic_txt_select_all.png
Normal file
|
After Width: | Height: | Size: 549 B |
BIN
app/src/main/res/drawable-xhdpi/ic_txt_select_none.png
Normal file
|
After Width: | Height: | Size: 735 B |
BIN
app/src/main/res/drawable-xhdpi/ic_txt_word_back.png
Normal file
|
After Width: | Height: | Size: 532 B |
BIN
app/src/main/res/drawable-xhdpi/ic_txt_word_forward.png
Normal file
|
After Width: | Height: | Size: 475 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_dpad_left.png
Normal file
|
After Width: | Height: | Size: 444 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_dpad_right.png
Normal file
|
After Width: | Height: | Size: 443 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_txt_copy.png
Normal file
|
After Width: | Height: | Size: 654 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_txt_cut.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_txt_paste.png
Normal file
|
After Width: | Height: | Size: 679 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_txt_select_all.png
Normal file
|
After Width: | Height: | Size: 853 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_txt_select_none.png
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_txt_word_back.png
Normal file
|
After Width: | Height: | Size: 785 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_txt_word_forward.png
Normal file
|
After Width: | Height: | Size: 812 B |
|
|
@ -86,248 +86,10 @@
|
|||
android:id="@+id/separator_candidates_bottom"
|
||||
style="@style/numRowSeparator" />
|
||||
|
||||
<!-- Keypad Wrapper -->
|
||||
<LinearLayout
|
||||
<include
|
||||
layout="@layout/panel_numpad"
|
||||
android:id="@+id/main_soft_keys"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/numpad_padding_bottom">
|
||||
|
||||
<!-- Row 1 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layoutDirection="ltr"
|
||||
tools:ignore="HardcodedText,KeyboardInaccessibleWidget">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeySettings
|
||||
android:id="@+id/soft_key_settings"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:text="⚙"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_1_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<!-- Digits 1-3 -->
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_1"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_2"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_3"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_1_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftBackspaceKey
|
||||
android:id="@+id/soft_key_backspace"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Row 2 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layoutDirection="ltr"
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeyAddWord
|
||||
android:id="@+id/soft_key_add_word"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:text="+"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_2_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<!-- Digits 4-6 -->
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_4"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_5"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_6"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_2_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftFilterKey
|
||||
android:id="@+id/soft_key_filter_suggestions"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Row 3 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layoutDirection="ltr"
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftInputModeKey
|
||||
android:id="@+id/soft_key_input_mode"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:text="⌨"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_3_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<!-- Digits 7-9 -->
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_7"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_8"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_9"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_3_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftVoiceInputKey
|
||||
android:id="@+id/soft_key_voice_input"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Row 4 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layoutDirection="ltr"
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeyNextLanguage
|
||||
android:id="@+id/soft_key_language"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:text="🌐" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_4_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftPunctuationKey
|
||||
android:id="@+id/soft_key_punctuation_1"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_0"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftPunctuationKey
|
||||
android:id="@+id/soft_key_punctuation_2"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_4_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftOkKey
|
||||
android:id="@+id/soft_key_ok"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:text="OK"
|
||||
tools:ignore="ButtonOrder" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
android:paddingBottom="@dimen/numpad_padding_bottom"/>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -23,9 +24,9 @@
|
|||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/suggestions_bar"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:scrollbars="none" />
|
||||
|
||||
|
|
@ -35,105 +36,18 @@
|
|||
android:id="@+id/separator_candidates_bottom"
|
||||
style="@style/numRowSeparator" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/main_soft_keys"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/soft_key_height"
|
||||
android:baselineAligned="true"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="HardcodedText,KeyboardInaccessibleWidget">
|
||||
<include
|
||||
layout="@layout/panel_small_function_keys"
|
||||
android:id="@+id/main_soft_keys" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeyCommandPalette
|
||||
android:id="@+id/soft_key_command_palette"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="3"
|
||||
android:focusable="false"
|
||||
android:text="🛠"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/main_separator_left"
|
||||
style="@style/hSeparator"
|
||||
android:background="@drawable/button_separator_dark" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftOkKey
|
||||
android:id="@+id/soft_key_ok"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="5"
|
||||
android:focusable="false"
|
||||
android:text="@android:string/ok" />
|
||||
|
||||
<View
|
||||
android:id="@+id/main_separator_right"
|
||||
android:background="@drawable/button_separator_dark"
|
||||
style="@style/hSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftBackspaceKey
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:id="@+id/soft_key_backspace"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="3"
|
||||
android:focusable="false"
|
||||
android:text="⌫"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
<include
|
||||
layout="@layout/panel_command_palette"
|
||||
android:id="@+id/main_command_keys"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
android:visibility="gone" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_1"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:textSize="@dimen/soft_key_icon_size"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_2_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_2"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:textSize="@dimen/soft_key_icon_size"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_2_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_3"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:textSize="@dimen/soft_key_icon_size"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_3_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_0"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:textSize="@dimen/soft_key_icon_size"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
<include
|
||||
layout="@layout/panel_small_text_editing"
|
||||
android:id="@+id/text_editing_container"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
|||
65
app/src/main/res/layout/panel_command_palette.xml
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:showIn="@layout/main_small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_1"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layout_weight="1"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_1_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_2"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layout_weight="1"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_1_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeyF3
|
||||
android:id="@+id/soft_key_3"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layout_weight="1"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_2_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeyF5
|
||||
android:id="@+id/soft_key_5"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layout_weight="1"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_2_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_8"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layout_weight="1"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
</LinearLayout>
|
||||
175
app/src/main/res/layout/panel_numpad.xml
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:showIn="@layout/main_numpad"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Row 1 -->
|
||||
<LinearLayout
|
||||
tools:ignore="HardcodedText,KeyboardInaccessibleWidget"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeySettings
|
||||
android:id="@+id/soft_key_settings"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:text="⚙"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_1_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<include
|
||||
android:id="@+id/numpad_row_1"
|
||||
layout="@layout/panel_numpad_row_1" />
|
||||
|
||||
<include
|
||||
layout="@layout/panel_numpad_text_editing_row_1"
|
||||
android:id="@+id/text_editing_row_1"
|
||||
android:visibility="gone" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_1_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftBackspaceKey
|
||||
android:id="@+id/soft_key_backspace"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Row 2 -->
|
||||
<LinearLayout
|
||||
tools:ignore="HardcodedText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeyAddWord
|
||||
android:id="@+id/soft_key_add_word"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:text="+"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_2_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<include
|
||||
android:id="@+id/numpad_row_2"
|
||||
layout="@layout/panel_numpad_row_2" />
|
||||
|
||||
<include
|
||||
layout="@layout/panel_numpad_text_editing_row_2"
|
||||
android:id="@+id/text_editing_row_2"
|
||||
android:visibility="gone" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_2_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftFilterKey
|
||||
android:id="@+id/soft_key_filter_suggestions"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Row 3 -->
|
||||
<LinearLayout
|
||||
tools:ignore="HardcodedText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftInputModeKey
|
||||
android:id="@+id/soft_key_input_mode"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:text="⌨"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_3_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<include
|
||||
android:id="@+id/numpad_row_3"
|
||||
layout="@layout/panel_numpad_row_3" />
|
||||
|
||||
<include
|
||||
layout="@layout/panel_numpad_text_editing_row_3"
|
||||
android:id="@+id/text_editing_row_3"
|
||||
android:visibility="gone" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_3_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeyRF3
|
||||
android:id="@+id/soft_key_rf3"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Row 4 -->
|
||||
<LinearLayout
|
||||
tools:ignore="HardcodedText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/numpad_key_height"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeyNextLanguage
|
||||
android:id="@+id/soft_key_language"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:text="🌐" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_4_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<include
|
||||
android:id="@+id/numpad_row_4"
|
||||
layout="@layout/panel_numpad_row_4" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_4_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftOkKey
|
||||
android:id="@+id/soft_key_ok"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
tools:ignore="ButtonOrder"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="@dimen/numpad_control_key_layout_weight"
|
||||
android:text="OK" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
26
app/src/main/res/layout/panel_numpad_row_1.xml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_1"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_2"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_3"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
</merge>
|
||||
26
app/src/main/res/layout/panel_numpad_row_2.xml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_4"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_5"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_6"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
</merge>
|
||||
26
app/src/main/res/layout/panel_numpad_row_3.xml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_7"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_8"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_9"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
</merge>
|
||||
26
app/src/main/res/layout/panel_numpad_row_4.xml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftPunctuationKey
|
||||
android:id="@+id/soft_key_punctuation_1"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftNumberKey
|
||||
android:id="@+id/soft_key_0"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftPunctuationKey
|
||||
android:id="@+id/soft_key_punctuation_2"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||
</merge>
|
||||
35
app/src/main/res/layout/panel_numpad_text_editing_row_1.xml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_101"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawableBottom="@drawable/ic_dpad_left"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:visibility="gone" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_102"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawableBottom="@drawable/ic_txt_select_none"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:visibility="gone" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_103"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawableBottom="@drawable/ic_dpad_right"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:visibility="gone" />
|
||||
</merge>
|
||||
35
app/src/main/res/layout/panel_numpad_text_editing_row_2.xml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_104"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawableBottom="@drawable/ic_txt_word_back"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:visibility="gone" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_105"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawableBottom="@drawable/ic_txt_select_all"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:visibility="gone" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_106"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawableBottom="@drawable/ic_txt_word_forward"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:visibility="gone" />
|
||||
</merge>
|
||||
36
app/src/main/res/layout/panel_numpad_text_editing_row_3.xml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_107"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawableBottom="@drawable/ic_txt_cut"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:visibility="gone" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_108"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawableBottom="@drawable/ic_txt_copy"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:visibility="gone" />
|
||||
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
android:id="@+id/soft_key_109"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawableBottom="@drawable/ic_txt_paste"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:visibility="gone" />
|
||||
</merge>
|
||||
50
app/src/main/res/layout/panel_small_function_keys.xml
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:ignore="HardcodedText,KeyboardInaccessibleWidget"
|
||||
tools:showIn="@layout/main_small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/soft_key_height"
|
||||
android:baselineAligned="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftKeyCommandPalette
|
||||
android:id="@+id/soft_key_command_palette"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="3"
|
||||
android:focusable="false"
|
||||
android:text="🛠"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
|
||||
<View
|
||||
android:id="@+id/main_separator_left"
|
||||
style="@style/hSeparator"
|
||||
android:background="@drawable/button_separator_dark" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftOkKey
|
||||
android:id="@+id/soft_key_ok"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="5"
|
||||
android:focusable="false"
|
||||
android:text="@android:string/ok" />
|
||||
|
||||
<View
|
||||
android:id="@+id/main_separator_right"
|
||||
style="@style/hSeparator"
|
||||
android:background="@drawable/button_separator_dark" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftBackspaceKey
|
||||
android:id="@+id/soft_key_backspace"
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="3"
|
||||
android:focusable="false"
|
||||
android:text="⌫"
|
||||
android:textSize="@dimen/soft_key_icon_size" />
|
||||
</LinearLayout>
|
||||
138
app/src/main/res/layout/panel_small_text_editing.xml
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:showIn="@layout/main_small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/text_editing_keys_small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/numpad_key_height">
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:id="@+id/soft_key_101"
|
||||
android:drawableBottom="@drawable/ic_dpad_left"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_10_1"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:id="@+id/soft_key_102"
|
||||
android:drawableBottom="@drawable/ic_txt_select_none"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_10_2"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:id="@+id/soft_key_103"
|
||||
android:drawableBottom="@drawable/ic_dpad_right"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_10_3"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:id="@+id/soft_key_104"
|
||||
android:drawableBottom="@drawable/ic_txt_word_back"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_10_4"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:id="@+id/soft_key_105"
|
||||
android:drawableBottom="@drawable/ic_txt_select_all"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_10_5"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:id="@+id/soft_key_106"
|
||||
android:drawableBottom="@drawable/ic_txt_word_forward"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_10_6"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:id="@+id/soft_key_107"
|
||||
android:drawableBottom="@drawable/ic_txt_cut"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:layout_width="0dp"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_10_7"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:id="@+id/soft_key_108"
|
||||
android:drawableBottom="@drawable/ic_txt_copy"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:layout_width="0dp"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator_10_8"
|
||||
style="@style/numSeparator" />
|
||||
|
||||
<io.github.sspanak.tt9.ui.main.keys.SoftCommandKey
|
||||
style="@android:style/Widget.Holo.Button.Borderless"
|
||||
android:id="@+id/soft_key_109"
|
||||
android:drawableBottom="@drawable/ic_txt_paste"
|
||||
android:paddingBottom="@dimen/soft_key_drawable_bottom_padding"
|
||||
android:layout_width="0dp"
|
||||
android:textSize="@dimen/soft_key_drawable_title_size"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
<dimen name="soft_key_height">44dp</dimen>
|
||||
<dimen name="soft_key_icon_size">24sp</dimen>
|
||||
<dimen name="soft_key_drawable_bottom_padding">6dp</dimen>
|
||||
<dimen name="soft_key_drawable_title_size">12sp</dimen>
|
||||
|
||||
<!-- Large font size -->
|
||||
<dimen name="pref_large_category_padding_top">30dp</dimen>
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@
|
|||
<string name="virtual_key_del" translatable="false">Del</string>
|
||||
<string name="virtual_key_input_mode" translatable="false">Mode</string>
|
||||
<string name="virtual_key_settings" translatable="false">Cfg</string>
|
||||
<string name="virtual_key_text_editing" translatable="false">Copy</string>
|
||||
|
||||
<string name="voice_input_listening">Speak</string>
|
||||
<string name="voice_input_stopping">Turning off the microphone…</string>
|
||||
|
|
|
|||