From 2673777be7880521e0cb416e94c67f5adc6a2391 Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Fri, 7 Aug 2015 23:00:08 -0700 Subject: [PATCH] Various improvements to disk management - Moves disk management form Apple2Activity to Apple2DisksMenu - Handle reading/writing disk images in /sdcard/... - Manage hirerarchical navigation --- .../deadc0de/apple2ix/Apple2AbstractMenu.java | 4 + .../org/deadc0de/apple2ix/Apple2Activity.java | 89 +---- .../deadc0de/apple2ix/Apple2DisksMenu.java | 356 +++++++++++++++--- .../apple2ix/Apple2JoystickCalibration.java | 8 +- .../apple2ix/Apple2JoystickSettingsMenu.java | 2 +- .../apple2ix/Apple2KeypadSettingsMenu.java | 25 +- .../org/deadc0de/apple2ix/Apple2MenuView.java | 2 + .../deadc0de/apple2ix/Apple2Preferences.java | 68 +++- .../deadc0de/apple2ix/Apple2SplashScreen.java | 4 + .../main/res/layout/a2disk_confirmation.xml | 51 +++ .../src/main/res/layout/activity_disks.xml | 43 +-- Android/app/src/main/res/values/strings.xml | 1 + 12 files changed, 496 insertions(+), 157 deletions(-) create mode 100644 Android/app/src/main/res/layout/a2disk_confirmation.xml diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2AbstractMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2AbstractMenu.java index c037c1b8..100e5f66 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2AbstractMenu.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2AbstractMenu.java @@ -51,6 +51,10 @@ public abstract class Apple2AbstractMenu implements Apple2MenuView { mActivity.popApple2View(this); } + public void dismissAll() { + this.dismiss(); + } + public boolean isShowing() { return mSettingsView.isShown(); } diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java index 2c1650d8..39d43254 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java @@ -14,8 +14,6 @@ package org.deadc0de.apple2ix; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; import android.graphics.Rect; import android.media.AudioManager; import android.os.Build; @@ -29,19 +27,13 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.widget.FrameLayout; -import java.io.File; -import java.io.InputStream; -import java.io.IOException; -import java.io.FileOutputStream; import java.util.ArrayList; public class Apple2Activity extends Activity { private final static String TAG = "Apple2Activity"; - private final static int BUF_SZ = 4096; private final static int MAX_FINGERS = 32;// HACK ... - private String mDataDir = null; private boolean mSetUncaughtExceptionHandler = false; private Apple2View mView = null; @@ -104,70 +96,6 @@ public class Apple2Activity extends Activity { public native void nativeChooseDisk(String path, boolean driveA, boolean readOnly); - // HACK NOTE 2015/02/22 : Apparently native code cannot easily access stuff in the APK ... so copy various resources - // out of the APK and into the /data/data/... for ease of access. Because this is FOSS software we don't care about - // security or DRM for these assets =) - private String _firstTimeInitialization() { - - String dataDir = null; - try { - PackageManager pm = getPackageManager(); - PackageInfo pi = pm.getPackageInfo(getPackageName(), 0); - dataDir = pi.applicationInfo.dataDir; - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "" + e); - System.exit(1); - } - - if (Apple2Preferences.PREFS_CONFIGURED.booleanValue(this)) { - return dataDir; - } - - Log.d(TAG, "First time copying stuff-n-things out of APK for ease-of-NDK access..."); - - try { - String[] shaders = getAssets().list("shaders"); - for (String shader : shaders) { - _copyFile(dataDir, "shaders", shader); - } - String[] disks = getAssets().list("disks"); - for (String disk : disks) { - _copyFile(dataDir, "disks", disk); - } - } catch (IOException e) { - Log.e(TAG, "problem copying resources : " + e); - System.exit(1); - } - - Log.d(TAG, "Saving default preferences"); - Apple2Preferences.PREFS_CONFIGURED.saveBoolean(this, true); - - return dataDir; - } - - private void _copyFile(String dataDir, String subdir, String assetName) - throws IOException { - String outputPath = dataDir + File.separator + subdir; - Log.d(TAG, "Copying " + subdir + File.separator + assetName + " to " + outputPath + File.separator + assetName + " ..."); - new File(outputPath).mkdirs(); - - InputStream is = getAssets().open(subdir + File.separator + assetName); - File file = new File(outputPath + File.separator + assetName); - file.setWritable(true); - FileOutputStream os = new FileOutputStream(file); - - byte[] buf = new byte[BUF_SZ]; - while (true) { - int len = is.read(buf, 0, BUF_SZ); - if (len < 0) { - break; - } - os.write(buf, 0, len); - } - os.flush(); - os.close(); - } - private void _setCustomExceptionHandler() { if (mSetUncaughtExceptionHandler) { return; @@ -246,7 +174,7 @@ public class Apple2Activity extends Activity { Log.e(TAG, "onCreate()"); _setCustomExceptionHandler(); - mDataDir = _firstTimeInitialization(); + String dataDir = Apple2DisksMenu.firstTimeAssetsInitialization(this); // get device audio parameters for native OpenSLES mSampleRate = DevicePropertyCalculator.getRecommendedSampleRate(this); @@ -254,7 +182,7 @@ public class Apple2Activity extends Activity { mStereoBufferSize = DevicePropertyCalculator.getRecommendedBufferSize(this, /*isStereo:*/true); Log.d(TAG, "Device sampleRate:" + mSampleRate + " mono bufferSize:" + mMonoBufferSize + " stereo bufferSize:" + mStereoBufferSize); - nativeOnCreate(mDataDir, mSampleRate, mMonoBufferSize, mStereoBufferSize); + nativeOnCreate(dataDir, mSampleRate, mMonoBufferSize, mStereoBufferSize); // NOTE: load preferences after nativeOnCreate ... native CPU thread should still be paused Apple2Preferences.loadPreferences(this); @@ -529,6 +457,19 @@ public class Apple2Activity extends Activity { return mMenuStack.get(lastIndex); } + public synchronized Apple2MenuView peekApple2View(int index) { + int lastIndex = mMenuStack.size() - 1; + if (lastIndex < 0) { + return null; + } + + try { + return mMenuStack.get(index); + } catch (IndexOutOfBoundsException e) { + return null; + } + } + public void dismissAllMenus() { if (mMainMenu != null) { mMainMenu.dismiss(); diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2DisksMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2DisksMenu.java index f35b6c14..cf46151e 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2DisksMenu.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2DisksMenu.java @@ -11,73 +11,299 @@ package org.deadc0de.apple2ix; +import android.app.AlertDialog; import android.content.Context; +import android.content.DialogInterface; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; +import android.os.Environment; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.CheckBox; +import android.widget.Button; +import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.RadioButton; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + import java.io.File; +import java.io.FileOutputStream; import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; import java.util.Arrays; public class Apple2DisksMenu implements Apple2MenuView { private final static String TAG = "Apple2DisksMenu"; + private static String sDataDir = null; private Apple2Activity mActivity = null; private View mDisksView = null; + private final ArrayList mPathStack = new ArrayList<>(); + + private static File sExternalFilesDir = null; + private static boolean sExternalStorageAvailable = false; + private static boolean sInitializedPath = false; + public Apple2DisksMenu(Apple2Activity activity) { mActivity = activity; - setup(); - } - private void setup() { + if (!sInitializedPath) { + sInitializedPath = true; + Apple2Preferences.CURRENT_DISK_PATH.load(mActivity); + } LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mDisksView = inflater.inflate(R.layout.activity_disks, null, false); - RadioButton diskA = (RadioButton) mDisksView.findViewById(R.id.radioButton_diskA); - diskA.setChecked(true); + final Button cancelButton = (Button) mDisksView.findViewById(R.id.cancelButton); + cancelButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Apple2DisksMenu.this.mActivity.dismissAllMenus(); + } + }); - CheckBox readWrite = (CheckBox) mDisksView.findViewById(R.id.checkBox_readWrite); - readWrite.setChecked(false); + if (!sExternalStorageAvailable) { + 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) { + 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; + } + } + } + + // HACK NOTE 2015/02/22 : Apparently native code cannot easily access stuff in the APK ... so copy various resources + // out of the APK and into the /data/data/... for ease of access. Because this is FOSS software we don't care about + // security or DRM for these assets =) + public static String firstTimeAssetsInitialization(Apple2Activity activity) { + + try { + PackageManager pm = activity.getPackageManager(); + PackageInfo pi = pm.getPackageInfo(activity.getPackageName(), 0); + sDataDir = pi.applicationInfo.dataDir; + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "" + e); + System.exit(1); + } + + if (Apple2Preferences.ASSETS_CONFIGURED.booleanValue(activity)) { + return sDataDir; + } + + Log.d(TAG, "First time copying stuff-n-things out of APK for ease-of-NDK access..."); + + try { + String[] shaders = activity.getAssets().list("shaders"); + for (String shader : shaders) { + Apple2DisksMenu.copyFile(activity, "shaders", shader); + } + String[] disks = activity.getAssets().list("disks"); + for (String disk : disks) { + Apple2DisksMenu.copyFile(activity, "disks", disk); + } + } catch (IOException e) { + Log.e(TAG, "problem copying resources : " + e); + System.exit(1); + } + + Log.d(TAG, "Saving default preferences"); + Apple2Preferences.ASSETS_CONFIGURED.saveBoolean(activity, true); + + return sDataDir; + } + + // ------------------------------------------------------------------------ + // Apple2MenuView interface methods + + public final boolean isCalibrating() { + return false; + } + + public void show() { + if (isShowing()) { + return; + } + dynamicSetup(); + mActivity.pushApple2View(this); + } + + public void dismiss() { + String path = popPathStack(); + if (path == null) { + mActivity.popApple2View(this); + } else { + dynamicSetup(); + ListView disksList = (ListView) mDisksView.findViewById(R.id.listView_settings); + disksList.postInvalidate(); + } + } + + public void dismissAll() { + mActivity.popApple2View(this); + } + + public boolean isShowing() { + return mDisksView.isShown(); + } + + public View getView() { + return mDisksView; + } + + // ------------------------------------------------------------------------ + // path stack methods + + public String getPathStackJSON() { + JSONArray jsonArray = new JSONArray(Arrays.asList(mPathStack.toArray())); + return jsonArray.toString(); + } + + public void setPathStackJSON(String pathStackJSON) { + mPathStack.clear(); + try { + JSONArray jsonArray = new JSONArray(pathStackJSON); + for (int i = 0, count = jsonArray.length(); i < count; i++) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + mPathStack.add(jsonObject.toString()); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public void pushPathStack(String path) { + mPathStack.add(path); + Apple2Preferences.CURRENT_DISK_PATH.saveString(mActivity, getPathStackJSON()); + } + + public String popPathStack() { + if (mPathStack.size() == 0) { + return null; + } + String path = mPathStack.remove(mPathStack.size() - 1); + Apple2Preferences.CURRENT_DISK_PATH.saveString(mActivity, getPathStackJSON()); + return path; + } + + // ------------------------------------------------------------------------ + // internals ... + + private String pathStackAsDirectory() { + if (mPathStack.size() == 0) { + return null; + } + StringBuilder pathBuffer = new StringBuilder(); + for (String component : mPathStack) { + pathBuffer.append(component); + pathBuffer.append(File.separator); + } + return pathBuffer.toString(); + } + + private static void copyFile(Apple2Activity activity, String subdir, String assetName) + 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) { + Log.d(TAG, "WARNING, cannot mkdirs on path : " + outputPath); + } + + InputStream is = activity.getAssets().open(subdir + File.separator + assetName); + File file = new File(outputPath + File.separator + assetName); + boolean madeWriteable = file.setWritable(true); + if (!madeWriteable) { + Log.d(TAG, "WARNING, cannot make a copied file writeable for asset : " + assetName); + } + FileOutputStream os = new FileOutputStream(file); + + final int BUF_SZ = 4096; + byte[] buf = new byte[BUF_SZ]; + while (true) { + int len = is.read(buf, 0, BUF_SZ); + if (len < 0) { + break; + } + os.write(buf, 0, len); + } + os.flush(); + os.close(); } private void dynamicSetup() { - final ListView disksList = (ListView)mDisksView.findViewById(R.id.listView_settings); + final ListView disksList = (ListView) mDisksView.findViewById(R.id.listView_settings); disksList.setEnabled(true); - String dataDir = mActivity.getDataDir() + File.separator + "disks"; - File dir = new File(dataDir); + String disksDir = pathStackAsDirectory(); + boolean isRootPath = false; + if (disksDir == null) { + isRootPath = true; + disksDir = sDataDir + File.separator + "disks"; // default path + } + + File dir = new File(disksDir); final File[] files = dir.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { name = name.toLowerCase(); - boolean acceptable = name.endsWith(".dsk") || name.endsWith(".do") || name.endsWith(".po") || name.endsWith(".nib") || - name.endsWith(".dsk.gz") || name.endsWith(".do.gz") || name.endsWith(".po.gz") || name.endsWith(".nib.gz"); - return acceptable; + if (name.equalsIgnoreCase(".")) { + return false; + } + if (name.equalsIgnoreCase("..")) { + return false; + } + + if (name.endsWith(".dsk") || name.endsWith(".do") || name.endsWith(".po") || name.endsWith(".nib") || name.endsWith(".dsk.gz") || name.endsWith(".do.gz") || name.endsWith(".po.gz") || name.endsWith(".nib.gz")) { + return true; + } + + File file = new File(dir, name); + return file.isDirectory(); } }); Arrays.sort(files); - int len = files.length; - final String[] fileNames = new String[len]; - final boolean[] isDirectory = new boolean[len]; - for (int i=0; i adapter = new ArrayAdapter(mActivity, R.layout.a2disk, R.id.a2disk_title, fileNames) { @@ -85,11 +311,12 @@ public class Apple2DisksMenu implements Apple2MenuView { public boolean areAllItemsEnabled() { return true; } + @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); - LinearLayout layout = (LinearLayout)view.findViewById(R.id.a2disk_widget_frame); + LinearLayout layout = (LinearLayout) view.findViewById(R.id.a2disk_widget_frame); if (layout.getChildCount() > 0) { // layout cells appear to be reused when scrolling into view ... make sure we start with clear hierarchy layout.removeAllViews(); @@ -105,43 +332,68 @@ public class Apple2DisksMenu implements Apple2MenuView { } }; + final int offset = includeExternalStoragePath ? 1 : 0; disksList.setAdapter(adapter); disksList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { + public void onItemClick(AdapterView parent, View view, final int position, long id) { if (isDirectory[position]) { - // TODO FIXME ... + Log.d(TAG, "Descending to path : " + fileNames[position]); + pushPathStack(fileNames[position]); + dynamicSetup(); + ListView disksList = (ListView) mDisksView.findViewById(R.id.listView_settings); + disksList.postInvalidate(); } else { - RadioButton diskA = (RadioButton) mDisksView.findViewById(R.id.radioButton_diskA); - CheckBox readWrite = (CheckBox) mDisksView.findViewById(R.id.checkBox_readWrite); - Apple2DisksMenu.this.dismiss(); - mActivity.nativeChooseDisk(files[position].getAbsolutePath(), diskA.isChecked(), !readWrite.isChecked()); + String title = mActivity.getResources().getString(R.string.header_disks); + title = title + " " + fileNames[position]; + + AlertDialog.Builder builder = new AlertDialog.Builder(mActivity).setCancelable(true).setMessage(title); + LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + final View diskConfirmationView = inflater.inflate(R.layout.a2disk_confirmation, null, false); + builder.setView(diskConfirmationView); + + final RadioButton diskA = (RadioButton) diskConfirmationView.findViewById(R.id.radioButton_diskA); + diskA.setChecked(Apple2Preferences.CURRENT_DISK_A.booleanValue(mActivity)); + diskA.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + Apple2Preferences.CURRENT_DISK_A.saveBoolean(mActivity, isChecked); + } + }); + final RadioButton diskB = (RadioButton) diskConfirmationView.findViewById(R.id.radioButton_diskB); + diskB.setChecked(!Apple2Preferences.CURRENT_DISK_A.booleanValue(mActivity)); + + + final RadioButton readOnly = (RadioButton) diskConfirmationView.findViewById(R.id.radioButton_readOnly); + readOnly.setChecked(Apple2Preferences.CURRENT_DISK_RO.booleanValue(mActivity)); + readOnly.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + Apple2Preferences.CURRENT_DISK_RO.saveBoolean(mActivity, isChecked); + } + }); + + final RadioButton readWrite = (RadioButton) diskConfirmationView.findViewById(R.id.radioButton_readWrite); + readWrite.setChecked(!Apple2Preferences.CURRENT_DISK_RO.booleanValue(mActivity)); + + builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + mActivity.dismissAllMenus(); + mActivity.nativeChooseDisk(files[position - offset].getAbsolutePath(), diskA.isChecked(), readOnly.isChecked()); + } + }); + + builder.show(); } } }); } - - public final boolean isCalibrating() { - return false; - } - - public void show() { - if (isShowing()) { - return; - } - dynamicSetup(); - mActivity.pushApple2View(this); - } - - public void dismiss() { - mActivity.popApple2View(this); - } - - public boolean isShowing() { - return mDisksView.isShown(); - } - - public View getView() { - return mDisksView; - } } diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickCalibration.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickCalibration.java index d4969368..a552128f 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickCalibration.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickCalibration.java @@ -87,7 +87,9 @@ public class Apple2JoystickCalibration implements Apple2MenuView { public void dismiss() { for (Apple2MenuView apple2MenuView : mViewStack) { - mActivity.pushApple2View(apple2MenuView); + if (apple2MenuView != this) { + mActivity.pushApple2View(apple2MenuView); + } } Apple2Preferences.nativeSetTouchMenuEnabled(mTouchMenuEnabled); @@ -97,6 +99,10 @@ public class Apple2JoystickCalibration implements Apple2MenuView { mActivity.popApple2View(this); } + public void dismissAll() { + dismiss(); + } + public boolean isShowing() { return mSettingsView.isShown(); } diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickSettingsMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickSettingsMenu.java index 146dc18c..9ae10772 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickSettingsMenu.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickSettingsMenu.java @@ -210,7 +210,7 @@ public class Apple2JoystickSettingsMenu extends Apple2AbstractMenu { @Override public void handleSelection(Apple2Activity activity, Apple2AbstractMenu settingsMenu, boolean isChecked) { - ArrayList viewStack = new ArrayList(); + ArrayList viewStack = new ArrayList<>(); { int idx = 0; while (true) { diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2KeypadSettingsMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2KeypadSettingsMenu.java index 878daa10..98b42f37 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2KeypadSettingsMenu.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2KeypadSettingsMenu.java @@ -63,7 +63,28 @@ public class Apple2KeypadSettingsMenu extends Apple2AbstractMenu { @Override public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) { - //new Apple2KeypadChooser(activity).show(); + ArrayList viewStack = new ArrayList<>(); + { + int idx = 0; + while (true) { + Apple2MenuView apple2MenuView = activity.peekApple2View(idx); + if (apple2MenuView == null) { + break; + } + viewStack.add(apple2MenuView); + ++idx; + } + } + + Apple2KeypadChooser chooser = new Apple2KeypadChooser(activity, viewStack); + + // show this new view... + chooser.show(); + + // ...with nothing else underneath 'cept the emulator OpenGL layer + for (Apple2MenuView apple2MenuView : viewStack) { + activity.popApple2View(apple2MenuView); + } } }, KEYPAD_CALIBRATE { @@ -79,7 +100,7 @@ public class Apple2KeypadSettingsMenu extends Apple2AbstractMenu { @Override public void handleSelection(Apple2Activity activity, Apple2AbstractMenu settingsMenu, boolean isChecked) { - ArrayList viewStack = new ArrayList(); + ArrayList viewStack = new ArrayList<>(); { int idx = 0; while (true) { diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MenuView.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MenuView.java index 4ffad6cd..d8d348a1 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MenuView.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MenuView.java @@ -21,6 +21,8 @@ public interface Apple2MenuView { public void dismiss(); + public void dismissAll(); + public View getView(); public boolean isCalibrating(); diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Preferences.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Preferences.java index 82008eea..8d7d8a7d 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Preferences.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Preferences.java @@ -14,9 +14,12 @@ package org.deadc0de.apple2ix; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.util.Log; + +import java.io.File; public enum Apple2Preferences { - PREFS_CONFIGURED { + ASSETS_CONFIGURED { @Override public void load(Apple2Activity activity) { // ... @@ -27,6 +30,60 @@ public enum Apple2Preferences { activity.getPreferences(Context.MODE_PRIVATE).edit().putBoolean(toString(), true).apply(); } }, + CURRENT_DISK_PATH { + @Override + public void load(final Apple2Activity activity) { + Apple2MainMenu mainMenu = activity.getMainMenu(); + if (mainMenu != null) { + mainMenu.getDisksMenu().setPathStackJSON(stringValue(activity)); + } + } + + @Override + public String stringValue(Apple2Activity activity) { + return activity.getPreferences(Context.MODE_PRIVATE).getString(toString(), "[]"); + } + + @Override + public void saveString(Apple2Activity activity, String value) { + activity.getPreferences(Context.MODE_PRIVATE).edit().putString(toString(), value).apply(); + //load(activity); + } + }, + CURRENT_DISK_A { + @Override + public void load(final Apple2Activity activity) { + /* ... */ + } + + @Override + public boolean booleanValue(Apple2Activity activity) { + return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true); + } + + @Override + public void saveBoolean(Apple2Activity activity, boolean value) { + activity.getPreferences(Context.MODE_PRIVATE).edit().putBoolean(toString(), value).apply(); + //load(activity); + } + }, + CURRENT_DISK_RO { + @Override + public void load(final Apple2Activity activity) { + /* ... */ + } + + @Override + public boolean booleanValue(Apple2Activity activity) { + return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true); + } + + @Override + public void saveBoolean(Apple2Activity activity, boolean value) { + activity.getPreferences(Context.MODE_PRIVATE).edit().putBoolean(toString(), value).apply(); + //load(activity); + } + }, CPU_SPEED_PERCENT { @Override public void load(Apple2Activity activity) { @@ -368,6 +425,11 @@ public enum Apple2Preferences { throw new RuntimeException("DENIED! You're doing it wrong! =P"); } + public void saveString(Apple2Activity activity, String value) { + activity.getPreferences(Context.MODE_PRIVATE).edit().putString(toString(), value).apply(); + load(activity); + } + public void saveHiresColor(Apple2Activity activity, HiresColor value) { activity.getPreferences(Context.MODE_PRIVATE).edit().putInt(toString(), value.ordinal()).apply(); load(activity); @@ -402,6 +464,10 @@ public enum Apple2Preferences { return (float) activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 0); } + public String stringValue(Apple2Activity activity) { + return activity.getPreferences(Context.MODE_PRIVATE).getString(toString(), null); + } + public static void loadPreferences(Apple2Activity activity) { for (Apple2Preferences pref : Apple2Preferences.values()) { pref.load(activity); diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SplashScreen.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SplashScreen.java index c9bb068d..1413a714 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SplashScreen.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SplashScreen.java @@ -68,6 +68,10 @@ public class Apple2SplashScreen implements Apple2MenuView { mActivity.popApple2View(this); } + public void dismissAll() { + dismiss(); + } + public boolean isShowing() { return mSettingsView.isShown(); } diff --git a/Android/app/src/main/res/layout/a2disk_confirmation.xml b/Android/app/src/main/res/layout/a2disk_confirmation.xml new file mode 100644 index 00000000..78c43458 --- /dev/null +++ b/Android/app/src/main/res/layout/a2disk_confirmation.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Android/app/src/main/res/layout/activity_disks.xml b/Android/app/src/main/res/layout/activity_disks.xml index 28bae324..e547e020 100644 --- a/Android/app/src/main/res/layout/activity_disks.xml +++ b/Android/app/src/main/res/layout/activity_disks.xml @@ -6,39 +6,30 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" > - - - + android:baselineAligned="false" + android:layout_width="fill_parent" + android:layout_height="wrap_content" > - + android:text="@string/header_disks" /> - + android:drawableLeft="@android:drawable/ic_menu_close_clear_cancel" + android:drawableStart="@android:drawable/ic_menu_close_clear_cancel" + android:id="@+id/cancelButton" /> - - + Interpolated color Drive 1 Drive 2 + Read only Read/write Continue… Preferences…