2424
2525import java .awt .event .*;
2626import java .io .File ;
27+ import java .lang .reflect .InvocationHandler ;
28+ import java .lang .reflect .InvocationTargetException ;
29+ import java .lang .reflect .Method ;
30+ import java .lang .reflect .Proxy ;
31+ import java .util .List ;
2732
2833import javax .swing .*;
2934
30- import com .apple .eawt .*;
31- import com .apple .eawt .AppEvent .*;
35+ import com .apple .eawt .Application ;
3236
3337import processing .app .*;
3438import processing .app .ui .About ;
@@ -65,44 +69,40 @@ static protected void init(final Base base) {
6569 if (adapter == null ) {
6670 adapter = new ThinkDifferent (); //base);
6771 }
68-
69- application .setAboutHandler (new AboutHandler () {
70- public void handleAbout (AboutEvent ae ) {
71- new About (null );
72- }
72+
73+ setHandler (application , "setAboutHandler" , (proxy , method , args ) -> {
74+ new About (null );
75+ return null ;
7376 });
74-
75- application .setPreferencesHandler (new PreferencesHandler () {
76- public void handlePreferences (PreferencesEvent arg0 ) {
77- base .handlePrefs ();
78- }
77+
78+ setHandler (application , "setPreferencesHandler" , (proxy , method , args ) -> {
79+ base .handlePrefs ();
80+ return null ;
7981 });
8082
81- application .setOpenFileHandler (new OpenFilesHandler () {
82- public void openFiles (OpenFilesEvent event ) {
83- for (File file : event .getFiles ()) {
84- base .handleOpen (file .getAbsolutePath ());
85- }
83+ setHandler (application , "setOpenFileHandler" , (proxy , method , args ) -> {
84+ Method m = args [0 ].getClass ().getMethod ("getFiles" );
85+ for (File file : (List <File >) m .invoke (args [0 ])) {
86+ base .handleOpen (file .getAbsolutePath ());
8687 }
88+ return null ;
8789 });
88-
89- application .setPrintFileHandler (new PrintFilesHandler () {
90- public void printFiles (PrintFilesEvent event ) {
91- // TODO not yet implemented
92- }
90+
91+ setHandler (application , "setPrintFileHandler" , (proxy , method , args ) -> {
92+ // TODO not yet implemented
93+ return null ;
9394 });
94-
95- application .setQuitHandler (new QuitHandler () {
96- public void handleQuitRequestWith (QuitEvent event , QuitResponse response ) {
97- if (base .handleQuit ()) {
98- response .performQuit ();
99- } else {
100- response .cancelQuit ();
101- }
95+
96+ setHandler (application , "setQuitHandler" , (proxy , method , args ) -> {
97+ if (base .handleQuit ()) {
98+ args [1 ].getClass ().getMethod ("performQuit" ).invoke (args [1 ]);
99+ } else {
100+ args [1 ].getClass ().getMethod ("cancelQuit" ).invoke (args [1 ]);
102101 }
102+ return null ;
103103 });
104104
105- // Set the menubar to be used when nothing else is open.
105+ // Set the menubar to be used when nothing else is open.
106106 JMenuBar defaultMenuBar = new JMenuBar ();
107107 JMenu fileMenu = buildFileMenu (base );
108108 defaultMenuBar .add (fileMenu );
@@ -117,12 +117,12 @@ public void handleQuitRequestWith(QuitEvent event, QuitResponse response) {
117117 e .printStackTrace (); // oh well, never mind
118118 }
119119// } else {
120- // // The douchebags at Oracle didn't feel that a working f*king menubar
121- // // on OS X was important enough to make it into the 7u40 release.
120+ // // The douchebags at Oracle didn't feel that a working f*king menubar
121+ // // on OS X was important enough to make it into the 7u40 release.
122122// //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8007267
123123// // It languished in the JDK 8 source and has been backported for 7u60:
124124// //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8022667
125- //
125+ //
126126// JFrame offscreen = new JFrame();
127127// offscreen.setUndecorated(true);
128128// offscreen.setJMenuBar(defaultMenuBar);
@@ -131,12 +131,51 @@ public void handleQuitRequestWith(QuitEvent event, QuitResponse response) {
131131// offscreen.setVisible(true);
132132// }
133133 }
134-
134+
135135
136136// public ThinkDifferent(Base base) {
137137// this.base = base;
138138// }
139139
140+ /**
141+ * Sets a handler on an instance of {@link Application}, taking into account JVM version
142+ * differences.
143+ *
144+ * @param app an instance of {@link Application}
145+ * @param name the "set handler" method name
146+ * @param handler the handler
147+ */
148+ private static void setHandler (Application app , String name , InvocationHandler handler ) {
149+ // Determine which version of com.apple.eawt.Application to use and pass it a handler of the
150+ // appropriate type
151+ Method [] methods = app .getClass ().getMethods ();
152+ for (Method m : methods ) {
153+ if (!name .equals (m .getName ())) {
154+ continue ;
155+ }
156+ if (m .getParameterCount () != 1 ) {
157+ continue ;
158+ }
159+ Class paramType = m .getParameterTypes ()[0 ];
160+ try {
161+ // Allow a null handler
162+ Object proxy = null ;
163+ if (handler != null ) {
164+ proxy = Proxy .newProxyInstance (
165+ paramType .getClassLoader (), new Class <?>[] { paramType }, handler );
166+ }
167+ m .invoke (app , proxy );
168+ } catch (IllegalArgumentException ex ) {
169+ // TODO: Print error?: method doesn't take an interface, etc.
170+ } catch (IllegalAccessException ex ) {
171+ // TODO: Print error?: Other method invocation problem
172+ } catch (InvocationTargetException ex ) {
173+ ex .getCause ().printStackTrace ();
174+ // TODO: Print ex.getCause() a different way?
175+ }
176+ break ;
177+ }
178+ }
140179
141180 /**
142181 * Gimpy file menu to be used on OS X when no sketches are open.
@@ -162,7 +201,7 @@ public void actionPerformed(ActionEvent e) {
162201 fileMenu .add (item );
163202
164203 item = Toolkit .newJMenuItemShift (Language .text ("menu.file.sketchbook" ), 'K' );
165- item .addActionListener (new ActionListener () {
204+ item .addActionListener (new ActionListener () {
166205 @ Override
167206 public void actionPerformed (ActionEvent e ) {
168207 base .getNextMode ().showSketchbookFrame ();
0 commit comments