Feature: Improve EKS

This commit is contained in:
zt515
2017-06-17 09:28:56 +08:00
parent 718ead6834
commit de522b9b19
23 changed files with 250 additions and 160 deletions

View File

@ -2,7 +2,6 @@ package io.neoterm.view;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
@ -11,121 +10,67 @@ import android.widget.Button;
import android.widget.GridLayout;
import android.widget.ToggleButton;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import io.neoterm.R;
import io.neoterm.backend.TerminalSession;
import io.neoterm.customize.NeoTermPath;
import io.neoterm.customize.shortcut.ShortcutConfig;
import io.neoterm.customize.shortcut.ShortcutConfigParser;
import io.neoterm.preference.NeoTermPreference;
import io.neoterm.utils.FileUtils;
import io.neoterm.view.eks.ControlButton;
import io.neoterm.view.eks.ExtraButton;
import io.neoterm.view.eks.StatedControlButton;
/**
* A view showing extra keys (such as Escape, Ctrl, Alt) not normally available on an Android soft
* keyboard.
*/
public final class ExtraKeysView extends GridLayout {
public static abstract class ExtraButton implements OnClickListener {
public String buttonText;
public static final String KEY_ESC = "Esc";
public static final String KEY_TAB = "Tab";
public static final String KEY_CTRL = "Ctrl";
@Override
public abstract void onClick(View view);
}
public static class ControlButton extends ExtraButton {
public ControlButton(String text) {
buttonText = text;
}
@Override
public void onClick(View view) {
ExtraKeysView.sendKey(view, buttonText);
}
}
public static class TextButton extends ExtraButton {
boolean withEnter = false;
public TextButton(String text) {
this(text, false);
}
public TextButton(String text, boolean withEnter) {
this.buttonText = text;
this.withEnter = withEnter;
}
@Override
public void onClick(View view) {
ExtraKeysView.sendKey(view, buttonText);
if (withEnter) {
ExtraKeysView.sendKey(view, "\n");
}
}
}
public static class StatedControlButton extends ControlButton {
public ToggleButton toggleButton;
public StatedControlButton(String text) {
super(text);
}
@Override
public void onClick(View view) {
toggleButton.setChecked(toggleButton.isChecked());
toggleButton.setTextColor(toggleButton.isChecked() ? 0xFF80DEEA : TEXT_COLOR);
}
public boolean readState() {
if (toggleButton.isPressed()) return true;
boolean result = toggleButton.isChecked();
if (result) {
toggleButton.setChecked(false);
toggleButton.setTextColor(TEXT_COLOR);
}
return result;
}
}
public static final ControlButton ESC = new ControlButton("ESC");
public static final ControlButton TAB = new ControlButton("TAB");
public static final StatedControlButton CTRL = new StatedControlButton("CTRL");
public static final StatedControlButton ALT = new StatedControlButton("ALT");
public static final StatedControlButton FN = new StatedControlButton("FN");
public static final ControlButton ESC = new ControlButton(KEY_ESC);
public static final ControlButton TAB = new ControlButton(KEY_TAB);
public static final StatedControlButton CTRL = new StatedControlButton(KEY_CTRL);
public static final ControlButton ARROW_UP = new ControlButton("");
public static final ControlButton ARROW_DOWN = new ControlButton("");
public static final ControlButton ARROW_LEFT = new ControlButton("");
public static final ControlButton ARROW_RIGHT = new ControlButton("");
public static final TextButton HORIZONTAL = new TextButton("-");
public static final TextButton SLASH = new TextButton("/");
public static final TextButton PIPE = new TextButton("|");
public static final String DEFAULT_FILE_CONTENT = "version " + ShortcutConfigParser.PARSER_VERSION + "\n" +
"program default\n" +
"define - false\n" +
"define / false\n" +
"define | false\n";
private static final int TEXT_COLOR = 0xFFFFFFFF;
public static final int NORMAL_TEXT_COLOR = 0xFFFFFFFF;
private List<ExtraButton> extraButtons;
private List<ExtraButton> externalButtons;
private List<ExtraButton> builtinExtraKeys;
private List<ExtraButton> userDefinedExtraKeys;
public ExtraKeysView(Context context, AttributeSet attrs) {
super(context, attrs);
try {
externalButtons = new ArrayList<>(3);
extraButtons = new ArrayList<>();
resetExternalButtons();
updateButtons();
} catch (Throwable e) {
Log.e("NeoTerm", e.toString());
throw e;
}
builtinExtraKeys = new ArrayList<>(7);
userDefinedExtraKeys = new ArrayList<>(7);
loadDefaultBuiltinExtraKeys();
loadDefaultUserDefinedExtraKeys();
updateButtons();
}
public static void sendKey(View view, String keyName) {
int keyCode = 0;
String chars = null;
switch (keyName) {
case "ESC":
case KEY_ESC:
keyCode = KeyEvent.KEYCODE_ESCAPE;
break;
case "TAB":
case KEY_TAB:
keyCode = KeyEvent.KEYCODE_TAB;
break;
case "":
@ -162,89 +107,97 @@ public final class ExtraKeysView extends GridLayout {
}
public boolean readAltButton() {
return ALT.readState();
}
public boolean readFnButton() {
return FN.readState();
return false;
}
public void addExternalButton(ExtraButton button) {
externalButtons.add(button);
}
public void removeExternalButton(ExtraButton button) {
externalButtons.remove(button);
userDefinedExtraKeys.add(button);
}
public void clearExternalButton() {
externalButtons.clear();
userDefinedExtraKeys.clear();
}
public void resetExternalButtons() {
public void loadDefaultUserDefinedExtraKeys() {
File defaultFile = new File(NeoTermPath.EKS_DEFAULT_FILE);
if (!defaultFile.exists()) {
generateDefaultFile(defaultFile);
}
clearExternalButton();
externalButtons.add(ALT);
externalButtons.add(HORIZONTAL);
externalButtons.add(SLASH);
externalButtons.add(PIPE);
try {
ShortcutConfigParser parser = new ShortcutConfigParser();
parser.setInput(defaultFile);
ShortcutConfig config = parser.parse();
userDefinedExtraKeys.addAll(config.getShortcutKeys());
} catch (Exception ignore) {
}
}
void loadDefaultButtons(List<ExtraButton> buttons) {
buttons.add(ESC);
buttons.add(CTRL);
buttons.add(TAB);
private void generateDefaultFile(File defaultFile) {
FileUtils.INSTANCE.writeFile(defaultFile, DEFAULT_FILE_CONTENT.getBytes());
}
void loadExternalButtons(List<ExtraButton> buttons) {
buttons.addAll(externalButtons);
void loadDefaultBuiltinExtraKeys() {
builtinExtraKeys.clear();
builtinExtraKeys.add(ESC);
builtinExtraKeys.add(CTRL);
builtinExtraKeys.add(TAB);
builtinExtraKeys.add(ARROW_LEFT);
builtinExtraKeys.add(ARROW_RIGHT);
builtinExtraKeys.add(ARROW_UP);
builtinExtraKeys.add(ARROW_DOWN);
}
public void updateButtons() {
removeAllViews();
List[] buttons = new List[]{userDefinedExtraKeys, builtinExtraKeys};
extraButtons.clear();
loadDefaultButtons(extraButtons);
loadExternalButtons(extraButtons);
setRowCount(buttons[0].size() == 0 ? 1 : 2);
setColumnCount(buttons[1].size());
setRowCount(1);
setColumnCount(extraButtons.size());
for (int row = 0; row < buttons.length; row++) {
for (int col = 0; col < buttons[row].size(); col++) {
final ExtraButton extraButton = (ExtraButton) buttons[row].get(col);
for (int col = 0; col < extraButtons.size(); col++) {
final ExtraButton extraButton = extraButtons.get(col);
Button button;
if (extraButton instanceof StatedControlButton) {
StatedControlButton btn = ((StatedControlButton) extraButton);
button = btn.toggleButton = new ToggleButton(getContext(), null, android.R.attr.buttonBarButtonStyle);
button.setClickable(true);
} else {
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
}
button.setText(extraButton.buttonText);
button.setTextColor(TEXT_COLOR);
button.setAllCaps(false);
final Button finalButton = button;
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finalButton.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
View root = getRootView();
extraButton.onClick(root);
Button button;
if (extraButton instanceof StatedControlButton) {
StatedControlButton btn = ((StatedControlButton) extraButton);
button = btn.toggleButton = new ToggleButton(getContext(), null, android.R.attr.buttonBarButtonStyle);
button.setClickable(true);
} else {
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
}
});
LayoutParams param = new LayoutParams();
param.height = param.width = 0;
param.rightMargin = param.topMargin = 0;
param.setGravity(Gravity.START);
float weight = "▲▼◀▶".contains(extraButton.buttonText) ? 0.7f : 1.f;
param.columnSpec = GridLayout.spec(col, GridLayout.FILL, weight);
param.rowSpec = GridLayout.spec(0, GridLayout.FILL, 1.f);
button.setLayoutParams(param);
button.setText(extraButton.buttonText);
button.setTextColor(NORMAL_TEXT_COLOR);
button.setAllCaps(false);
addView(button);
final Button finalButton = button;
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finalButton.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
View root = getRootView();
extraButton.onClick(root);
}
});
LayoutParams param = new LayoutParams();
param.height = param.width = 0;
param.rightMargin = param.topMargin = 0;
param.setGravity(Gravity.START);
float weight = 1.f;
if (NeoTermPreference.INSTANCE.loadBoolean(R.string.key_ui_wide_char_weigh_explicit, false)) {
weight = "▲▼◀▶".contains(extraButton.buttonText) ? 0.7f : 1.f;
}
param.columnSpec = GridLayout.spec(col, GridLayout.FILL, weight);
param.rowSpec = GridLayout.spec(row, GridLayout.FILL, 1.f);
button.setLayoutParams(param);
addView(button);
}
}
}