Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 75 additions & 36 deletions app/src/processing/app/platform/ThinkDifferent.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@

import java.awt.event.*;
import java.io.File;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

import javax.swing.*;

import com.apple.eawt.*;
import com.apple.eawt.AppEvent.*;
import com.apple.eawt.Application;

import processing.app.*;
import processing.app.ui.About;
Expand Down Expand Up @@ -65,44 +69,40 @@ static protected void init(final Base base) {
if (adapter == null) {
adapter = new ThinkDifferent(); //base);
}

application.setAboutHandler(new AboutHandler() {
public void handleAbout(AboutEvent ae) {
new About(null);
}

setHandler(application, "setAboutHandler", (proxy, method, args) -> {
new About(null);
return null;
});

application.setPreferencesHandler(new PreferencesHandler() {
public void handlePreferences(PreferencesEvent arg0) {
base.handlePrefs();
}

setHandler(application, "setPreferencesHandler", (proxy, method, args) -> {
base.handlePrefs();
return null;
});

application.setOpenFileHandler(new OpenFilesHandler() {
public void openFiles(OpenFilesEvent event) {
for (File file : event.getFiles()) {
base.handleOpen(file.getAbsolutePath());
}
setHandler(application, "setOpenFileHandler", (proxy, method, args) -> {
Method m = args[0].getClass().getMethod("getFiles");
for (File file : (List<File>) m.invoke(args[0])) {
base.handleOpen(file.getAbsolutePath());
}
return null;
});

application.setPrintFileHandler(new PrintFilesHandler() {
public void printFiles(PrintFilesEvent event) {
// TODO not yet implemented
}

setHandler(application, "setPrintFileHandler", (proxy, method, args) -> {
// TODO not yet implemented
return null;
});

application.setQuitHandler(new QuitHandler() {
public void handleQuitRequestWith(QuitEvent event, QuitResponse response) {
if (base.handleQuit()) {
response.performQuit();
} else {
response.cancelQuit();
}

setHandler(application, "setQuitHandler", (proxy, method, args) -> {
if (base.handleQuit()) {
args[1].getClass().getMethod("performQuit").invoke(args[1]);
} else {
args[1].getClass().getMethod("cancelQuit").invoke(args[1]);
}
return null;
});

// Set the menubar to be used when nothing else is open.
// Set the menubar to be used when nothing else is open.
JMenuBar defaultMenuBar = new JMenuBar();
JMenu fileMenu = buildFileMenu(base);
defaultMenuBar.add(fileMenu);
Expand All @@ -117,12 +117,12 @@ public void handleQuitRequestWith(QuitEvent event, QuitResponse response) {
e.printStackTrace(); // oh well, never mind
}
// } else {
// // The douchebags at Oracle didn't feel that a working f*king menubar
// // on OS X was important enough to make it into the 7u40 release.
// // The douchebags at Oracle didn't feel that a working f*king menubar
// // on OS X was important enough to make it into the 7u40 release.
// //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8007267
// // It languished in the JDK 8 source and has been backported for 7u60:
// //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8022667
//
//
// JFrame offscreen = new JFrame();
// offscreen.setUndecorated(true);
// offscreen.setJMenuBar(defaultMenuBar);
Expand All @@ -131,12 +131,51 @@ public void handleQuitRequestWith(QuitEvent event, QuitResponse response) {
// offscreen.setVisible(true);
// }
}


// public ThinkDifferent(Base base) {
// this.base = base;
// }

/**
* Sets a handler on an instance of {@link Application}, taking into account JDK version
* differences.
*
* @param app an instance of {@link Application}
* @param name the "set handler" method name
* @param handler the handler
*/
private static void setHandler(Application app, String name, InvocationHandler handler) {
// Determine which version of com.apple.eawt.Application to use and pass it a handler of the
// appropriate type
Method[] methods = app.getClass().getMethods();
for (Method m : methods) {
if (!name.equals(m.getName())) {
continue;
}
if (m.getParameterCount() != 1) {
continue;
}
Class paramType = m.getParameterTypes()[0];
try {
// Allow a null handler
Object proxy = null;
if (handler != null) {
proxy = Proxy.newProxyInstance(
paramType.getClassLoader(), new Class<?>[] { paramType }, handler);
}
m.invoke(app, proxy);
} catch (IllegalArgumentException ex) {
// TODO: Print error?: method doesn't take an interface, etc.
} catch (IllegalAccessException ex) {
// TODO: Print error?: Other method invocation problem
} catch (InvocationTargetException ex) {
ex.getCause().printStackTrace();
// TODO: Print ex.getCause() a different way?
}
break;
}
}

/**
* Gimpy file menu to be used on OS X when no sketches are open.
Expand All @@ -162,7 +201,7 @@ public void actionPerformed(ActionEvent e) {
fileMenu.add(item);

item = Toolkit.newJMenuItemShift(Language.text("menu.file.sketchbook"), 'K');
item.addActionListener(new ActionListener() {
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
base.getNextMode().showSketchbookFrame();
Expand Down
68 changes: 54 additions & 14 deletions core/src/processing/core/ThinkDifferent.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@
package processing.core;

import java.awt.Image;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.apple.eawt.AppEvent.QuitEvent;
import com.apple.eawt.Application;
import com.apple.eawt.QuitHandler;
import com.apple.eawt.QuitResponse;


/**
Expand Down Expand Up @@ -57,25 +58,64 @@ static public void init(final PApplet sketch) {
application = Application.getApplication();
}

application.setQuitHandler(new QuitHandler() {
public void handleQuitRequestWith(QuitEvent event, QuitResponse response) {
sketch.exit();
if (PApplet.uncaughtThrowable == null && // no known crash
!attemptedQuit) { // haven't tried yet
response.cancelQuit(); // tell OS X we'll handle this
attemptedQuit = true;
} else {
response.performQuit(); // just force it this time
}
setHandler(application, "setQuitHandler", (proxy, method, args) -> {
sketch.exit();
if (PApplet.uncaughtThrowable == null && // no known crash
!attemptedQuit) { // haven't tried yet
args[1].getClass().getMethod("cancelQuit").invoke(args[1]); // tell OS X we'll handle this
attemptedQuit = true;
} else {
args[1].getClass().getMethod("performQuit").invoke(args[1]); // just force it this time
}
return null;
});
}

/**
* Sets a handler on an instance of {@link Application}, taking into account JDK version
* differences.
*
* @param app an instance of {@link Application}
* @param name the "set handler" method name
* @param handler the handler
*/
private static void setHandler(Application app, String name, InvocationHandler handler) {
// Determine which version of com.apple.eawt.Application to use and pass it a handler of the
// appropriate type
Method[] methods = app.getClass().getMethods();
for (Method m : methods) {
if (!name.equals(m.getName())) {
continue;
}
if (m.getParameterCount() != 1) {
continue;
}
Class paramType = m.getParameterTypes()[0];
try {
// Allow a null handler
Object proxy = null;
if (handler != null) {
proxy = Proxy.newProxyInstance(
paramType.getClassLoader(), new Class<?>[] { paramType }, handler);
}
m.invoke(app, proxy);
} catch (IllegalArgumentException ex) {
// TODO: Print error?: method doesn't take an interface, etc.
} catch (IllegalAccessException ex) {
// TODO: Print error?: Other method invocation problem
} catch (InvocationTargetException ex) {
ex.getCause().printStackTrace();
// TODO: Print ex.getCause() a different way?
}
break;
}
}

static public void cleanup() {
if (application == null) {
application = Application.getApplication();
}
application.setQuitHandler(null);
setHandler(application, "setQuitHandler", null);
}

// Called via reflection from PSurfaceAWT and others
Expand Down