mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-06-26 00:29:27 +00:00
First cut at Android disk selection interface
This commit is contained in:
parent
ae27a891dd
commit
e808dd9861
|
@ -39,6 +39,8 @@ public class Apple2Activity extends Activity {
|
|||
private final static int SOFTKEYBOARD_THRESHOLD = 50;
|
||||
private final static int MAX_FINGERS = 32;// HACK ...
|
||||
|
||||
private String mDataDir = null;
|
||||
|
||||
private Apple2View mView = null;
|
||||
private AlertDialog mQuitDialog = null;
|
||||
private AlertDialog mRebootDialog = null;
|
||||
|
@ -77,6 +79,7 @@ public class Apple2Activity extends Activity {
|
|||
|
||||
public native void nativeEnableTouchJoystick(boolean visibility);
|
||||
public native void nativeSetColor(int color);
|
||||
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
|
||||
|
@ -152,8 +155,8 @@ public class Apple2Activity extends Activity {
|
|||
super.onCreate(savedInstanceState);
|
||||
Log.e(TAG, "onCreate()");
|
||||
|
||||
String dataDir = firstTimeInitialization();
|
||||
nativeOnCreate(dataDir);
|
||||
mDataDir = firstTimeInitialization();
|
||||
nativeOnCreate(mDataDir);
|
||||
|
||||
mView = new Apple2View(this);
|
||||
setContentView(mView);
|
||||
|
@ -214,9 +217,13 @@ public class Apple2Activity extends Activity {
|
|||
}
|
||||
|
||||
Apple2SettingsMenu settingsMenu = mView.getSettingsMenu();
|
||||
Apple2DisksMenu disksMenu = mView.getDisksMenu();
|
||||
if (settingsMenu != null) {
|
||||
settingsMenu.dismissWithoutResume();
|
||||
}
|
||||
if (disksMenu != null) {
|
||||
disksMenu.dismissWithoutResume();
|
||||
}
|
||||
|
||||
boolean someMenuShowing = mainMenu.isShowing() ||
|
||||
(mQuitDialog != null && mQuitDialog.isShowing()) ||
|
||||
|
@ -237,9 +244,12 @@ public class Apple2Activity extends Activity {
|
|||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
Apple2SettingsMenu settingsMenu = mView.getSettingsMenu();
|
||||
Apple2DisksMenu disksMenu = mView.getDisksMenu();
|
||||
if (settingsMenu != null) {
|
||||
if (settingsMenu.isShowing()) {
|
||||
settingsMenu.dismiss();
|
||||
} else if (disksMenu.isShowing()) {
|
||||
disksMenu.dismiss();
|
||||
} else {
|
||||
mView.showMainMenu();
|
||||
}
|
||||
|
@ -304,9 +314,13 @@ public class Apple2Activity extends Activity {
|
|||
}
|
||||
|
||||
Apple2SettingsMenu settingsMenu = mainMenu.getSettingsMenu();
|
||||
Apple2DisksMenu disksMenu = mView.getDisksMenu();
|
||||
if (settingsMenu != null && settingsMenu.isShowing()) {
|
||||
break;
|
||||
}
|
||||
if (disksMenu != null && disksMenu.isShowing()) {
|
||||
break;
|
||||
}
|
||||
|
||||
//printSamples(event);
|
||||
int action = event.getActionMasked();
|
||||
|
@ -396,6 +410,14 @@ public class Apple2Activity extends Activity {
|
|||
nativeGraphicsInitialized(width, height);
|
||||
}
|
||||
|
||||
public Apple2View getView() {
|
||||
return mView;
|
||||
}
|
||||
|
||||
public String getDataDir() {
|
||||
return mDataDir;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return mWidth;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Apple // emulator for *nix
|
||||
*
|
||||
* This software package is subject to the GNU General Public License
|
||||
* version 2 or later (your choice) as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* THERE ARE NO WARRANTIES WHATSOEVER.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.deadc0de.apple2ix;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
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.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.RadioButton;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Apple2DisksMenu {
|
||||
|
||||
private final static String TAG = "Apple2DisksMenu";
|
||||
|
||||
private Apple2Activity mActivity = null;
|
||||
private Apple2View mParentView = null;
|
||||
private View mDisksView = null;
|
||||
|
||||
public Apple2DisksMenu(Apple2Activity activity, Apple2View parent) {
|
||||
mActivity = activity;
|
||||
mParentView = parent;
|
||||
setup();
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
|
||||
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);
|
||||
|
||||
CheckBox readWrite = (CheckBox) mDisksView.findViewById(R.id.checkBox_readWrite);
|
||||
readWrite.setChecked(false);
|
||||
}
|
||||
|
||||
private void dynamicSetup() {
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
Arrays.sort(files);
|
||||
int len = files.length;
|
||||
final String[] fileNames = new String[len];
|
||||
final boolean[] isDirectory = new boolean[len];
|
||||
|
||||
for (int i=0; i<files.length; i++) {
|
||||
File file = files[i];
|
||||
fileNames[i] = file.getName();
|
||||
isDirectory[i] = file.isDirectory();
|
||||
}
|
||||
|
||||
ArrayAdapter<?> adapter = new ArrayAdapter<String>(mActivity, R.layout.a2disk, R.id.a2disk_title, fileNames) {
|
||||
@Override
|
||||
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);
|
||||
if (layout.getChildCount() > 0) {
|
||||
// layout cells appear to be reused when scrolling into view ... make sure we start with clear hierarchy
|
||||
layout.removeAllViews();
|
||||
}
|
||||
|
||||
if (isDirectory[position]) {
|
||||
ImageView imageView = new ImageView(mActivity);
|
||||
Drawable drawable = mActivity.getResources().getDrawable(android.R.drawable.ic_menu_more);
|
||||
imageView.setImageDrawable(drawable);
|
||||
layout.addView(imageView);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
};
|
||||
|
||||
disksList.setAdapter(adapter);
|
||||
disksList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (isDirectory[position]) {
|
||||
// TODO FIXME ...
|
||||
} else {
|
||||
RadioButton diskA = (RadioButton)mDisksView.findViewById(R.id.radioButton_diskA);
|
||||
CheckBox readWrite = (CheckBox)mDisksView.findViewById(R.id.checkBox_readWrite);
|
||||
mActivity.nativeChooseDisk(files[position].getAbsolutePath(), diskA.isChecked(), !readWrite.isChecked());
|
||||
Apple2DisksMenu.this.dismissWithoutResume();
|
||||
Apple2DisksMenu.this.mActivity.getView().showMainMenu();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (isShowing()) {
|
||||
return;
|
||||
}
|
||||
dynamicSetup();
|
||||
mActivity.nativeOnPause();
|
||||
mActivity.addContentView(mDisksView, new FrameLayout.LayoutParams(mActivity.getWidth(), mActivity.getHeight()));
|
||||
}
|
||||
|
||||
public void dismiss() {
|
||||
if (isShowing()) {
|
||||
dismissWithoutResume();
|
||||
mActivity.nativeOnResume();
|
||||
}
|
||||
}
|
||||
|
||||
public void dismissWithoutResume() {
|
||||
if (isShowing()) {
|
||||
((ViewGroup)mDisksView.getParent()).removeView(mDisksView);
|
||||
// HACK FIXME TODO ... we seem to lose ability to toggle/show soft keyboard upon dismissal of mDisksView after use.
|
||||
// This hack appears to get the Android UI unwedged ... =P
|
||||
Apple2MainMenu androidUIFTW = mParentView.getMainMenu();
|
||||
androidUIFTW.show();
|
||||
androidUIFTW.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return mDisksView.isShown();
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ public class Apple2MainMenu {
|
|||
private Apple2View mParentView = null;
|
||||
private PopupWindow mMainMenuPopup = null;
|
||||
private Apple2SettingsMenu mSettingsMenu = null;
|
||||
private Apple2DisksMenu mDisksMenu = null;
|
||||
|
||||
public Apple2MainMenu(Apple2Activity activity, Apple2View parent) {
|
||||
mActivity = activity;
|
||||
|
@ -161,7 +162,8 @@ public class Apple2MainMenu {
|
|||
mMainMenuPopup.setOnDismissListener(new PopupWindow.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss() {
|
||||
if ( !(getSettingsMenu().isShowing() /*|| getDisksMenu().isShowing()*/) ) {
|
||||
boolean otherMenusShowing = (getSettingsMenu().isShowing() || getDisksMenu().isShowing());
|
||||
if (!otherMenusShowing) {
|
||||
Apple2MainMenu.this.mActivity.nativeOnResume();
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +171,9 @@ public class Apple2MainMenu {
|
|||
}
|
||||
|
||||
public void showDisksMenu() {
|
||||
Log.d(TAG, "showDisksMenu...");
|
||||
Apple2DisksMenu disksMenu = getDisksMenu();
|
||||
disksMenu.show();
|
||||
mMainMenuPopup.dismiss();
|
||||
}
|
||||
|
||||
public void showSettings() {
|
||||
|
@ -178,6 +182,13 @@ public class Apple2MainMenu {
|
|||
mMainMenuPopup.dismiss();
|
||||
}
|
||||
|
||||
public synchronized Apple2DisksMenu getDisksMenu() {
|
||||
if (mDisksMenu == null) {
|
||||
mDisksMenu = new Apple2DisksMenu(mActivity, mParentView);
|
||||
}
|
||||
return mDisksMenu;
|
||||
}
|
||||
|
||||
public synchronized Apple2SettingsMenu getSettingsMenu() {
|
||||
if (mSettingsMenu == null) {
|
||||
mSettingsMenu = new Apple2SettingsMenu(mActivity, mParentView);
|
||||
|
|
|
@ -93,7 +93,8 @@ class Apple2View extends GLSurfaceView {
|
|||
public void showMainMenu() {
|
||||
if (mMainMenu != null) {
|
||||
Apple2SettingsMenu settingsMenu = mMainMenu.getSettingsMenu();
|
||||
if (!settingsMenu.isShowing()) {
|
||||
Apple2DisksMenu disksMenu = mMainMenu.getDisksMenu();
|
||||
if (! (settingsMenu.isShowing() || disksMenu.isShowing()) ) {
|
||||
mMainMenu.show();
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +108,10 @@ class Apple2View extends GLSurfaceView {
|
|||
return (mMainMenu == null) ? null : mMainMenu.getSettingsMenu();
|
||||
}
|
||||
|
||||
public Apple2DisksMenu getDisksMenu() {
|
||||
return (mMainMenu == null) ? null : mMainMenu.getDisksMenu();
|
||||
}
|
||||
|
||||
public void toggleKeyboard() {
|
||||
InputMethodManager inputMethodManager=(InputMethodManager)mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
inputMethodManager.toggleSoftInputFromWindow(getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0);
|
||||
|
|
61
Android/app/src/main/res/layout/a2disk.xml
Normal file
61
Android/app/src/main/res/layout/a2disk.xml
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2006 The Android Open Source Project
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- Modified from Gingerbread android.R.layout.preference -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingRight="?android:attr/scrollbarSize">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dip"
|
||||
android:layout_marginRight="6dip"
|
||||
android:layout_marginTop="6dip"
|
||||
android:layout_marginBottom="6dip"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView android:id="@+id/a2disk_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal" />
|
||||
|
||||
<!--
|
||||
<TextView android:id="@+id/a2disk_summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/a2preference_title"
|
||||
android:layout_alignLeft="@id/a2preference_title"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:maxLines="4" />
|
||||
-->
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- Custom preference should place its actual preference widget here. -->
|
||||
<LinearLayout android:id="@+id/a2disk_widget_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:descendantFocusability="blocksDescendants" />
|
||||
|
||||
</LinearLayout>
|
48
Android/app/src/main/res/layout/activity_disks.xml
Normal file
48
Android/app/src/main/res/layout/activity_disks.xml
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:background="@color/black"
|
||||
android:orientation="vertical"
|
||||
android:baselineAligned="false"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/header_disks"
|
||||
style="?android:attr/listSeparatorTextViewStyle"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/header_disks" />
|
||||
|
||||
<RadioGroup
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<RadioButton
|
||||
android:layout_weight="1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/diskA"
|
||||
android:id="@+id/radioButton_diskA" />
|
||||
|
||||
<RadioButton
|
||||
android:layout_weight="1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/diskB"
|
||||
android:id="@+id/radioButton_diskB" />
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/disk_read_write"
|
||||
android:id="@+id/checkBox_readWrite" />
|
||||
</RadioGroup>
|
||||
|
||||
<ListView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dp"
|
||||
android:id="@+id/listView_settings"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
|
@ -15,6 +15,10 @@
|
|||
<string name="configure_joystick_summary">TouchJoy axis and buttons, hitboxes, etc</string>
|
||||
<string name="configure_video">Configure video…</string>
|
||||
<string name="configure_video_summary">Color settings</string>
|
||||
<string name="diskA">Drive 1</string>
|
||||
<string name="diskB">Drive 2</string>
|
||||
<string name="disk_read_write">Read/write</string>
|
||||
<string name="header_disks">Insert disk:</string>
|
||||
<string name="joystick">Joystick</string>
|
||||
<string name="joystick_keyA">Key Joystick 1</string>
|
||||
<string name="joystick_keyB">Key Joystick 2</string>
|
||||
|
|
|
@ -276,3 +276,23 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeSetColor(JNIEnv *env, jobje
|
|||
video_redraw();
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeChooseDisk(JNIEnv *env, jobject obj, jstring jPath, jboolean driveA, jboolean readOnly) {
|
||||
const char *path = (*env)->GetStringUTFChars(env, jPath, 0);
|
||||
int drive = driveA ? 0 : 1;
|
||||
int ro = readOnly ? 1 : 0;
|
||||
LOG("nativeChooseDisk(%s, %s, %s)", path, driveA ? "drive A" : "drive B", readOnly ? "read only" : "read/write");
|
||||
if (c_new_diskette_6(drive, path, ro)) {
|
||||
char *gzPath = NULL;
|
||||
asprintf(&gzPath, "%s.gz", path);
|
||||
if (c_new_diskette_6(drive, gzPath, ro)) {
|
||||
// TODO FIXME : show error message disk was unreadable ...
|
||||
} else {
|
||||
// TODO FIXME : show an OpenGL message that the disk was chosen ...
|
||||
}
|
||||
FREE(gzPath);
|
||||
} else {
|
||||
// TODO FIXME : show an OpenGL message that the disk was chosen ...
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, jPath, path);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user