2012-08-07 00:04:38 +00:00
|
|
|
package com.froop.app.kegs;
|
|
|
|
|
2012-09-21 05:02:01 +00:00
|
|
|
import android.app.ActionBar;
|
2012-08-07 00:04:38 +00:00
|
|
|
import android.app.Activity;
|
|
|
|
import android.app.AlertDialog;
|
|
|
|
import android.app.Dialog;
|
|
|
|
import android.app.DialogFragment;
|
|
|
|
import android.app.ProgressDialog;
|
2012-08-21 10:41:05 +00:00
|
|
|
import android.content.Context;
|
2012-08-07 00:04:38 +00:00
|
|
|
import android.content.DialogInterface;
|
2012-09-21 05:02:01 +00:00
|
|
|
import android.content.res.Configuration;
|
2012-10-03 22:32:11 +00:00
|
|
|
import android.graphics.Rect;
|
2012-08-07 00:04:38 +00:00
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.AsyncTask;
|
|
|
|
import android.util.Log;
|
2012-08-21 10:41:05 +00:00
|
|
|
import android.view.inputmethod.InputMethodManager;
|
2012-08-07 00:04:38 +00:00
|
|
|
import android.view.GestureDetector;
|
2012-08-21 10:41:05 +00:00
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuItem;
|
2012-08-07 00:04:38 +00:00
|
|
|
import android.view.View;
|
|
|
|
import android.view.KeyEvent;
|
|
|
|
import android.view.MotionEvent;
|
|
|
|
import android.view.View.OnTouchListener;
|
|
|
|
import android.widget.Button;
|
2012-08-21 10:41:05 +00:00
|
|
|
import android.widget.PopupMenu;
|
2012-08-07 00:04:38 +00:00
|
|
|
import android.widget.ToggleButton;
|
|
|
|
|
|
|
|
public class KegsMain extends Activity implements KegsKeyboard.StickyReset {
|
|
|
|
private static final String FRAGMENT_ROM = "rom";
|
|
|
|
private static final String FRAGMENT_DOWNLOAD = "download";
|
|
|
|
private static final String FRAGMENT_ERROR = "error";
|
2012-08-21 10:41:05 +00:00
|
|
|
private static final String FRAGMENT_SPEED = "speed";
|
2012-08-07 00:04:38 +00:00
|
|
|
|
2012-08-21 10:41:05 +00:00
|
|
|
protected KegsView mKegsView;
|
2012-08-07 00:04:38 +00:00
|
|
|
private KegsTouch mKegsTouch;
|
|
|
|
private KegsKeyboard mKegsKeyboard;
|
2012-08-21 10:41:05 +00:00
|
|
|
private TouchJoystick mJoystick;
|
|
|
|
|
|
|
|
private PopupMenu mSettingsMenu;
|
|
|
|
private boolean mModeMouse = true;
|
2012-10-04 04:51:49 +00:00
|
|
|
private int mLastActionBar = 0; // window height at last ActionBar change.
|
2012-08-07 00:04:38 +00:00
|
|
|
|
|
|
|
private View.OnClickListener mButtonClick = new View.OnClickListener() {
|
|
|
|
public void onClick(View v) {
|
|
|
|
// Log.e("kegs", "button clicked");
|
2012-08-21 10:41:05 +00:00
|
|
|
final int click_id = v.getId();
|
2012-08-07 00:04:38 +00:00
|
|
|
int key_id = -1;
|
|
|
|
boolean sticky = false;
|
|
|
|
if (click_id == R.id.key_escape) {
|
|
|
|
key_id = KegsKeyboard.KEY_ESCAPE;
|
|
|
|
} else if (click_id == R.id.key_return) {
|
|
|
|
key_id = KegsKeyboard.KEY_RETURN;
|
|
|
|
} else if (click_id == R.id.key_f4) {
|
|
|
|
key_id = KegsKeyboard.KEY_F4;
|
|
|
|
} else if (click_id == R.id.key_tab) {
|
|
|
|
key_id = KegsKeyboard.KEY_TAB;
|
|
|
|
} else if (click_id == R.id.key_control) {
|
|
|
|
key_id = KegsKeyboard.KEY_CONTROL;
|
|
|
|
sticky = true;
|
|
|
|
} else if (click_id == R.id.key_open_apple) {
|
|
|
|
key_id = KegsKeyboard.KEY_OPEN_APPLE;
|
|
|
|
sticky = true;
|
|
|
|
} else if (click_id == R.id.key_closed_apple) {
|
|
|
|
key_id = KegsKeyboard.KEY_CLOSED_APPLE;
|
|
|
|
sticky = true;
|
|
|
|
} else if (click_id == R.id.key_left) {
|
|
|
|
key_id = KegsKeyboard.KEY_LEFT;
|
|
|
|
} else if (click_id == R.id.key_right) {
|
|
|
|
key_id = KegsKeyboard.KEY_RIGHT;
|
|
|
|
} else if (click_id == R.id.key_up) {
|
|
|
|
key_id = KegsKeyboard.KEY_UP;
|
|
|
|
} else if (click_id == R.id.key_down) {
|
|
|
|
key_id = KegsKeyboard.KEY_DOWN;
|
|
|
|
} else {
|
|
|
|
Log.e("kegs", "UNKNOWN BUTTON " + click_id + " CLICKED");
|
|
|
|
}
|
|
|
|
if (key_id != -1) {
|
|
|
|
if (sticky) {
|
|
|
|
mKegsKeyboard.keyDownSticky(key_id, !((ToggleButton)v).isChecked());
|
|
|
|
} else {
|
|
|
|
mKegsKeyboard.keyDownUp(key_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-08-21 10:41:05 +00:00
|
|
|
private PopupMenu.OnMenuItemClickListener mSettingsClick = new PopupMenu.OnMenuItemClickListener() {
|
|
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
|
|
final int item_id = item.getItemId();
|
|
|
|
if (item_id == R.id.input_mouse) {
|
|
|
|
mModeMouse = !mModeMouse;
|
|
|
|
return true;
|
|
|
|
} else if (item_id == R.id.input_keyboard) {
|
|
|
|
// There doesn't seem to be a reliable way to determine the current state, so we have to just toggle it.
|
|
|
|
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
|
|
if (imm != null) {
|
|
|
|
imm.toggleSoftInput(0, 0);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else if (item_id == R.id.input_controls) {
|
|
|
|
final int vis = areControlsVisible() ? View.GONE : View.VISIBLE;
|
|
|
|
findViewById(R.id.b1).setVisibility(vis);
|
|
|
|
findViewById(R.id.b2).setVisibility(vis);
|
|
|
|
return true;
|
|
|
|
} else if (item_id == R.id.emulation_speed) {
|
|
|
|
new SpeedFragment().show(getFragmentManager(), FRAGMENT_SPEED);
|
|
|
|
return true;
|
2012-10-13 00:25:04 +00:00
|
|
|
} else if (item_id == R.id.warm_reset) {
|
|
|
|
mKegsView.doWarmReset();
|
|
|
|
return true;
|
2012-08-21 10:41:05 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private boolean areControlsVisible() {
|
|
|
|
return findViewById(R.id.b1).getVisibility() == View.VISIBLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust items to say "Use Joystick" vs "Use Mouse", etc.
|
|
|
|
private void updateSettingsMenu() {
|
|
|
|
final Menu m = mSettingsMenu.getMenu();
|
|
|
|
MenuItem item;
|
|
|
|
item = m.findItem(R.id.input_mouse);
|
|
|
|
item.setTitle(mModeMouse ? R.string.input_joystick : R.string.input_mouse);
|
|
|
|
|
|
|
|
item = m.findItem(R.id.input_controls);
|
|
|
|
item.setTitle(areControlsVisible() ? R.string.input_controls_hide : R.string.input_controls_show);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void showPopup(View v) {
|
|
|
|
updateSettingsMenu();
|
|
|
|
mSettingsMenu.show();
|
|
|
|
}
|
|
|
|
|
2012-08-07 00:04:38 +00:00
|
|
|
public void onStickyReset() {
|
|
|
|
((ToggleButton)findViewById(R.id.key_control)).setChecked(false);
|
|
|
|
((ToggleButton)findViewById(R.id.key_open_apple)).setChecked(false);
|
|
|
|
((ToggleButton)findViewById(R.id.key_closed_apple)).setChecked(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void getRomFile(String romfile) {
|
|
|
|
final DialogFragment download = new DownloadDialogFragment();
|
|
|
|
download.show(getFragmentManager(), FRAGMENT_DOWNLOAD);
|
|
|
|
new DownloadRom().execute(romfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
class DownloadRom extends AsyncTask<String, Void, Boolean> {
|
|
|
|
private String mRomfile;
|
|
|
|
protected Boolean doInBackground(String ... raw_romfile) {
|
|
|
|
mRomfile = raw_romfile[0];
|
|
|
|
return new DownloadHelper().save(
|
|
|
|
"http://jsan.co/" + mRomfile, Config.mPath.getPath() + "/" + mRomfile);
|
|
|
|
}
|
|
|
|
protected void onPostExecute(Boolean success) {
|
|
|
|
final DialogFragment frag = (DialogFragment)getFragmentManager().findFragmentByTag(FRAGMENT_DOWNLOAD);
|
|
|
|
if (frag != null) {
|
|
|
|
frag.dismiss();
|
|
|
|
}
|
|
|
|
if (!success) {
|
|
|
|
if (!isCancelled()) {
|
|
|
|
final DialogFragment dialog = new ErrorDialogFragment();
|
|
|
|
dialog.show(getFragmentManager(), FRAGMENT_ERROR);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Config.checkConfig(mRomfile);
|
|
|
|
mKegsView.setReady(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class DownloadDialogFragment extends DialogFragment {
|
|
|
|
@Override
|
|
|
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
|
|
ProgressDialog dialog = new ProgressDialog(getActivity());
|
|
|
|
// TODO: should probably use an XML layout for this.
|
|
|
|
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
2012-08-12 07:12:20 +00:00
|
|
|
dialog.setMessage(getResources().getText(R.string.rom_check));
|
2012-08-07 00:04:38 +00:00
|
|
|
dialog.setProgressNumberFormat(null);
|
2012-10-03 22:32:11 +00:00
|
|
|
if (android.os.Build.VERSION.SDK_INT >= 11) {
|
|
|
|
dialog.setProgressPercentFormat(null);
|
|
|
|
}
|
2012-08-07 00:04:38 +00:00
|
|
|
dialog.setIndeterminate(true);
|
|
|
|
dialog.setCancelable(false);
|
|
|
|
dialog.setCanceledOnTouchOutside(false); // lame
|
|
|
|
return dialog;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class ErrorDialogFragment extends DialogFragment {
|
|
|
|
@Override
|
|
|
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
2012-08-12 07:12:20 +00:00
|
|
|
builder.setMessage(getResources().getText(R.string.rom_error));
|
2012-08-07 00:04:38 +00:00
|
|
|
// TODO do getActivity().finish() on button clicks
|
2012-10-01 04:17:32 +00:00
|
|
|
// TODO setCanceledOnTouchOutside(false) ? otherwise can accidentally dismiss the error.
|
2012-08-07 00:04:38 +00:00
|
|
|
return builder.create();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-04 04:51:49 +00:00
|
|
|
private void updateActionBar(boolean showActionBar) {
|
|
|
|
final ActionBar actionBar = getActionBar();
|
|
|
|
if (showActionBar) {
|
|
|
|
if (actionBar != null && !actionBar.isShowing()) {
|
|
|
|
actionBar.show();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (actionBar != null && actionBar.isShowing()) {
|
|
|
|
actionBar.hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-03 22:32:11 +00:00
|
|
|
private void setScreenSize(boolean quick) {
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
|
|
|
|
if (quick) {
|
|
|
|
width = getResources().getDisplayMetrics().widthPixels;
|
|
|
|
height = getResources().getDisplayMetrics().heightPixels;
|
|
|
|
if (android.os.Build.VERSION.SDK_INT >= 11) {
|
|
|
|
// NOTE: 48 is a guess at the System Bar obstruction.
|
|
|
|
// These are 'visible insets' into the display from the window manager.
|
|
|
|
height -= 48;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Rect displaySize = new Rect();
|
2012-10-13 00:25:04 +00:00
|
|
|
// We use the mKegsView object here, but we could ask any view.
|
2012-10-03 22:32:11 +00:00
|
|
|
mKegsView.getWindowVisibleDisplayFrame(displaySize);
|
|
|
|
width = displaySize.width();
|
|
|
|
height = displaySize.height();
|
|
|
|
}
|
2012-10-01 04:17:32 +00:00
|
|
|
final BitmapSize bitmapSize = new BitmapSize(width, height);
|
2012-09-21 05:02:01 +00:00
|
|
|
|
2012-10-01 04:17:32 +00:00
|
|
|
mKegsView.updateScreenSize(bitmapSize);
|
2012-09-21 05:02:01 +00:00
|
|
|
|
2012-10-04 04:51:49 +00:00
|
|
|
// Only change action bar if the window height is significantly
|
|
|
|
// different from the last time we changed the action bar.
|
|
|
|
if (height < (mLastActionBar * 0.85) || height > (mLastActionBar * 1.15)) {
|
|
|
|
mLastActionBar = height;
|
|
|
|
updateActionBar(bitmapSize.showActionBar());
|
2012-09-21 05:02:01 +00:00
|
|
|
}
|
|
|
|
|
2012-10-01 04:17:32 +00:00
|
|
|
// Force another redraw of the bitmap into the canvas. Bug workaround.
|
|
|
|
mKegsView.getThread().updateScreen();
|
2012-09-21 05:02:01 +00:00
|
|
|
}
|
|
|
|
|
2012-10-03 22:32:11 +00:00
|
|
|
private void workaroundScreenSize() {
|
|
|
|
// First use displayMetrics.
|
|
|
|
setScreenSize(true);
|
|
|
|
|
|
|
|
// Then update with getWindowVisibleDisplayFrame in 250ms.
|
|
|
|
//
|
|
|
|
// We want to use getWindowVisibleDisplayFrame, but it's not
|
|
|
|
// always immediately available. Bug workaround.
|
2012-10-04 05:05:29 +00:00
|
|
|
//
|
|
|
|
// BUG: Sometimes if the device rotates as the soft keyboard
|
|
|
|
// is becoming visible for the first time, the reported
|
|
|
|
// window size is reduced and we don't scale to full screen.
|
|
|
|
// The user can fix this by rotating the screen again.
|
|
|
|
// We may want to trap IME visible/hidden events and update the size.
|
2012-10-03 22:32:11 +00:00
|
|
|
mKegsView.postDelayed(new Runnable() {
|
|
|
|
public void run() { setScreenSize(false); }
|
|
|
|
}, 250);
|
|
|
|
}
|
|
|
|
|
2012-09-21 05:02:01 +00:00
|
|
|
@Override
|
|
|
|
public void onConfigurationChanged(Configuration newConfig) {
|
|
|
|
super.onConfigurationChanged(newConfig);
|
2012-10-03 22:32:11 +00:00
|
|
|
workaroundScreenSize();
|
2012-09-21 05:02:01 +00:00
|
|
|
}
|
|
|
|
|
2012-08-07 00:04:38 +00:00
|
|
|
@Override
|
|
|
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
2012-08-21 10:41:05 +00:00
|
|
|
return mKegsKeyboard.keyEvent(event) || super.dispatchKeyEvent(event);
|
2012-08-07 00:04:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// @Override
|
|
|
|
// public boolean dispatchGenericMotionEvent(MotionEvent event) {
|
|
|
|
// // Joystick! if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 && event.getAction() == MotionEvent.ACTION_MOVE) {}
|
|
|
|
// // See also GameControllerInput.java from ApiDemos
|
|
|
|
// return super.dispatchGenericMotionEvent(event);
|
|
|
|
// }
|
|
|
|
|
2012-10-10 03:55:27 +00:00
|
|
|
@Override
|
|
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
|
|
// BUG: no overflow menu on devices with menu button
|
|
|
|
// BUG: when action bar is hidden, menu bar only shows overflow items
|
|
|
|
getMenuInflater().inflate(R.menu.actions, menu);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
|
|
// TODO: add code to adjust anything that might change
|
|
|
|
return super.onPrepareOptionsMenu(menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: FIXME: Seriously in progress.
|
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
// Action bar was clicked.
|
|
|
|
final int item_id = item.getItemId();
|
|
|
|
if (item_id == R.id.action_keyboard) {
|
|
|
|
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
|
|
if (imm != null) {
|
|
|
|
imm.toggleSoftInput(0, 0);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else if (item_id == R.id.action_speed) {
|
|
|
|
new SpeedFragment().show(getFragmentManager(), FRAGMENT_SPEED);
|
|
|
|
return true;
|
|
|
|
} else if (item_id == R.id.action_joystick) {
|
|
|
|
mModeMouse = !mModeMouse;
|
|
|
|
// TOAST...'now using...joystick or mouse'
|
|
|
|
return true;
|
|
|
|
} else if (item_id == R.id.action_function) {
|
|
|
|
// drop down menu for special keys...?
|
|
|
|
return true;
|
|
|
|
} else if (item_id == R.id.action_diskimage) {
|
|
|
|
// start fragment for disk images
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-07 00:04:38 +00:00
|
|
|
@Override
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
setContentView(R.layout.main);
|
|
|
|
|
|
|
|
mKegsView = (KegsView)findViewById(R.id.kegsview);
|
2012-10-01 04:17:32 +00:00
|
|
|
|
2012-10-03 22:32:11 +00:00
|
|
|
workaroundScreenSize();
|
2012-08-07 00:04:38 +00:00
|
|
|
|
|
|
|
mKegsTouch = new KegsTouch(mKegsView.getEventQueue());
|
|
|
|
final GestureDetector inputDetect = new GestureDetector(this, mKegsTouch);
|
|
|
|
|
2012-08-21 10:41:05 +00:00
|
|
|
mJoystick = new TouchJoystick(mKegsView.getEventQueue());
|
|
|
|
|
2012-08-07 00:04:38 +00:00
|
|
|
final View mainView = findViewById(R.id.mainview);
|
|
|
|
mainView.setClickable(true);
|
|
|
|
mainView.setLongClickable(true);
|
|
|
|
mainView.setOnTouchListener(new OnTouchListener() {
|
|
|
|
public boolean onTouch(View v, MotionEvent event) {
|
2012-08-21 10:41:05 +00:00
|
|
|
// TODO: consider using two listeners and setOnTouchListener them
|
|
|
|
if (mModeMouse) {
|
|
|
|
return inputDetect.onTouchEvent(event);
|
|
|
|
} else {
|
|
|
|
return mJoystick.onTouchEvent(event);
|
|
|
|
}
|
2012-08-07 00:04:38 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
mKegsKeyboard = new KegsKeyboard(mKegsView.getEventQueue());
|
|
|
|
mKegsKeyboard.setOnStickyReset(this);
|
|
|
|
|
2012-08-21 10:41:05 +00:00
|
|
|
mSettingsMenu = new PopupMenu(this, findViewById(R.id.key_settings));
|
|
|
|
mSettingsMenu.inflate(R.menu.options);
|
|
|
|
mSettingsMenu.setOnMenuItemClickListener(mSettingsClick);
|
|
|
|
|
2012-08-07 00:04:38 +00:00
|
|
|
findViewById(R.id.key_escape).setOnClickListener(mButtonClick);
|
|
|
|
findViewById(R.id.key_return).setOnClickListener(mButtonClick);
|
|
|
|
findViewById(R.id.key_f4).setOnClickListener(mButtonClick);
|
|
|
|
findViewById(R.id.key_control).setOnClickListener(mButtonClick);
|
|
|
|
findViewById(R.id.key_open_apple).setOnClickListener(mButtonClick);
|
|
|
|
findViewById(R.id.key_closed_apple).setOnClickListener(mButtonClick);
|
|
|
|
findViewById(R.id.key_left).setOnClickListener(mButtonClick);
|
|
|
|
findViewById(R.id.key_right).setOnClickListener(mButtonClick);
|
|
|
|
findViewById(R.id.key_up).setOnClickListener(mButtonClick);
|
|
|
|
findViewById(R.id.key_down).setOnClickListener(mButtonClick);
|
|
|
|
|
|
|
|
final String romfile = Config.whichRomFile();
|
|
|
|
if (romfile == null) {
|
|
|
|
final DialogFragment chooseRom = new RomDialogFragment();
|
|
|
|
chooseRom.show(getFragmentManager(), FRAGMENT_ROM);
|
|
|
|
} else {
|
|
|
|
Config.checkConfig(romfile);
|
|
|
|
mKegsView.setReady(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPause() {
|
|
|
|
super.onPause();
|
|
|
|
mKegsView.getThread().onPause();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onResume() {
|
|
|
|
super.onResume();
|
|
|
|
mKegsView.getThread().onResume();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onDestroy() {
|
|
|
|
super.onDestroy();
|
|
|
|
Log.w("kegs", "onDestroy called, halting");
|
|
|
|
// Force process to exit. We cannot handle another onCreate
|
|
|
|
// once a KegsView has been active. (JNI kegsmain has already run)
|
|
|
|
java.lang.Runtime.getRuntime().halt(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static {
|
|
|
|
System.loadLibrary("kegs");
|
|
|
|
}
|
|
|
|
}
|