From 1bb05ccc3181da9c02106340750984cca81d5a03 Mon Sep 17 00:00:00 2001 From: herrtunante Date: Fri, 13 Dec 2024 16:27:44 +0100 Subject: [PATCH] Handle new iOS DEsktop and Taskbar classes --- .../collect/earth/app/desktop/EarthApp.java | 130 +++++++++++++----- .../MacOpenFilesInvocationHandlerNewIos.java | 65 +++++++++ 2 files changed, 163 insertions(+), 32 deletions(-) create mode 100644 collect-earth/collect-earth-app/src/main/java/org/openforis/collect/earth/app/desktop/MacOpenFilesInvocationHandlerNewIos.java diff --git a/collect-earth/collect-earth-app/src/main/java/org/openforis/collect/earth/app/desktop/EarthApp.java b/collect-earth/collect-earth-app/src/main/java/org/openforis/collect/earth/app/desktop/EarthApp.java index 4470ed194f..8e1a60f0c6 100644 --- a/collect-earth/collect-earth-app/src/main/java/org/openforis/collect/earth/app/desktop/EarthApp.java +++ b/collect-earth/collect-earth-app/src/main/java/org/openforis/collect/earth/app/desktop/EarthApp.java @@ -8,6 +8,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.net.MalformedURLException; @@ -164,49 +165,114 @@ private static void initializeSentry() { @SuppressWarnings({ "rawtypes", "unchecked" }) public static void handleMacStartup(String doubleClickedProjectFile) throws Exception { try { - Class applicationClass = Class.forName("com.apple.eawt.Application"); - Method getApplicationMethod = applicationClass.getMethod("getApplication"); - Method setDockIconImageMethod = applicationClass.getMethod("setDockIconImage", Image.class); - - Class openFilesHandlerInterface = Class.forName("com.apple.eawt.OpenFilesHandler"); - Method setOpenFileHandlerMethod = applicationClass.getMethod("setOpenFileHandler", - openFilesHandlerInterface); - - // SET THE MAC OS X DOCK ICON! - // Get an Application object - Object applicationObject = getApplicationMethod.invoke(null); + try { - Image dockIconImage = new ImageIcon(new File("images/dockIconMac.png").toURI().toURL()).getImage(); - // Invoke the setDockIconImage on the application object using the dockIconImage - // as an argument - setDockIconImageMethod.invoke(applicationObject, dockIconImage); - } catch (MalformedURLException e2) { - logger.error("Problems finding the docker icon", e2); + // This code is only available in Java 9 and later and in newer Mac OS versions + setIconMacNewOS(); + } catch (Exception e) { + logger.error("Error while defining the double-click behaviour on CEP files in NEW Mac OS X", e); + try { + setIconMacOldOS(); + } catch (Exception e2) { + logger.error("Error while defining the double-click behaviour on CEP files in OLD Mac OS X", e2); + } + } - // ------------------------------------------- - - // DEFINE A LISTENER THAT IS REGISTERED BY THE OS TO HEAR DOUBLE-CLICK EVENTS - // AND REGISTER ITSELF AS THE CEP OPENER - MacOpenFilesInvocationHandler macOpenFileHandlerProxyInterface = new MacOpenFilesInvocationHandler(); - Object openFilesHandlerImplementation = Proxy.newProxyInstance(applicationClass.getClassLoader(), - new Class[] { openFilesHandlerInterface }, macOpenFileHandlerProxyInterface); - - // Call the setOpenFileHandler method of the application object using the - setOpenFileHandlerMethod.invoke(applicationObject, - (openFilesHandlerInterface.cast(openFilesHandlerImplementation))); - + // Lets wait for the Apple event to arrive. If it did then the earthApp variable // will be non-nulls Thread.sleep(2000); + + } catch (Exception e) { + logger.error("Error while defining the double-click behaviour on CEP files in Mac OS X", e); + + } finally { if (earthApp == null) { + logger.info("Collect Earth started by double-clicking a CEP file in Mac OS X " + doubleClickedProjectFile); startCollectEarth(doubleClickedProjectFile); + } else { + logger.info("Collect Earth started but no CEP file loaded in Mac OS X"); + startCollectEarth(null); } - } catch (Exception e) { - logger.error("Error while defining the double-click behaviour on CEP files in Mac OS X", e); - startCollectEarth(null); } } + private static void setIconMacOldOS() + throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { + Class applicationClass = Class.forName("com.apple.eawt.Application"); + Method getApplicationMethod = applicationClass.getMethod("getApplication"); + Method setDockIconImageMethod = applicationClass.getMethod("setDockIconImage", Image.class); + + Class openFilesHandlerInterface = Class.forName("com.apple.eawt.OpenFilesHandler"); + Method setOpenFileHandlerMethod = applicationClass.getMethod("setOpenFileHandler", + openFilesHandlerInterface); + + // SET THE MAC OS X DOCK ICON! + // Get an Application object + Object applicationObject = getApplicationMethod.invoke(null); + try { + Image dockIconImage = new ImageIcon(new File("images/dockIconMac.png").toURI().toURL()).getImage(); + // Invoke the setDockIconImage on the application object using the dockIconImage + // as an argument + setDockIconImageMethod.invoke(applicationObject, dockIconImage); + } catch (MalformedURLException e2) { + logger.error("Problems finding the docker icon", e2); + } + // ------------------------------------------- + + // DEFINE A LISTENER THAT IS REGISTERED BY THE OS TO HEAR DOUBLE-CLICK EVENTS + // AND REGISTER ITSELF AS THE CEP OPENER + MacOpenFilesInvocationHandler macOpenFileHandlerProxyInterface = new MacOpenFilesInvocationHandler(); + Object openFilesHandlerImplementation = Proxy.newProxyInstance(applicationClass.getClassLoader(), + new Class[] { openFilesHandlerInterface }, macOpenFileHandlerProxyInterface); + + // Call the setOpenFileHandler method of the application object using the + setOpenFileHandlerMethod.invoke(applicationObject, + (openFilesHandlerInterface.cast(openFilesHandlerImplementation))); + } + + + private static void setIconMacNewOS() + throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { + // SET THE MAC OS X DOCK ICON! + // Get an Application object + Object taskbarObject; + Object desktopObject; + + Class taskbarClass = Class.forName("java.awt.Taskbar"); + Class desktopClass = Class.forName("java.awt.Desktop"); + Method getTaskBarMethod = taskbarClass.getMethod("getTaskbar"); + Method getDesktopMethod = desktopClass.getMethod("getDesktop"); + Method setIconImage = taskbarClass.getMethod("setIconImage", Image.class); + + Class openFilesHandlerInterface = Class.forName("java.awt.desktop.OpenFilesHandler"); + Method setOpenFileHandlerMethod = desktopClass.getMethod("setOpenFileHandler", + openFilesHandlerInterface); + + taskbarObject = getTaskBarMethod.invoke(null); + try { + Image dockIconImage = new ImageIcon(new File("images/dockIconMac.png").toURI().toURL()).getImage(); + // Invoke the setDockIconImage on the application object using the dockIconImage + // as an argument + setIconImage.invoke(taskbarObject, dockIconImage); + } catch (MalformedURLException e2) { + logger.error("Problems finding the docker icon", e2); + } + // ------------------------------------------- + + // DEFINE A LISTENER THAT IS REGISTERED BY THE OS TO HEAR DOUBLE-CLICK EVENTS + // AND REGISTER ITSELF AS THE CEP OPENER + MacOpenFilesInvocationHandlerNewIos macOpenFileHandlerProxyInterface = new MacOpenFilesInvocationHandlerNewIos(); + Object openFilesHandlerImplementation = Proxy.newProxyInstance(desktopClass.getClassLoader(), + new Class[] { openFilesHandlerInterface }, macOpenFileHandlerProxyInterface); + + desktopObject = getDesktopMethod.invoke(null); + + // Call the setOpenFileHandler method of the application object using the + setOpenFileHandlerMethod.invoke(desktopObject, + (openFilesHandlerInterface.cast(openFilesHandlerImplementation))); + } + public void generateKml() { try { diff --git a/collect-earth/collect-earth-app/src/main/java/org/openforis/collect/earth/app/desktop/MacOpenFilesInvocationHandlerNewIos.java b/collect-earth/collect-earth-app/src/main/java/org/openforis/collect/earth/app/desktop/MacOpenFilesInvocationHandlerNewIos.java new file mode 100644 index 0000000000..d149969b6e --- /dev/null +++ b/collect-earth/collect-earth-app/src/main/java/org/openforis/collect/earth/app/desktop/MacOpenFilesInvocationHandlerNewIos.java @@ -0,0 +1,65 @@ +package org.openforis.collect.earth.app.desktop; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Use reflection to be able to add the code specific to Mac OS X without generating compilation errors + * This class generates a Proxy so that an Interface method can be invoked. Sort of implementing an Interface using reflection + * @see How to implement an interface using Reflection + * @author Alfonso Sanchez-Paus Diaz + * + */ +public class MacOpenFilesInvocationHandlerNewIos implements java.lang.reflect.InvocationHandler { + + private final Logger logger = LoggerFactory.getLogger(MacOpenFilesInvocationHandlerNewIos.class); + + public MacOpenFilesInvocationHandlerNewIos() { + super(); + } + + public Object invoke(Object proxy, Method m, Object[] args) throws Throwable + + { + + Object result = null; + + try { + + // if the method name equals some method's name then call your method + if ( m!= null && m.getName().equals("openFiles") && args !=null && args.length>0) { + openFilesImplmentation(args[0]); + } + + } catch (Exception e) { + logger.error(" Error while interpreting invocation " , e ); + } finally { + logger.info("end method {}", m!=null?m.getName():"Unknown method"); + } + + return result; + + } + + private void openFilesImplmentation(Object openFilesEventObject) throws Exception { + Class openFilesEventClass = Class.forName("java.awt.dektop.OpenFilesEvent"); + Method getFilesMethod = openFilesEventClass.getMethod("getFiles"); + + List files = (List) getFilesMethod.invoke( openFilesEventClass.cast( openFilesEventObject ) ); + + for (File file : files ){ + try { + EarthApp.openProjectFileInRunningCollectEarth(file.getAbsolutePath()); + } catch (IOException e1) { + logger.error("Error opening CEP file " + e1); + } + } + + } + } +