Allow choosing alternate keyboard.kbd.json file from /sdcard (or internal dataDir)

This commit is contained in:
Aaron Culliney 2015-08-28 22:15:42 -07:00
parent 4258da8cbd
commit e4a849e6ae
9 changed files with 151 additions and 71 deletions

View File

@ -120,6 +120,7 @@ public abstract class Apple2AbstractMenu implements Apple2MenuView {
public interface IPreferenceLoadSave {
public int intValue();
public void saveInt(int value);
}
@ -166,6 +167,10 @@ public abstract class Apple2AbstractMenu implements Apple2MenuView {
}
protected static void _alertDialogHandleSelection(final Apple2Activity activity, final int titleId, final String[] choices, final IPreferenceLoadSave iLoadSave) {
_alertDialogHandleSelection(activity, activity.getResources().getString(titleId), choices, iLoadSave);
}
protected static void _alertDialogHandleSelection(final Apple2Activity activity, final String titleId, final String[] choices, final IPreferenceLoadSave iLoadSave) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(titleId);
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override

View File

@ -53,7 +53,6 @@ public class Apple2DisksMenu implements Apple2MenuView {
private final ArrayList<String> mPathStack = new ArrayList<>();
private static File sExternalFilesDir = null;
private static boolean sExternalStorageAvailable = false;
private static boolean sInitializedPath = false;
public Apple2DisksMenu(Apple2Activity activity) {
@ -70,22 +69,26 @@ public class Apple2DisksMenu implements Apple2MenuView {
}
});
if (!sExternalStorageAvailable) {
getExternalStorageDirectory();
}
public static File getExternalStorageDirectory() {
if (sExternalFilesDir == null) {
String storageState = Environment.getExternalStorageState();
File externalDir = new File(Environment.getExternalStorageDirectory().getPath() + File.separator + "apple2ix"); // /sdcard/apple2ix
sExternalFilesDir = null;
sExternalStorageAvailable = storageState.equals(Environment.MEDIA_MOUNTED);
if (sExternalStorageAvailable) {
boolean externalStorageAvailable = storageState.equals(Environment.MEDIA_MOUNTED);
if (externalStorageAvailable) {
sExternalFilesDir = externalDir;
boolean made = sExternalFilesDir.mkdirs();
if (!made) {
Log.d(TAG, "WARNING: could not make directory : " + sExternalFilesDir);
}
} else {
sExternalStorageAvailable = storageState.equals(Environment.MEDIA_MOUNTED_READ_ONLY) && externalDir.exists();
sExternalFilesDir = externalDir;
}
}
return sExternalFilesDir;
}
// HACK NOTE 2015/02/22 : Apparently native code cannot easily access stuff in the APK ... so copy various resources
@ -114,14 +117,25 @@ public class Apple2DisksMenu implements Apple2MenuView {
Log.d(TAG, "First time copying stuff-n-things out of APK for ease-of-NDK access...");
getExternalStorageDirectory();
try {
String[] shaders = activity.getAssets().list("shaders");
for (String shader : shaders) {
Apple2DisksMenu.copyFile(activity, "shaders", shader);
Apple2DisksMenu.copyFile(activity, "shaders", shader, sDataDir + File.separator + "shaders");
}
String[] keyboards = activity.getAssets().list("keyboards");
for (String kbd : keyboards) {
Apple2DisksMenu.copyFile(activity, "keyboards", kbd, sDataDir + File.separator + "keyboards");
if (sExternalFilesDir != null) {
Apple2DisksMenu.copyFile(activity, "keyboards", kbd, sExternalFilesDir.getPath());
}
}
String[] disks = activity.getAssets().list("disks");
for (String disk : disks) {
Apple2DisksMenu.copyFile(activity, "disks", disk);
Apple2DisksMenu.copyFile(activity, "disks", disk, sDataDir + File.separator + "disks");
}
} catch (IOException e) {
Log.e(TAG, "problem copying resources : " + e);
@ -225,9 +239,8 @@ public class Apple2DisksMenu implements Apple2MenuView {
return pathBuffer.toString();
}
private static void copyFile(Apple2Activity activity, String subdir, String assetName)
private static void copyFile(Apple2Activity activity, String subdir, String assetName, String outputPath)
throws IOException {
String outputPath = sDataDir + File.separator + subdir;
Log.d(TAG, "Copying " + subdir + File.separator + assetName + " to " + outputPath + File.separator + assetName + " ...");
boolean made = new File(outputPath).mkdirs();
if (!made) {
@ -325,13 +338,14 @@ public class Apple2DisksMenu implements Apple2MenuView {
Arrays.sort(files);
final boolean includeExternalStoragePath = (sExternalStorageAvailable && isRootPath);
getExternalStorageDirectory();
final boolean includeExternalStoragePath = (sExternalFilesDir != null && isRootPath);
final int offset = includeExternalStoragePath ? 1 : 0;
final String[] fileNames = new String[files.length + offset];
final boolean[] isDirectory = new boolean[files.length + offset];
if (includeExternalStoragePath) {
fileNames[0] = sExternalFilesDir.toString();
fileNames[0] = sExternalFilesDir.getPath();
isDirectory[0] = true;
}

View File

@ -16,6 +16,10 @@ import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
private final static String TAG = "Apple2KeyboardSettingsMenu";
@ -23,11 +27,11 @@ public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
// These settings must match native side
public final static int MOUSETEXT_BEGIN = 0x80;
public final static int MOUSETEXT_CLOSEDAPPLE = MOUSETEXT_BEGIN/*+0x00*/;
public final static int MOUSETEXT_OPENAPPLE = MOUSETEXT_BEGIN+0x01;
public final static int MOUSETEXT_LEFT = MOUSETEXT_BEGIN+0x08;
public final static int MOUSETEXT_UP = MOUSETEXT_BEGIN+0x0b;
public final static int MOUSETEXT_DOWN = MOUSETEXT_BEGIN+0x0a;
public final static int MOUSETEXT_RIGHT = MOUSETEXT_BEGIN+0x15;
public final static int MOUSETEXT_OPENAPPLE = MOUSETEXT_BEGIN + 0x01;
public final static int MOUSETEXT_LEFT = MOUSETEXT_BEGIN + 0x08;
public final static int MOUSETEXT_UP = MOUSETEXT_BEGIN + 0x0b;
public final static int MOUSETEXT_DOWN = MOUSETEXT_BEGIN + 0x0a;
public final static int MOUSETEXT_RIGHT = MOUSETEXT_BEGIN + 0x15;
public final static int ICONTEXT_BEGIN = 0xA0;
public final static int ICONTEXT_VISUAL_SPACE = ICONTEXT_BEGIN + 0x11;
@ -194,11 +198,45 @@ public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
@Override
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) {
String[] titles = new String[Apple2Preferences.KeyboardAltPreset.size + 1];
titles[0] = activity.getResources().getString(R.string.keyboard_preset_custom);
System.arraycopy(Apple2Preferences.KeyboardAltPreset.titles(activity), 0, titles, 1, Apple2Preferences.KeyboardAltPreset.size);
_alertDialogHandleSelection(activity, R.string.keyboard_choose_alt_title, titles, new IPreferenceLoadSave() {
File keyboardDir = Apple2DisksMenu.getExternalStorageDirectory();
if (keyboardDir == null) {
keyboardDir = new File(Apple2DisksMenu.getDataDir(activity) + File.separator + "keyboards");
}
final File[] files = keyboardDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
File file = new File(dir, name);
if (file.isDirectory()) {
return false;
}
// check file extensions ... sigh ... no String.endsWithIgnoreCase() ?
final String extension = ".kbd.json";
final int nameLen = name.length();
final int extLen = extension.length();
if (nameLen <= extLen) {
return false;
}
String suffix = name.substring(nameLen - extLen, nameLen);
return (suffix.equalsIgnoreCase(extension));
}
});
Arrays.sort(files);
String[] titles = new String[files.length];
int idx = 0;
for (File file : files) {
titles[idx] = file.getName();
++idx;
}
final String keyboardDirName = keyboardDir.getPath();
_alertDialogHandleSelection(activity, keyboardDirName, titles, new IPreferenceLoadSave() {
@Override
public int intValue() {
return Apple2Preferences.KEYBOARD_ALT.intValue(activity);
@ -207,12 +245,8 @@ public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
@Override
public void saveInt(int value) {
Apple2Preferences.KEYBOARD_ALT.saveInt(activity, value);
if (value == 0) {
Apple2KeyboardSettingsMenu keyboardSettingsMenu = (Apple2KeyboardSettingsMenu) settingsMenu;
////TODO FIXME ... keyboardSettingsMenu.chooseAltKeyboard(activity);
} else {
Apple2Preferences.KeyboardAltPreset.values()[value - 1].apply(activity);
}
String path = files[value].getPath();
Apple2Preferences.KEYBOARD_ALT_PATH.saveString(activity, path);
}
});
}

View File

@ -520,7 +520,18 @@ public enum Apple2Preferences {
@Override
public int intValue(Apple2Activity activity) {
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 1);
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 0);
}
},
KEYBOARD_ALT_PATH {
@Override
public void load(Apple2Activity activity) {
nativeLoadTouchKeyboardJSON(stringValue(activity));
}
@Override
public String stringValue(Apple2Activity activity) {
return activity.getPreferences(Context.MODE_PRIVATE).getString(toString(), "");
}
},
KEYBOARD_VISIBILITY_ACTIVE {
@ -774,46 +785,6 @@ public enum Apple2Preferences {
}
}
public enum KeyboardAltPreset {
DEFAULT {
@Override
public String getTitle(Apple2Activity activity) {
return activity.getResources().getString(R.string.keyboard_preset_default);
}
@Override
public void apply(Apple2Activity activity) {
// TODO FIXME ...
}
},
U4 {
@Override
public String getTitle(Apple2Activity activity) {
return activity.getResources().getString(R.string.keyboard_preset_u4);
}
@Override
public void apply(Apple2Activity activity) {
// TODO FIXME ...
}
};
public abstract String getTitle(Apple2Activity activity);
public abstract void apply(Apple2Activity activity);
public static final int size = KeyboardAltPreset.values().length;
public static String[] titles(Apple2Activity activity) {
String[] titles = new String[size];
int i = 0;
for (KeyboardAltPreset preset : values()) {
titles[i++] = preset.getTitle(activity);
}
return titles;
}
}
public final static int DECENT_AMOUNT_OF_CHOICES = 20;
public final static int AUDIO_LATENCY_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES;
public final static int ALPHA_SLIDER_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES;
@ -1055,4 +1026,6 @@ public enum Apple2Preferences {
private static native void nativeSetTouchDeviceKeyRepeatThreshold(float threshold);
private static native void nativeLoadTouchKeyboardJSON(String path);
}

View File

@ -73,14 +73,11 @@
<string name="keyboard">Keyboard</string>
<string name="keyboard_choose_alt">Choose alt keyboard…</string>
<string name="keyboard_choose_alt_summary">Choose alternative customized layout</string>
<string name="keyboard_choose_alt_title">Alt keyboard layout</string>
<string name="keyboard_configure">Configure keyboard…</string>
<string name="keyboard_configure_summary">Transparency, lowercase, custom keys</string>
<string name="keyboard_lowercase_enabled">Enable lowercase</string>
<string name="keyboard_lowercase_enabled_summary">Enable lowercase keys</string>
<string name="keyboard_preset_custom">Load custom…</string>
<string name="keyboard_preset_default">Default</string>
<string name="keyboard_preset_u4">U4 optimized</string>
<string name="keyboard_visibility_active">Visibility when active</string>
<string name="keyboard_visibility_active_summary">Keyboard visibility when active</string>
<string name="keyboard_visibility_inactive">Visibility when inactive</string>

View File

@ -0,0 +1,26 @@
[
"Default Alternate Touch Keyboard",
{
"_comment" : "hex code for special glyphs",
"_AA" : "b5",
"_CTRL": "b3",
"_XX" : "9b",
"_ESC" : "bc",
"_OA" : "81",
"_CA" : "80",
"_UP" : "8b",
"_LT" : "88",
"_RT" : "95",
"_DN" : "8a"
},
["reserved for future use"],
["reserved for future use"],
["_AA", "", "_CTRL", "", "_ESC", "", "_OA", "", "_CA", ""],
[ "", "", "", "", "", "", "", "", "", ""],
[ "", "", "", "", "", "_UP", "", "", "", ""],
[ "", "", "", "", "_LT", "_XX", "_RT", "", "", ""],
[ "", "", "", "", "", "_DN", "", "", "", ""],
[ "", "", "", "", "", "", "", "", "", ""]
]

View File

@ -0,0 +1,23 @@
[
"Alt keyboard optimized for Ultima(tm) 4",
{
"_comment" : "hex code for special glyphs",
"_AA" : "b5",
"_XX" : "9b",
"_ESC" : "bc",
"_UP" : "8b",
"_LT" : "88",
"_RT" : "95",
"_DN" : "8a"
},
["reserved for future use"],
["reserved for future use"],
["_AA", "", "", "", "", "", "", "", "", "_ESC"],
[ "", "", "", "", "", "", "1", "2", "3", "4"],
[ "", "", "", "", "", "", "5", "6", "7", "8"],
[ "S", "", "", "", "", "", "", "T", "_UP", "G"],
[ "A", "", "", "", "", "", "", "_LT", "_XX", "_RT"],
[ "Z", "", "", "", "", "", "", "C", "_DN", "O"]
]

View File

@ -286,3 +286,10 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetCPUSpeed(JNIEnv *env,
}
}
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeLoadTouchKeyboardJSON(JNIEnv *env, jclass cls, jstring j_jsonPath) {
const char *jsonPath = (*env)->GetStringUTFChars(env, j_jsonPath, 0);
LOG("jsonPath: %s", jsonPath);
keydriver_loadAltKbd(jsonPath);
(*env)->ReleaseStringUTFChars(env, j_jsonPath, jsonPath);
}

View File

@ -35,7 +35,8 @@ APPLE2_META_SRC = \
APPLE2_MAIN_SRC = \
$(APPLE2_SRC_PATH)/font.c $(APPLE2_SRC_PATH)/rom.c $(APPLE2_SRC_PATH)/misc.c $(APPLE2_SRC_PATH)/display.c $(APPLE2_SRC_PATH)/vm.c \
$(APPLE2_SRC_PATH)/timing.c $(APPLE2_SRC_PATH)/zlib-helpers.c $(APPLE2_SRC_PATH)/joystick.c $(APPLE2_SRC_PATH)/keys.c \
$(APPLE2_SRC_PATH)/interface.c $(APPLE2_SRC_PATH)/disk.c $(APPLE2_SRC_PATH)/cpu-supp.c jnihooks.c
$(APPLE2_SRC_PATH)/interface.c $(APPLE2_SRC_PATH)/disk.c $(APPLE2_SRC_PATH)/cpu-supp.c jnihooks.c \
$(APPLE2_SRC_PATH)/json_parse.c $(APPLE2_SRC_PATH)/../externals/jsmn/jsmn.c
APPLE2_OPTIM_CFLAGS := -g -O2
APPLE2_BASE_CFLAGS := -DAPPLE2IX=1 -DINTERFACE_TOUCH=1 -DMOBILE_DEVICE=1 -DVIDEO_OPENGL=1 -DDEBUGGER=1 -DAUDIO_ENABLED=1 -std=gnu11 $(APPLE2_OPTIM_CFLAGS) -I$(APPLE2_SRC_PATH)