Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ dependencies {
implementation(libs.transition)
implementation(libs.fragment)
implementation(libs.activity)
implementation(project(":filetree"))
implementation(libs.terminal.view)
implementation(libs.terminal.emulator)
implementation(libs.utilcodex)


// with Paths
implementation(project(":filetree"))

//tests
coreLibraryDesugaring(libs.desugar.jdk.libs)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.sparkleseditor.components.virtualkeys;

import androidx.annotation.NonNull;
import java.util.HashMap;

/** The {@link Class} that implements special buttons for {@link VirtualKeysView}. */
public class SpecialButton {

private static final HashMap<String, SpecialButton> map = new HashMap<>();
public static final SpecialButton CTRL = new SpecialButton("CTRL");
public static final SpecialButton ALT = new SpecialButton("ALT");
public static final SpecialButton SHIFT = new SpecialButton("SHIFT");
public static final SpecialButton FN = new SpecialButton("FN");

/** The special button key. */
private final String key;

/**
* Initialize a {@link SpecialButton}.
*
* @param key The unique key name for the special button. The key is registered in {@link #map}
* with which the {@link SpecialButton} can be retrieved via a call to {@link
* #valueOf(String)}.
*/
public SpecialButton(@NonNull final String key) {
this.key = key;
map.put(key, this);
}

/**
* Get the {@link SpecialButton} for {@code key}.
*
* @param key The unique key name for the special button.
*/
public static SpecialButton valueOf(String key) {
return map.get(key);
}

/** Get {@link #key} for this {@link SpecialButton}. */
public String getKey() {
return key;
}

@NonNull
@Override
public String toString() {
return key;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.sparkleseditor.components.virtualkeys;

import android.widget.Button;
import java.util.ArrayList;
import java.util.List;

/** The {@link Class} that maintains a state of a {@link SpecialButton} */
public class SpecialButtonState {

/** If special button has been created for the {@link VirtualKeysView}. */
boolean isCreated = false;

/** If special button is active. */
boolean isActive = false;

/**
* If special button is locked due to long hold on it and should not be deactivated if its state
* is read.
*/
boolean isLocked = false;

List<Button> buttons = new ArrayList<>();

VirtualKeysView mVirtualKeysView;

/**
* Initialize a {@link SpecialButtonState} to maintain state of a {@link SpecialButton}.
*
* @param extraKeysView The {@link VirtualKeysView} instance in which the {@link SpecialButton} is
* to be registered.
*/
public SpecialButtonState(VirtualKeysView extraKeysView) {
mVirtualKeysView = extraKeysView;
}

/** Set {@link #isCreated}. */
public void setIsCreated(boolean value) {
isCreated = value;
}

/** Set {@link #isActive}. */
public void setIsActive(boolean value) {
isActive = value;
for (Button button : buttons) {
button.setTextColor(
value
? mVirtualKeysView.getButtonActiveTextColor()
: mVirtualKeysView.getButtonTextColor());
}
}

/** Set {@link #isLocked}. */
public void setIsLocked(boolean value) {
isLocked = value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package com.sparkleseditor.components.virtualkeys;

import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Arrays;
import java.util.stream.Collectors;
import org.json.JSONException;
import org.json.JSONObject;

public class VirtualKeyButton {

/**
* The key name for the name of the extra key if using a dict to define the extra key. {key: name,
* ...}
*/
public static final String KEY_KEY_NAME = "key";

/**
* The key name for the macro value of the extra key if using a dict to define the extra key.
* {macro: value, ...}
*/
public static final String KEY_MACRO = "macro";

/**
* The key name for the alternate display name of the extra key if using a dict to define the
* extra key. {display: name, ...}
*/
public static final String KEY_DISPLAY_NAME = "display";

/**
* The key name for the nested dict to define popup extra key info if using a dict to define the
* extra key. {popup: {key: name, ...}, ...}
*/
public static final String KEY_POPUP = "popup";

/**
* The key that will be sent to the terminal, either a control character, like defined in {@link
* VirtualKeysConstants#PRIMARY_KEY_CODES_FOR_STRINGS} (LEFT, RIGHT, PGUP...) or some text.
*/
private final String key;

/** If the key is a macro, i.e. a sequence of keys separated by space. */
private final boolean macro;

/** The text that will be displayed on the button. */
private final String display;

/**
* The {@link VirtualKeyButton} containing the information of the popup button (triggered by swipe
* up).
*/
@Nullable private final VirtualKeyButton popup;

/**
* Initialize a {@link VirtualKeyButton}.
*
* @param config The {@link JSONObject} containing the info to create the {@link
* VirtualKeyButton}.
* @param extraKeyDisplayMap The {@link VirtualKeysConstants.VirtualKeyDisplayMap} that defines
* the display text mapping for the keys if a custom value is not defined by {@link
* #KEY_DISPLAY_NAME}.
* @param extraKeyAliasMap The {@link VirtualKeysConstants.VirtualKeyDisplayMap} that defines the
* aliases for the actual key names.
*/
public VirtualKeyButton(
@NonNull JSONObject config,
@NonNull VirtualKeysConstants.VirtualKeyDisplayMap extraKeyDisplayMap,
@NonNull VirtualKeysConstants.VirtualKeyDisplayMap extraKeyAliasMap)
throws JSONException {
this(config, null, extraKeyDisplayMap, extraKeyAliasMap);
}

/**
* Initialize a {@link VirtualKeyButton}.
*
* @param config The {@link JSONObject} containing the info to create the {@link
* VirtualKeyButton}.
* @param popup The {@link VirtualKeyButton} optional {@link #popup} button.
* @param extraKeyDisplayMap The {@link VirtualKeysConstants.VirtualKeyDisplayMap} that defines
* the display text mapping for the keys if a custom value is not defined by {@link
* #KEY_DISPLAY_NAME}.
* @param extraKeyAliasMap The {@link VirtualKeysConstants.VirtualKeyDisplayMap} that defines the
* aliases for the actual key names.
*/
public VirtualKeyButton(
@NonNull JSONObject config,
@Nullable VirtualKeyButton popup,
@NonNull VirtualKeysConstants.VirtualKeyDisplayMap extraKeyDisplayMap,
@NonNull VirtualKeysConstants.VirtualKeyDisplayMap extraKeyAliasMap)
throws JSONException {
String keyFromConfig = getStringFromJson(config, KEY_KEY_NAME);
String macroFromConfig = getStringFromJson(config, KEY_MACRO);
String[] keys;
if (keyFromConfig != null && macroFromConfig != null) {
throw new JSONException(
"Both key and macro can't be set for the same key. key: \""
+ keyFromConfig
+ "\", macro: \""
+ macroFromConfig
+ "\"");
} else if (keyFromConfig != null) {
keys = new String[] {keyFromConfig};
this.macro = false;
} else if (macroFromConfig != null) {
keys = macroFromConfig.split(" ");
this.macro = true;
} else {
throw new JSONException("All keys have to specify either key or macro");
}

for (int i = 0; i < keys.length; i++) {
keys[i] = replaceAlias(extraKeyAliasMap, keys[i]);
}

this.key = TextUtils.join(" ", keys);

String displayFromConfig = getStringFromJson(config, KEY_DISPLAY_NAME);
if (displayFromConfig != null) {
this.display = displayFromConfig;
} else {
this.display =
Arrays.stream(keys)
.map(key -> extraKeyDisplayMap.get(key, key))
.collect(Collectors.joining(" "));
}

this.popup = popup;
}

public String getStringFromJson(@NonNull JSONObject config, @NonNull String key) {
try {
return config.getString(key);
} catch (JSONException e) {
return null;
}
}

/** Replace the alias with its actual key name if found in extraKeyAliasMap. */
public static String replaceAlias(
@NonNull VirtualKeysConstants.VirtualKeyDisplayMap extraKeyAliasMap, String key) {
return extraKeyAliasMap.get(key, key);
}

/** Get {@link #key}. */
public String getKey() {
return key;
}

/** Check whether a {@link #macro} is defined or not. */
public boolean isMacro() {
return macro;
}

/** Get {@link #display}. */
public String getDisplay() {
return display;
}

/** Get {@link #popup}. */
@Nullable
public VirtualKeyButton getPopup() {
return popup;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.sparkleseditor.components.virtualkeys

import android.view.View
import android.widget.Button
import com.termux.terminal.TerminalSession

class VirtualKeyClient(val session: TerminalSession) : VirtualKeysView.IVirtualKeysView {
override fun onVirtualKeyButtonClick(
view: View?,
buttonInfo: VirtualKeyButton?,
button: Button?,
) {
val key = buttonInfo?.key
if (key.isNullOrEmpty()) {
return
}
when (key) {
"ESC" -> session.write("\u001B") // ESC
"TAB" -> session.write("\u0009") // TAB
"HOME" -> session.write("\u001B[H") // HOME
"UP" -> session.write("\u001B[A") // UP Arrow (ANSI escape code)
"DOWN" -> session.write("\u001B[B") // DOWN Arrow (ANSI escape code)
"LEFT" -> session.write("\u001B[D") // LEFT Arrow (ANSI escape code)
"RIGHT" -> session.write("\u001B[C") // RIGHT Arrow (ANSI escape code)
"PGUP" -> session.write("\u001B[5~") // Page Up (ANSI escape code)
"PGDN" -> session.write("\u001B[6~") // Page Down (ANSI escape code)
"END" -> session.write("\u001B[4~") // End (ANSI escape code, may vary)
else -> session.write(buttonInfo.key)
}
}

override fun performVirtualKeyButtonHapticFeedback(
view: View?,
buttonInfo: VirtualKeyButton?,
button: Button?,
): Boolean {
return false
}
}
Loading