/*
* Copyright 2010-2015 Institut Pasteur.
*
* This file is part of Icy.
*
* Icy is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Icy 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Icy. If not, see <http://www.gnu.org/licenses/>.
*/
package icy.system;
import icy.gui.dialog.LoaderDialog;
import icy.gui.frame.AboutFrame;
import icy.gui.preferences.GeneralPreferencePanel;
import icy.gui.preferences.PreferenceFrame;
import icy.main.Icy;
import icy.resource.ResourceUtil;
import icy.system.thread.ThreadUtil;
import java.awt.Toolkit;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* OSX application compatibility class
*
* @author stephane
*/
public class AppleUtil
{
static final Thread fixThread = new Thread(new Runnable()
{
@Override
public void run()
{
appleFixLiveRun();
}
}, "AppleFix");
@SuppressWarnings({"unchecked", "rawtypes"})
public static void init()
{
// only when we have the GUI
if (!Icy.getMainInterface().isHeadLess())
{
try
{
final ClassLoader classLoader = SystemUtil.getSystemClassLoader();
final Class appClass = classLoader.loadClass("com.apple.eawt.Application");
final Object app = appClass.newInstance();
final Class listenerClass = classLoader.loadClass("com.apple.eawt.ApplicationListener");
final Object listener = Proxy.newProxyInstance(classLoader, new Class[] {listenerClass},
new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
final Object applicationEvent = args[0];
final Class appEventClass = applicationEvent.getClass();
final Method m = appEventClass.getMethod("setHandled", boolean.class);
if (method.getName().equals("handleQuit"))
{
m.invoke(applicationEvent, Boolean.valueOf(Icy.exit(false)));
}
if (method.getName().equals("handleAbout"))
{
new AboutFrame();
m.invoke(applicationEvent, Boolean.valueOf(true));
}
if (method.getName().equals("handleOpenFile"))
{
new LoaderDialog();
m.invoke(applicationEvent, Boolean.valueOf(true));
}
if (method.getName().equals("handlePreferences"))
{
new PreferenceFrame(GeneralPreferencePanel.NODE_NAME);
m.invoke(applicationEvent, Boolean.valueOf(true));
}
return null;
}
});
Method m;
m = appClass.getMethod("addApplicationListener", listenerClass);
m.invoke(app, listener);
m = appClass.getMethod("setDockIconImage", java.awt.Image.class);
m.invoke(app, ResourceUtil.IMAGE_ICY_256);
m = appClass.getMethod("addPreferencesMenuItem");
m.invoke(app);
// set menu bar name
SystemUtil.setProperty("com.apple.mrj.application.apple.menu.about.name", "Icy");
}
catch (Exception e)
{
System.err.println("Can't install OSX application wrapper...");
}
}
// start the fix thread
fixThread.start();
}
/**
* Apple fix live run (fixes specific OS X JVM stuff)
*/
static void appleFixLiveRun()
{
while (true)
{
final Toolkit toolkit = Toolkit.getDefaultToolkit();
// fix memory leak introduced in java 1.6.0_29 in Mac OS X JVM
// TODO : remove this when issue will be resolved in JVM
final PropertyChangeListener[] leak = toolkit.getPropertyChangeListeners("apple.awt.contentScaleFactor");
// remove listener
for (int i = 0; i < leak.length; i++)
toolkit.removePropertyChangeListener("apple.awt.contentScaleFactor", leak[i]);
// no need more...
ThreadUtil.sleep(500);
}
}
}