fix event handling bugs

This commit is contained in:
benfry
2012-09-03 22:49:43 +00:00
parent a69ba6b22d
commit 06045df2be
5 changed files with 351 additions and 167 deletions
+212 -138
View File
@@ -560,15 +560,6 @@ public class PApplet extends Activity implements PConstants, Runnable {
redraw = true; // draw this guy once
firstMotion = true;
// these need to be inited before setup
sizeMethods = new RegisteredMethods();
preMethods = new RegisteredMethods();
drawMethods = new RegisteredMethods();
postMethods = new RegisteredMethods();
mouseEventMethods = new RegisteredMethods();
keyEventMethods = new RegisteredMethods();
disposeMethods = new RegisteredMethods();
Context context = getApplicationContext();
sketchPath = context.getFilesDir().getAbsolutePath();
@@ -584,7 +575,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
@Override
public void onConfigurationChanged(Configuration newConfig) {
System.out.println("configuration changed: " + newConfig);
if (DEBUG) System.out.println("configuration changed: " + newConfig);
super.onConfigurationChanged(newConfig);
}
@@ -597,6 +588,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
// surfaceView.onResume();
if (DEBUG) System.out.println("PApplet.onResume() called");
paused = false;
handleMethods("resume");
//start(); // kick the thread back on
resume();
// surfaceView.onResume();
@@ -607,10 +599,10 @@ public class PApplet extends Activity implements PConstants, Runnable {
protected void onPause() {
super.onPause();
// TODO need to save all application state here!
// System.out.println("PApplet.onPause() called");
paused = true;
handleMethods("pause");
pause(); // handler for others to write
// synchronized (this) {
// paused = true;
@@ -1094,51 +1086,69 @@ public class PApplet extends Activity implements PConstants, Runnable {
//////////////////////////////////////////////////////////////
protected RegisteredMethods sizeMethods;
protected RegisteredMethods preMethods, drawMethods, postMethods;
protected RegisteredMethods mouseEventMethods, keyEventMethods;
protected RegisteredMethods disposeMethods;
public class RegisteredMethods {
/** Map of registered methods, stored by name. */
HashMap<String, RegisteredMethods> registerMap =
new HashMap<String, PApplet.RegisteredMethods>();
class RegisteredMethods {
int count;
Object objects[];
Method methods[];
Object[] objects;
// Because the Method comes from the class being called,
// it will be unique for most, if not all, objects.
Method[] methods;
Object[] emptyArgs = new Object[] { };
// convenience version for no args
public void handle() {
handle(new Object[] { });
void handle() {
handle(emptyArgs);
}
public void handle(Object oargs[]) {
void handle(Object[] args) {
for (int i = 0; i < count; i++) {
try {
//System.out.println(objects[i] + " " + args);
methods[i].invoke(objects[i], oargs);
methods[i].invoke(objects[i], args);
} catch (Exception e) {
e.printStackTrace();
// check for wrapped exception, get root exception
Throwable t;
if (e instanceof InvocationTargetException) {
InvocationTargetException ite = (InvocationTargetException) e;
t = ite.getCause();
} else {
t = e;
}
// check for RuntimeException, and allow to bubble up
if (t instanceof RuntimeException) {
// re-throw exception
throw (RuntimeException) t;
} else {
// trap and print as usual
t.printStackTrace();
}
}
}
}
public void add(Object object, Method method) {
if (objects == null) {
objects = new Object[5];
methods = new Method[5];
void add(Object object, Method method) {
if (findIndex(object) == -1) {
if (objects == null) {
objects = new Object[5];
methods = new Method[5];
} else if (count == objects.length) {
objects = (Object[]) PApplet.expand(objects);
methods = (Method[]) PApplet.expand(methods);
}
objects[count] = object;
methods[count] = method;
count++;
} else {
die(method.getName() + "() already added for this instance of " +
object.getClass().getName());
}
if (count == objects.length) {
objects = (Object[]) PApplet.expand(objects);
methods = (Method[]) PApplet.expand(methods);
// Object otemp[] = new Object[count << 1];
// System.arraycopy(objects, 0, otemp, 0, count);
// objects = otemp;
// Method mtemp[] = new Method[count << 1];
// System.arraycopy(methods, 0, mtemp, 0, count);
// methods = mtemp;
}
objects[count] = object;
methods[count] = method;
count++;
}
@@ -1147,8 +1157,10 @@ public class PApplet extends Activity implements PConstants, Runnable {
* must be called multiple times if object is registered multiple times).
* Does not shrink array afterwards, silently returns if method not found.
*/
public void remove(Object object, Method method) {
int index = findIndex(object, method);
// public void remove(Object object, Method method) {
// int index = findIndex(object, method);
public void remove(Object object) {
int index = findIndex(object);
if (index != -1) {
// shift remaining methods by one to preserve ordering
count--;
@@ -1162,9 +1174,12 @@ public class PApplet extends Activity implements PConstants, Runnable {
}
}
protected int findIndex(Object object, Method method) {
// protected int findIndex(Object object, Method method) {
protected int findIndex(Object object) {
for (int i = 0; i < count; i++) {
if (objects[i] == object && methods[i].equals(method)) {
if (objects[i] == object) {
// if (objects[i] == object && methods[i].equals(method)) {
//objects[i].equals() might be overridden, so use == for safety
// since here we do care about actual object identity
//methods[i]==method is never true even for same method, so must use
@@ -1177,126 +1192,177 @@ public class PApplet extends Activity implements PConstants, Runnable {
}
/**
* Register a built-in event so that it can be fired for libraries, etc.
* Supported events include:
* <ul>
* <li>pre at the very top of the draw() method (safe to draw)
* <li>draw at the end of the draw() method (safe to draw)
* <li>post after draw() has exited (not safe to draw)
* <li>pause()  called when the sketch is paused
* <li>resume()  called when the sketch is resumed
* <li>dispose when the sketch is shutting down (definitely not safe to draw)
* <ul>
* In addition, the new (for 2.0) processing.event classes are passed to
* the following event types:
* <ul>
* <li>mouseEvent
* <li>keyEvent
* <li>touchEvent
* </ul>
* The older java.awt events are no longer supported.
* See the Library Wiki page for more details.
* @param methodName name of the method to be called
* @param target the target object that should receive the event
*/
public void registerMethod(String methodName, Object target) {
if (methodName.equals("mouseEvent")) {
registerWithArgs("mouseEvent", target, new Class[] { processing.event.MouseEvent.class });
} else if (methodName.equals("keyEvent")) {
registerWithArgs("keyEvent", target, new Class[] { processing.event.KeyEvent.class });
} else if (methodName.equals("touchEvent")) {
registerWithArgs("touchEvent", target, new Class[] { processing.event.TouchEvent.class });
} else {
registerNoArgs(methodName, target);
}
}
private void registerNoArgs(String name, Object o) {
RegisteredMethods meth = registerMap.get(name);
if (meth == null) {
meth = new RegisteredMethods();
registerMap.put(name, meth);
}
Class<?> c = o.getClass();
try {
Method method = c.getMethod(name, new Class[] {});
meth.add(o, method);
} catch (NoSuchMethodException nsme) {
die("There is no public " + name + "() method in the class " +
o.getClass().getName());
} catch (Exception e) {
die("Could not register " + name + " + () for " + o, e);
}
}
private void registerWithArgs(String name, Object o, Class<?> cargs[]) {
RegisteredMethods meth = registerMap.get(name);
if (meth == null) {
meth = new RegisteredMethods();
registerMap.put(name, meth);
}
Class<?> c = o.getClass();
try {
Method method = c.getMethod(name, cargs);
meth.add(o, method);
} catch (NoSuchMethodException nsme) {
die("There is no public " + name + "() method in the class " +
o.getClass().getName());
} catch (Exception e) {
die("Could not register " + name + " + () for " + o, e);
}
}
// public void registerMethod(String methodName, Object target, Object... args) {
// registerWithArgs(methodName, target, args);
// }
public void unregisterMethod(String name, Object target) {
RegisteredMethods meth = registerMap.get(name);
if (meth == null) {
die("No registered methods with the name " + name + "() were found.");
}
try {
// Method method = o.getClass().getMethod(name, new Class[] {});
// meth.remove(o, method);
meth.remove(target);
} catch (Exception e) {
die("Could not unregister " + name + "() for " + target, e);
}
}
protected void handleMethods(String methodName) {
RegisteredMethods meth = registerMap.get(methodName);
if (meth != null) {
meth.handle();
}
}
@Deprecated
public void registerSize(Object o) {
Class<?> methodArgs[] = new Class[] { Integer.TYPE, Integer.TYPE };
registerWithArgs(sizeMethods, "size", o, methodArgs);
System.err.println("The registerSize() command is no longer supported.");
// Class<?> methodArgs[] = new Class[] { Integer.TYPE, Integer.TYPE };
// registerWithArgs(sizeMethods, "size", o, methodArgs);
}
@Deprecated
public void registerPre(Object o) {
registerNoArgs(preMethods, "pre", o);
registerNoArgs("pre", o);
}
@Deprecated
public void registerDraw(Object o) {
registerNoArgs(drawMethods, "draw", o);
registerNoArgs("draw", o);
}
@Deprecated
public void registerPost(Object o) {
registerNoArgs(postMethods, "post", o);
}
public void registerMouseEvent(Object o) {
// Class<?> methodArgs[] = new Class[] { MouseEvent.class };
// registerWithArgs(mouseEventMethods, "mouseEvent", o, methodArgs);
registerNoArgs("post", o);
}
public void registerKeyEvent(Object o) {
Class<?> methodArgs[] = new Class[] { KeyEvent.class };
registerWithArgs(keyEventMethods, "keyEvent", o, methodArgs);
}
@Deprecated
public void registerDispose(Object o) {
//registerNoArgs(disposeMethods, "dispose", o);
}
protected void registerNoArgs(RegisteredMethods meth,
String name, Object o) {
Class<?> c = o.getClass();
try {
Method method = c.getMethod(name, new Class[] {});
meth.add(o, method);
} catch (NoSuchMethodException nsme) {
die("There is no public " + name + "() method in the class " +
o.getClass().getName());
} catch (Exception e) {
die("Could not register " + name + " + () for " + o, e);
}
}
protected void registerWithArgs(RegisteredMethods meth,
String name, Object o, Class<?> cargs[]) {
Class<?> c = o.getClass();
try {
Method method = c.getMethod(name, cargs);
meth.add(o, method);
} catch (NoSuchMethodException nsme) {
die("There is no public " + name + "() method in the class " +
o.getClass().getName());
} catch (Exception e) {
die("Could not register " + name + " + () for " + o, e);
}
registerNoArgs("dispose", o);
}
@Deprecated
public void unregisterSize(Object o) {
Class<?> methodArgs[] = new Class[] { Integer.TYPE, Integer.TYPE };
unregisterWithArgs(sizeMethods, "size", o, methodArgs);
System.err.println("The unregisterSize() command is no longer supported.");
// Class<?> methodArgs[] = new Class[] { Integer.TYPE, Integer.TYPE };
// unregisterWithArgs(sizeMethods, "size", o, methodArgs);
}
@Deprecated
public void unregisterPre(Object o) {
unregisterNoArgs(preMethods, "pre", o);
unregisterMethod("pre", o);
}
@Deprecated
public void unregisterDraw(Object o) {
unregisterNoArgs(drawMethods, "draw", o);
unregisterMethod("draw", o);
}
@Deprecated
public void unregisterPost(Object o) {
unregisterNoArgs(postMethods, "post", o);
unregisterMethod("post", o);
}
public void unregisterMouseEvent(Object o) {
// Class<?> methodArgs[] = new Class[] { MouseEvent.class };
// unregisterWithArgs(mouseEventMethods, "mouseEvent", o, methodArgs);
}
public void unregisterKeyEvent(Object o) {
Class<?> methodArgs[] = new Class[] { KeyEvent.class };
unregisterWithArgs(keyEventMethods, "keyEvent", o, methodArgs);
}
@Deprecated
public void unregisterDispose(Object o) {
unregisterNoArgs(disposeMethods, "dispose", o);
}
protected void unregisterNoArgs(RegisteredMethods meth,
String name, Object o) {
Class<?> c = o.getClass();
try {
Method method = c.getMethod(name, new Class[] {});
meth.remove(o, method);
} catch (Exception e) {
die("Could not unregister " + name + "() for " + o, e);
}
}
protected void unregisterWithArgs(RegisteredMethods meth,
String name, Object o, Class<?> cargs[]) {
Class<?> c = o.getClass();
try {
Method method = c.getMethod(name, cargs);
meth.remove(o, method);
} catch (Exception e) {
die("Could not unregister " + name + "() for " + o, e);
}
unregisterMethod("dispose", o);
}
@@ -1876,6 +1942,10 @@ public class PApplet extends Activity implements PConstants, Runnable {
float instantaneousRate = (float) rate / 1000.0f;
frameRate = (frameRate * 0.9f) + (instantaneousRate * 0.1f);
if (frameCount != 0) {
handleMethods("pre");
}
// use dmouseX/Y as previous mouse pos, since this is the
// last position the mouse was in during the previous draw.
pmouseX = dmouseX;
@@ -1900,13 +1970,17 @@ public class PApplet extends Activity implements PConstants, Runnable {
dequeueMotionEvents();
dequeueKeyEvents();
handleMethods("draw");
redraw = false; // unset 'redraw' flag in case it was set
// (only do this once draw() has run, not just setup())
}
g.endDraw();
if (frameCount != 0) {
handleMethods("post");
}
frameRateLastNanos = now;
frameCount++;
}
@@ -2746,7 +2820,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
// call to shut down renderer, in case it needs it (pdf does)
if (g != null) g.dispose();
disposeMethods.handle();
handleMethods("dispose");
}
@@ -0,0 +1,41 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2012 The Processing Foundation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, version 2.1.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.event;
public class KeyEvent {
Object nativeObject;
char key;
int keyCode;
public KeyEvent(Object nativeObject) {
this.nativeObject = nativeObject;
}
public Object getNative() {
return nativeObject;
}
}
@@ -0,0 +1,40 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2012 The Processing Foundation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, version 2.1.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.event;
public class MouseEvent {
Object nativeObject;
int x, y;
public MouseEvent(Object nativeObject) {
this.nativeObject = nativeObject;
}
public Object getNative() {
return nativeObject;
}
}
@@ -0,0 +1,40 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2012 The Processing Foundation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, version 2.1.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.event;
public class TouchEvent {
Object nativeObject;
float x, y;
public TouchEvent(Object nativeObject) {
this.nativeObject = nativeObject;
}
public Object getNative() {
return nativeObject;
}
}