2017-06-11 19:24:09 +08:00
|
|
|
package io.neoterm.view;
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
import android.util.AttributeSet;
|
|
|
|
import android.view.Gravity;
|
|
|
|
import android.view.HapticFeedbackConstants;
|
|
|
|
import android.view.KeyEvent;
|
|
|
|
import android.view.View;
|
|
|
|
import android.widget.Button;
|
|
|
|
import android.widget.GridLayout;
|
|
|
|
import android.widget.ToggleButton;
|
|
|
|
|
2017-06-14 11:43:39 +08:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
2017-06-11 19:24:09 +08:00
|
|
|
import io.neoterm.R;
|
2017-06-12 15:03:57 +08:00
|
|
|
import io.neoterm.backend.TerminalSession;
|
2017-06-11 19:24:09 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A view showing extra keys (such as Escape, Ctrl, Alt) not normally available on an Android soft
|
|
|
|
* keyboard.
|
|
|
|
*/
|
|
|
|
public final class ExtraKeysView extends GridLayout {
|
2017-06-14 11:43:39 +08:00
|
|
|
public static abstract class ExtraButton implements OnClickListener {
|
|
|
|
public String buttonText;
|
|
|
|
|
|
|
|
@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 {
|
|
|
|
public TextButton(String text) {
|
|
|
|
buttonText = text;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
|
|
|
ExtraKeysView.sendKey(view, buttonText);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 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("|");
|
2017-06-11 19:24:09 +08:00
|
|
|
|
|
|
|
private static final int TEXT_COLOR = 0xFFFFFFFF;
|
|
|
|
|
2017-06-14 11:43:39 +08:00
|
|
|
private List<ExtraButton> extraButtons;
|
|
|
|
private List<ExtraButton> externalButtons;
|
|
|
|
|
2017-06-11 19:24:09 +08:00
|
|
|
public ExtraKeysView(Context context, AttributeSet attrs) {
|
|
|
|
super(context, attrs);
|
2017-06-14 11:43:39 +08:00
|
|
|
externalButtons = new ArrayList<>(3);
|
|
|
|
extraButtons = new ArrayList<>();
|
|
|
|
resetExternalButtons();
|
2017-06-11 19:24:09 +08:00
|
|
|
reload();
|
|
|
|
}
|
|
|
|
|
2017-06-14 11:43:39 +08:00
|
|
|
public static void sendKey(View view, String keyName) {
|
2017-06-11 19:24:09 +08:00
|
|
|
int keyCode = 0;
|
|
|
|
String chars = null;
|
|
|
|
switch (keyName) {
|
|
|
|
case "ESC":
|
|
|
|
keyCode = KeyEvent.KEYCODE_ESCAPE;
|
|
|
|
break;
|
|
|
|
case "TAB":
|
|
|
|
keyCode = KeyEvent.KEYCODE_TAB;
|
|
|
|
break;
|
|
|
|
case "▲":
|
|
|
|
keyCode = KeyEvent.KEYCODE_DPAD_UP;
|
|
|
|
break;
|
|
|
|
case "◀":
|
|
|
|
keyCode = KeyEvent.KEYCODE_DPAD_LEFT;
|
|
|
|
break;
|
|
|
|
case "▶":
|
|
|
|
keyCode = KeyEvent.KEYCODE_DPAD_RIGHT;
|
|
|
|
break;
|
|
|
|
case "▼":
|
|
|
|
keyCode = KeyEvent.KEYCODE_DPAD_DOWN;
|
|
|
|
break;
|
|
|
|
case "―":
|
|
|
|
chars = "-";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
chars = keyName;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keyCode > 0) {
|
|
|
|
view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
|
|
|
|
view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
|
|
|
|
} else {
|
|
|
|
TerminalView terminalView = (TerminalView) view.findViewById(R.id.terminal_view);
|
|
|
|
TerminalSession session = terminalView.getCurrentSession();
|
|
|
|
if (session != null) session.write(chars);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean readControlButton() {
|
2017-06-14 11:43:39 +08:00
|
|
|
return CTRL.readState();
|
2017-06-11 19:24:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean readAltButton() {
|
2017-06-14 11:43:39 +08:00
|
|
|
return ALT.readState();
|
2017-06-11 19:24:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean readFnButton() {
|
2017-06-14 11:43:39 +08:00
|
|
|
return FN.readState();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addExternalButton(ExtraButton button) {
|
|
|
|
externalButtons.add(button);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeExternalButton(ExtraButton button) {
|
|
|
|
externalButtons.remove(button);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void clearExternalButton() {
|
|
|
|
externalButtons.clear();
|
2017-06-11 19:24:09 +08:00
|
|
|
}
|
|
|
|
|
2017-06-14 11:43:39 +08:00
|
|
|
public void resetExternalButtons() {
|
|
|
|
clearExternalButton();
|
|
|
|
externalButtons.add(HORIZONTAL);
|
|
|
|
externalButtons.add(SLASH);
|
|
|
|
externalButtons.add(PIPE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void loadDefaultButtons(List<ExtraButton> buttons) {
|
|
|
|
buttons.add(ESC);
|
|
|
|
buttons.add(CTRL);
|
|
|
|
buttons.add(ALT);
|
|
|
|
buttons.add(TAB);
|
|
|
|
}
|
|
|
|
|
|
|
|
void loadExternalButtons(List<ExtraButton> buttons) {
|
|
|
|
buttons.addAll(externalButtons);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void reload() {
|
|
|
|
ALT.toggleButton = CTRL.toggleButton = null;
|
2017-06-11 19:24:09 +08:00
|
|
|
removeAllViews();
|
|
|
|
|
2017-06-14 11:43:39 +08:00
|
|
|
extraButtons.clear();
|
|
|
|
loadDefaultButtons(extraButtons);
|
|
|
|
loadExternalButtons(extraButtons);
|
|
|
|
|
|
|
|
setRowCount(1);
|
|
|
|
setColumnCount(extraButtons.size());
|
|
|
|
|
|
|
|
for (int col = 0; col < extraButtons.size(); col++) {
|
|
|
|
final ExtraButton extraButton = extraButtons.get(col);
|
2017-06-11 19:24:09 +08:00
|
|
|
|
2017-06-14 11:43:39 +08:00
|
|
|
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);
|
2017-06-11 19:24:09 +08:00
|
|
|
}
|
2017-06-14 11:43:39 +08:00
|
|
|
|
|
|
|
button.setText(extraButton.buttonText);
|
|
|
|
button.setTextColor(TEXT_COLOR);
|
|
|
|
|
|
|
|
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 = "▲▼◀▶".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);
|
|
|
|
|
|
|
|
addView(button);
|
2017-06-11 19:24:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|