/** * MicroEmulator * Copyright (C) 2009 Bartek Teodorczyk <barteo@barteo.net> * * It is licensed under the following two licenses as alternatives: * 1. GNU Lesser General Public License (the "LGPL") version 2.1 or any newer version * 2. Apache License (the "AL") Version 2.0 * * You may not use this file except in compliance with at least one of * the above two licenses. * * You may obtain a copy of the LGPL at * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt * * You may obtain a copy of the AL 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 LGPL or the AL for the specific language governing permissions and * limitations. * * @version $Id: MicroEmulatorActivity.java 1918 2009-01-21 12:56:43Z barteo $ */ package org.microemu.android; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import javax.microedition.io.ConnectionNotFoundException; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Displayable; import android.view.KeyEvent; import android.view.MotionEvent; import jimm.modules.DebugLog; import org.microemu.DisplayAccess; import org.microemu.DisplayComponent; import org.microemu.MIDletAccess; import org.microemu.MIDletBridge; import org.microemu.android.device.AndroidDeviceDisplay; import org.microemu.android.device.AndroidFontManager; import org.microemu.android.device.AndroidInputMethod; import org.microemu.android.device.ui.AndroidCanvasUI; import org.microemu.android.device.ui.AndroidDisplayableUI; import org.microemu.android.device.ui.CanvasView; import org.microemu.android.util.ActivityResultListener; import org.microemu.device.DeviceDisplay; import org.microemu.device.DeviceFactory; import org.microemu.device.EmulatorContext; import org.microemu.device.FontManager; import org.microemu.device.InputMethod; import android.app.Activity; import android.app.Dialog; import android.content.ActivityNotFoundException; import android.content.Intent; import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.Display; import android.view.View; public abstract class MicroEmulatorActivity extends Activity { public static AndroidConfig config = new AndroidConfig(); public boolean windowFullscreen; private Handler handler = new Handler(); private Thread activityThread; protected View contentView; private Dialog dialog; private ArrayList<ActivityResultListener> activityResultListeners = new ArrayList<ActivityResultListener>(); protected EmulatorContext emulatorContext; public void setConfig(AndroidConfig config) { MicroEmulatorActivity.config = config; } public EmulatorContext getEmulatorContext() { return emulatorContext; } public boolean post(final Runnable r) { Runnable nn = new Runnable() { @Override public void run() { try { r.run(); } catch (Exception e) { DebugLog.panic("err ", e); } } }; if (activityThread == Thread.currentThread()) { nn.run(); return true; } else { return handler.post(nn); } } public boolean postDelayed(Runnable r, long delayMillis) { if (activityThread == Thread.currentThread()) { r.run(); return true; } else { return handler.postDelayed(r, delayMillis); } } public boolean isActivityThread() { return (activityThread == Thread.currentThread()); } @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); emulatorContext = new EmulatorContext() { private InputMethod inputMethod = new AndroidInputMethod(); private DeviceDisplay deviceDisplay = new AndroidDeviceDisplay(MicroEmulatorActivity.this, this, 200, 200); private FontManager fontManager = new AndroidFontManager(getResources().getDisplayMetrics()); public DisplayComponent getDisplayComponent() { // TODO consider removal of EmulatorContext.getDisplayComponent() System.out.println("MicroEmulator.emulatorContext::getDisplayComponent()"); return null; } public InputMethod getDeviceInputMethod() { return inputMethod; } public DeviceDisplay getDeviceDisplay() { return deviceDisplay; } public FontManager getDeviceFontManager() { return fontManager; } public InputStream getResourceAsStream(Class origClass, String name) { try { if (name.startsWith("/")) { return MicroEmulatorActivity.this.getAssets().open(name.substring(1)); } else { Package p = origClass.getPackage(); if (p == null) { return MicroEmulatorActivity.this.getAssets().open(name); } else { String folder = origClass.getPackage().getName().replace('.', '/'); return MicroEmulatorActivity.this.getAssets().open(folder + "/" + name); } } } catch (IOException e) { //Logger.debug(e); // large output with BombusMod return null; } } public boolean platformRequest(String url) throws ConnectionNotFoundException { try { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); } catch (ActivityNotFoundException e) { throw new ConnectionNotFoundException(); } return true; } }; activityThread = Thread.currentThread(); } @Override public void setContentView(View view) { Log.d("AndroidCanvasUI", "set content view: " + view); super.setContentView(view); contentView = view; } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); MIDletAccess ma = MIDletBridge.getMIDletAccess(); if (ma == null) { return; } DisplayAccess da = ma.getDisplayAccess(); if (da != null) { Displayable d = da.getCurrent(); if (d instanceof Canvas) { CanvasView c = ((AndroidCanvasUI)d.getUi()).getCanvasView(); AndroidDeviceDisplay deviceDisplay = (AndroidDeviceDisplay) DeviceFactory.getDevice().getDeviceDisplay(); deviceDisplay.displayRectangleWidth = c.getWidth(); deviceDisplay.displayRectangleHeight = c.getHeight(); da.sizeChanged(); deviceDisplay.repaint(0, 0, deviceDisplay.getFullWidth(), deviceDisplay.getFullHeight()); } } } public void addActivityResultListener(ActivityResultListener listener) { activityResultListeners.add(listener); } public void removeActivityResultListener(ActivityResultListener listener) { activityResultListeners.remove(listener); } @Override protected final void onActivityResult(int requestCode, int resultCode, Intent data) { for (ActivityResultListener activityResultListener : activityResultListeners) { if (activityResultListener.onActivityResult(requestCode, resultCode, data)) { return; } } super.onActivityResult(requestCode, resultCode, data); } @Override public boolean onTrackballEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_MOVE) { MIDletAccess ma = MIDletBridge.getMIDletAccess(); if (ma == null) { return false; } final DisplayAccess da = ma.getDisplayAccess(); if (da == null) { return false; } AndroidDisplayableUI ui = (AndroidDisplayableUI) da.getDisplayableUI(da.getCurrent()); if (ui instanceof AndroidCanvasUI) { float x = event.getX(); float y = event.getY(); if ((x > 0 && accumulatedTrackballX < 0) || (x < 0 && accumulatedTrackballX > 0)) { accumulatedTrackballX = 0; } if ((y > 0 && accumulatedTrackballY < 0) || (y < 0 && accumulatedTrackballY > 0)) { accumulatedTrackballY = 0; } if (accumulatedTrackballX + x > TRACKBALL_THRESHOLD) { accumulatedTrackballX -= TRACKBALL_THRESHOLD; KEY_RIGHT_DOWN_EVENT.dispatch(this); KEY_RIGHT_UP_EVENT.dispatch(this); } else if (accumulatedTrackballX + x < -TRACKBALL_THRESHOLD) { accumulatedTrackballX += TRACKBALL_THRESHOLD; KEY_LEFT_DOWN_EVENT.dispatch(this); KEY_LEFT_UP_EVENT.dispatch(this); } if (accumulatedTrackballY + y > TRACKBALL_THRESHOLD) { accumulatedTrackballY -= TRACKBALL_THRESHOLD; KEY_DOWN_DOWN_EVENT.dispatch(this); KEY_DOWN_UP_EVENT.dispatch(this); } else if (accumulatedTrackballY + y < -TRACKBALL_THRESHOLD) { accumulatedTrackballY += TRACKBALL_THRESHOLD; KEY_UP_DOWN_EVENT.dispatch(this); KEY_UP_UP_EVENT.dispatch(this); } accumulatedTrackballX += x; accumulatedTrackballY += y; return true; } } return super.onTrackballEvent(event); } private final static KeyEvent KEY_RIGHT_DOWN_EVENT = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT); private final static KeyEvent KEY_RIGHT_UP_EVENT = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_RIGHT); private final static KeyEvent KEY_LEFT_DOWN_EVENT = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT); private final static KeyEvent KEY_LEFT_UP_EVENT = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_LEFT); private final static KeyEvent KEY_DOWN_DOWN_EVENT = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN); private final static KeyEvent KEY_DOWN_UP_EVENT = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_DOWN); private final static KeyEvent KEY_UP_DOWN_EVENT = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP); private final static KeyEvent KEY_UP_UP_EVENT = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_UP); private final static float TRACKBALL_THRESHOLD = 1.0f; private float accumulatedTrackballX = 0; private float accumulatedTrackballY = 0; }