package org.gudy.azureus2.ui.swt.osx; import java.lang.reflect.*; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.internal.C; import org.eclipse.swt.internal.Callback; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Shell; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.internat.MessageText; import org.gudy.azureus2.core3.util.AERunnable; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.config.wizard.ConfigureWizard; import org.gudy.azureus2.ui.swt.help.AboutWindow; import org.gudy.azureus2.ui.swt.mainwindow.SWTThread; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.nat.NatTestWindow; import org.gudy.azureus2.ui.swt.speedtest.SpeedTestWizard; import com.aelitis.azureus.core.impl.AzureusCoreImpl; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; /** * You can exclude this file (or this whole path) for non OSX builds * * Hook some Cocoa specific abilities: * - App->About <BR> * - App->Preferences <BR> * - App->Exit <BR> * <BR> * - OpenDocument (possible limited to only files?) <BR> * * This code was influenced by the * <a href="http://www.transparentech.com/opensource/cocoauienhancer"> * CocoaUIEnhancer</a>, which was influenced by the * <a href="http://www.simidude.com/blog/2008/macify-a-swt-application-in-a-cross-platform-way/"> * CarbonUIEnhancer from Agynami</a>. * * Both cocoa implementations are modified from * <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.ui.cocoa/src/org/eclipse/ui/internal/cocoa/CocoaUIEnhancer.java"> * org.eclipse.ui.internal.cocoa.CocoaUIEnhancer</a> */ public class CocoaUIEnhancer { public static final boolean is64bit = (System.getProperty("os.arch").indexOf("64") != -1); private static final boolean DEBUG = false; private static Object /*Callback*/ callBack3; private static long callBack3Addr; private static Object /*Callback*/ callBack4; private static long callBack4Addr; private static CocoaUIEnhancer instance; private static final int kAboutMenuItem = 0; private static final int kPreferencesMenuItem = 2; private static final int kServicesMenuItem = 4; // private static final int kHideApplicationMenuItem = 6; // private static final int kQuitMenuItem = 10; //private static int NSWindowCloseButton = 0; //private static int NSWindowDocumentIconButton = 4; //private static int NSWindowMiniaturizeButton = 1; private static int NSWindowToolbarButton = 3; //private static int NSWindowZoomButton = 2; private static long sel_aboutMenuItemSelected_; private static long sel_application_openFile_; private static long sel_application_openFiles_; private static long sel_preferencesMenuItemSelected_; private static long sel_applicationShouldHandleReopen_; private static long sel_toolbarButtonClicked_; private static long sel_restartMenuSelected_; private static long sel_wizardMenuSelected_; private static long sel_natMenuSelected_; private static long sel_speedMenuSelected_; private static boolean alreadyHaveOpenDoc; static final byte[] SWT_OBJECT = { 'S', 'W', 'T', '_', 'O', 'B', 'J', 'E', 'C', 'T', '\0' }; private long delegateIdSWTApplication; private long delegateJniRef; private Object delegate; private static boolean initialized = false; private static Class<?> osCls = classForName("org.eclipse.swt.internal.cocoa.OS"); private static Class<?> nsmenuCls = classForName("org.eclipse.swt.internal.cocoa.NSMenu"); private static Class<?> nsmenuitemCls = classForName("org.eclipse.swt.internal.cocoa.NSMenuItem"); private static Class<?> nsapplicationCls = classForName("org.eclipse.swt.internal.cocoa.NSApplication"); private static Class<?> nsarrayCls = classForName("org.eclipse.swt.internal.cocoa.NSArray"); private static Class<?> nsstringCls = classForName("org.eclipse.swt.internal.cocoa.NSString"); private static Class<?> swtmenuitemCls = classForName("org.eclipse.swt.internal.cocoa.SWTMenuItem"); private static Class<?> nsidCls = classForName("org.eclipse.swt.internal.cocoa.id"); private static Class<?> nsautoreleasepoolCls = classForName("org.eclipse.swt.internal.cocoa.NSAutoreleasePool"); private static Class<?> nsworkspaceCls = classForName("org.eclipse.swt.internal.cocoa.NSWorkspace"); private static Class<?> nsimageCls = classForName("org.eclipse.swt.internal.cocoa.NSImage"); private static Class<?> nssizeCls = classForName("org.eclipse.swt.internal.cocoa.NSSize"); static { Class<CocoaUIEnhancer> clazz = CocoaUIEnhancer.class; Class<?> callbackCls = classForName("org.eclipse.swt.internal.Callback"); try { SWT.class.getDeclaredField("OpenDocument"); alreadyHaveOpenDoc = true; } catch (Throwable t) { alreadyHaveOpenDoc = false; } try { Method mGetAddress = callbackCls.getMethod("getAddress", new Class[0]); Constructor<?> consCallback = callbackCls.getConstructor(new Class<?>[] { Object.class, String.class, int.class }); // callBack3 = new Callback(clazz, "actionProc", 3); callBack3 = consCallback.newInstance(new Object[] { clazz, "actionProc", 3 }); Object object = mGetAddress.invoke(callBack3, (Object[]) null); callBack3Addr = convertToLong(object); if (callBack3Addr == 0) { SWT.error(SWT.ERROR_NO_MORE_CALLBACKS); } //callBack4 = new Callback(clazz, "actionProc", 4); callBack4 = consCallback.newInstance(new Object[] { clazz, "actionProc", 4 }); object = mGetAddress.invoke(callBack4, (Object[]) null); callBack4Addr = convertToLong(object); if (callBack4Addr == 0) { SWT.error(SWT.ERROR_NO_MORE_CALLBACKS); } } catch (Throwable e) { Debug.out(e); } } /** Will be used with 32-bit SWT. */ static int actionProc(int id, int sel, int arg0) { return (int)actionProc((long) id, (long) sel, (long) arg0); } static long actionProc(long id, long sel, long arg0) { if (DEBUG) { System.err.println("id=" + id + ";sel=" + sel); } if (sel == sel_aboutMenuItemSelected_) { AboutWindow.show(SWTThread.getInstance().getDisplay()); } else if (sel == sel_restartMenuSelected_) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.dispose(true, false); } } else if (sel == sel_wizardMenuSelected_) { new ConfigureWizard(AzureusCoreImpl.getSingleton(), false); } else if (sel == sel_natMenuSelected_) { new NatTestWindow(); } else if (sel == sel_speedMenuSelected_) { new SpeedTestWizard(AzureusCoreImpl.getSingleton(), SWTThread.getInstance().getDisplay()); } else if (sel == sel_toolbarButtonClicked_) { try { Field fldsel_window = osCls.getField("sel_window"); Object windowId = invoke(osCls, "objc_msgSend", new Object[] { wrapPointer(arg0), fldsel_window.get(null) }); final Shell shellAffected = (Shell) invoke(Display.class, Display.getCurrent(), "findWidget", new Object[] { windowId }); Utils.execSWTThread(new AERunnable() { public void runSupport() { int type; Long l = (Long) shellAffected.getData("OSX.ToolBarToggle"); if (l == null || l.longValue() == 0) { type = SWT.Collapse; } else { type = SWT.Expand; } Event event = new Event(); event.type = type; event.display = shellAffected.getDisplay(); event.widget = shellAffected; shellAffected.notifyListeners(type, event); shellAffected.setData("OSX.ToolBarToggle", new Long( type == SWT.Collapse ? 1 : 0)); } }); } catch (Throwable t) { Debug.out(t); } } else if (sel == sel_preferencesMenuItemSelected_) { UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions(); if (uiFunctions != null) { uiFunctions.showConfig(null); } } return 0; } /** Will be used with 32-bit SWT. */ static int actionProc(int id, int sel, int arg0, int arg1) throws Throwable { return (int)actionProc((long) id, (long) sel, (long) arg0, (long) arg1); } static long actionProc(long id, long sel, long arg0, long arg1) throws Throwable { if (DEBUG) { System.err.println("actionProc 4 " + id + "/" + sel); } Display display = Display.getCurrent(); if (display == null) return 0; if (!alreadyHaveOpenDoc && sel == sel_application_openFile_) { Constructor<?> conNSString = nsstringCls.getConstructor(new Class[] { int.class }); Object file = conNSString.newInstance(arg1); String fileString = (String) invoke(file, "getString"); if (DEBUG) { System.err.println("OMG GOT OpenFile " + fileString); } fileOpen(new String[] { fileString }); } else if (!alreadyHaveOpenDoc && sel == sel_application_openFiles_) { Constructor<?> conNSArray = nsarrayCls.getConstructor(new Class[] { int.class }); Constructor<?> conNSString = nsstringCls.getConstructor(new Class[] { nsidCls }); Object arrayOfFiles = conNSArray.newInstance(arg1); int count = ((Number) invoke(arrayOfFiles, "count")).intValue(); String[] files = new String[count]; for (int i = 0; i < count; i++) { Object fieldId = invoke(nsarrayCls, arrayOfFiles, "objectAtIndex", new Object[] { i }); Object nsstring = conNSString.newInstance(fieldId); files[i] = (String) invoke(nsstring, "getString"); if (DEBUG) { System.err.println("OMG GOT OpenFiles " + files[i]); } } fileOpen(files); } else if (sel == sel_applicationShouldHandleReopen_) { Event event = new Event(); event.detail = 1; if (display != null) { invoke(Display.class, display, "sendEvent", new Class[] { int.class, Event.class }, new Object[] { SWT.Activate, event }); } } return 0; } private static Class<?> classForName(String classname) { try { Class<?> cls = Class.forName(classname); return cls; } catch (ClassNotFoundException e) { throw new IllegalStateException(e); } } private static long convertToLong(Object object) { if (object instanceof Integer) { Integer i = (Integer) object; return i.longValue(); } if (object instanceof Long) { Long l = (Long) object; return l.longValue(); } return 0; } protected static void fileOpen(final String[] files) { // AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { // public void azureusCoreRunning(AzureusCore core) { TorrentOpener.openTorrents(files); // } // }); } public static CocoaUIEnhancer getInstance() { if (instance == null) { try { instance = new CocoaUIEnhancer(); } catch (Throwable e) { Debug.out(e); } } return instance; } private static Object invoke(Class<?> clazz, Object target, String methodName, Object[] args) { try { Class<?>[] signature = new Class<?>[args.length]; for (int i = 0; i < args.length; i++) { Class<?> thisClass = args[i].getClass(); if (thisClass == Integer.class) signature[i] = int.class; else if (thisClass == Long.class) signature[i] = long.class; else if (thisClass == Byte.class) signature[i] = byte.class; else if (thisClass == Boolean.class) signature[i] = boolean.class; else signature[i] = thisClass; } Method method = clazz.getMethod(methodName, signature); return method.invoke(target, args); } catch (Exception e) { throw new IllegalStateException(e); } } private static Object invoke(Class<?> clazz, Object target, String methodName, Class[] signature, Object[] args) { try { Method method = clazz.getDeclaredMethod(methodName, signature); method.setAccessible(true); return method.invoke(target, args); } catch (Exception e) { throw new IllegalStateException(e); } } private static Object invoke(Class<?> clazz, String methodName, Object[] args) { return invoke(clazz, null, methodName, args); } private static Object invoke(Object obj, String methodName) { return invoke(obj, methodName, (Class<?>[]) null, (Object[]) null); } private static Object invoke(Object obj, String methodName, Class<?>[] paramTypes, Object... arguments) { try { Method m = obj.getClass().getMethod(methodName, paramTypes); return m.invoke(obj, arguments); } catch (Exception e) { throw new IllegalStateException(e); } } private static long registerName(Class<?> osCls, String name) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { Object object = invoke(osCls, "sel_registerName", new Object[] { name }); return convertToLong(object); } //////////////////////////////////////////////////////////// private static Object wrapPointer(long value) { Class<?> PTR_CLASS = C.PTR_SIZEOF == 8 ? long.class : int.class; if (PTR_CLASS == long.class) return new Long(value); else return new Integer((int) value); } private CocoaUIEnhancer() throws Throwable { // Instead of creating a new delegate class in objective-c, // just use the current SWTApplicationDelegate. An instance of this // is a field of the Cocoa Display object and is already the target // for the menuItems. So just get this class and add the new methods // to it. Object delegateObjSWTApplication = invoke(osCls, "objc_lookUpClass", new Object[] { "SWTApplicationDelegate" }); delegateIdSWTApplication = convertToLong(delegateObjSWTApplication); // This doesn't feel right, but it works Class<?> swtapplicationdelegateCls = classForName("org.eclipse.swt.internal.cocoa.SWTApplicationDelegate"); delegate = swtapplicationdelegateCls.newInstance(); Object delegateAlloc = invoke(delegate, "alloc"); invoke(delegateAlloc, "init"); Object delegateIdObj = nsidCls.getField("id").get(delegate); delegateJniRef = ((Number) invoke(osCls, "NewGlobalRef", new Class<?>[] { Object.class }, new Object[] { CocoaUIEnhancer.this })).longValue(); if (delegateJniRef == 0) SWT.error(SWT.ERROR_NO_HANDLES); //OS.object_setInstanceVariable(delegate.id, SWT_OBJECT, delegateJniRef); invoke(osCls, "object_setInstanceVariable", new Object[] { delegateIdObj, SWT_OBJECT, wrapPointer(delegateJniRef) }); } /** * Hook the given Listener to the Mac OS X application Quit menu and the IActions to the About * and Preferences menus. * * @param display * The Display to use. * @param quitListener * The listener to invoke when the Quit menu is invoked. * @param aboutAction * The action to run when the About menu is invoked. * @param preferencesAction * The action to run when the Preferences menu is invoked. */ public void hookApplicationMenu() { Display display = Display.getCurrent(); try { // Initialize the menuItems. initialize(); } catch (Exception e) { throw new IllegalStateException(e); } // Schedule disposal of callback object display.disposeExec(new Runnable() { public void run() { invoke(callBack3, "dispose"); callBack3 = null; invoke(callBack4, "dispose"); callBack4 = null; if (delegateJniRef != 0) { //OS.DeleteGlobalRef(delegateJniRef); invoke(osCls, "DeleteGlobalRef", new Object[] { wrapPointer(delegateJniRef) }); delegateJniRef = 0; } if (delegate != null) { invoke(delegate, "release"); delegate = null; } } }); } public void hookDocumentOpen() throws Throwable { if (alreadyHaveOpenDoc) { return; } if (sel_application_openFile_ == 0) { sel_application_openFile_ = registerName(osCls, "application:openFile:"); } invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_application_openFile_), wrapPointer(callBack4Addr), "@:@:@" }); if (sel_application_openFiles_ == 0) { sel_application_openFiles_ = registerName(osCls, "application:openFiles:"); } invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_application_openFiles_), wrapPointer(callBack4Addr), "@:@:@" }); } private void initialize() throws Exception { // Register names in objective-c. if (sel_preferencesMenuItemSelected_ == 0) { sel_preferencesMenuItemSelected_ = registerName(osCls, "preferencesMenuItemSelected:"); sel_aboutMenuItemSelected_ = registerName(osCls, "aboutMenuItemSelected:"); sel_restartMenuSelected_ = registerName(osCls, "restartMenuItemSelected:"); sel_natMenuSelected_ = registerName(osCls, "natMenuItemSelected:"); sel_speedMenuSelected_ = registerName(osCls, "speedMenuItemSelected:"); sel_wizardMenuSelected_ = registerName(osCls, "wizardMenuItemSelected:"); sel_applicationShouldHandleReopen_ = registerName(osCls, "applicationShouldHandleReopen:hasVisibleWindows:"); } // Add the action callbacks for Preferences and About menu items. invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_preferencesMenuItemSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_aboutMenuItemSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_restartMenuSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_wizardMenuSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_speedMenuSelected_), wrapPointer(callBack3Addr), "@:@" }); invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_natMenuSelected_), wrapPointer(callBack3Addr), "@:@" }); /** * class_addMethod will fail if someone has previously registered for this selector. * The latest cocoa version of SWT does this, simply returning '1' when called. * (See Display.java lines 4711--4713.) * To replace their implementation, we need to use method_setImplementation instead. * (Since SWT doesn't provide method_setImplementation.) */ Boolean success = (Boolean)invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_applicationShouldHandleReopen_), wrapPointer(callBack4Addr), "@:@c" }); if (!success) { Long method = (Long)invoke(osCls, "class_getInstanceMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_applicationShouldHandleReopen_) }); invoke(osCls, "method_setImplementation", new Object[] { wrapPointer(method.longValue()), wrapPointer(callBack4Addr) }); } // Get the Mac OS X Application menu. Object sharedApplication = invoke(nsapplicationCls, "sharedApplication"); Object mainMenu = invoke(sharedApplication, "mainMenu"); Object mainMenuItem = invoke(nsmenuCls, mainMenu, "itemAtIndex", new Object[] { wrapPointer(0) }); Object appMenu = invoke(mainMenuItem, "submenu"); // Create the About <application-name> menu command Object aboutMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer(kAboutMenuItem) }); // Enable the Preferences menuItem. Object prefMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer(kPreferencesMenuItem) }); invoke(nsmenuitemCls, prefMenuItem, "setEnabled", new Object[] { true }); Object servicesMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer(kServicesMenuItem) }); invoke(nsmenuitemCls, servicesMenuItem, "setEnabled", new Object[] { false }); // Set the action to execute when the About or Preferences menuItem is invoked. // // We don't need to set the target here as the current target is the SWTApplicationDelegate // and we have registerd the new selectors on it. So just set the new action to invoke the // selector. invoke(nsmenuitemCls, prefMenuItem, "setAction", new Object[] { wrapPointer(sel_preferencesMenuItemSelected_) }); invoke(nsmenuitemCls, aboutMenuItem, "setAction", new Object[] { wrapPointer(sel_aboutMenuItemSelected_) }); // Add other menus Object menuId = appMenu.getClass().getField("id").get(appMenu); boolean isAZ3 = "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui")); if (!isAZ3) { // add Wizard, NAT Test, Speed Test addMenuItem(menuId, 5, sel_wizardMenuSelected_, MessageText.getString("MainWindow.menu.file.configure").replaceAll( "&", "")); addMenuItem(menuId, 6, sel_natMenuSelected_, MessageText.getString( "MainWindow.menu.tools.nattest").replaceAll("&", "")); addMenuItem(menuId, 7, sel_speedMenuSelected_, MessageText.getString("MainWindow.menu.tools.speedtest").replaceAll( "&", "")); } int numOfItems = ((Number) invoke(appMenu, "numberOfItems")).intValue(); Object sep = invoke(osCls, "objc_msgSend", new Object[] { osCls.getField("class_NSMenuItem").get(null), osCls.getField("sel_separatorItem").get(null) }); invoke(osCls, "objc_msgSend", new Object[] { sep, osCls.getField("sel_retain").get(null) }); //OS.objc_msgSend(menuId, OS.sel_insertItem_atIndex_, sep, numOfItems - 1); invoke(osCls, "objc_msgSend", new Object[] { menuId, osCls.getField("sel_insertItem_atIndex_").get(null), sep, is64bit ? (long) (numOfItems - 1) : (numOfItems - 1) }); numOfItems++; addMenuItem(menuId, numOfItems - 1, (int) sel_restartMenuSelected_, MessageText.getString("MainWindow.menu.file.restart").replaceAll("&", "")); initialized = true; } private void addMenuItem(Object menuId, int index, long selector, String title) { try { //NSMenuItem nsItem = (NSMenuItem) new SWTMenuItem().alloc(); Object oSWTMenuItem = swtmenuitemCls.newInstance(); Object nsItem = invoke(oSWTMenuItem, "alloc"); Object nsStrTitle = invoke(nsstringCls, "stringWith", new Object[] { title }); Object nsStrEmpty = invoke(nsstringCls, "stringWith", new Object[] { "" }); invoke(nsmenuitemCls, nsItem, "initWithTitle", new Object[] { nsStrTitle, is64bit ? 0L : 0, nsStrEmpty }); invoke(nsItem, "setTarget", new Class<?>[] { nsidCls }, new Object[] { delegate }); invoke(nsmenuitemCls, nsItem, "setAction", new Object[] { wrapPointer(selector) }); //OS.objc_msgSend(menuId, OS.sel_insertItem_atIndex_, nsItem.id, index); invoke(osCls, "objc_msgSend", new Object[] { menuId, osCls.getField("sel_insertItem_atIndex_").get(null), nsmenuitemCls.getField("id").get(nsItem), is64bit ? (long) index : index }); } catch (Throwable e) { Debug.out(e); } } private Object invoke(Class<?> cls, String methodName) { return invoke(cls, methodName, (Class<?>[]) null, (Object[]) null); } private Object invoke(Class<?> cls, String methodName, Class<?>[] paramTypes, Object... arguments) { try { Method m = cls.getMethod(methodName, paramTypes); return m.invoke(null, arguments); } catch (Exception e) { throw new IllegalStateException(e); } } public void registerToolbarToggle(Shell shell) throws Throwable { if (sel_toolbarButtonClicked_ == 0) { sel_toolbarButtonClicked_ = registerName(osCls, "toolbarButtonClicked:"); } invoke(osCls, "class_addMethod", new Object[] { wrapPointer(delegateIdSWTApplication), wrapPointer(sel_toolbarButtonClicked_), wrapPointer(callBack3Addr), "@:@" }); Class<?> nstoolbarCls = classForName("org.eclipse.swt.internal.cocoa.NSToolbar"); Class<?> nsbuttonCls = classForName("org.eclipse.swt.internal.cocoa.NSButton"); //NSToolbar dummyBar = new NSToolbar(); Object dummyBar = nstoolbarCls.newInstance(); //dummyBar.alloc(); invoke(dummyBar, "alloc"); //dummyBar.initWithIdentifier(NSString.stringWith("SWTToolbar")); Object nsStrDummyToolbar = invoke(nsstringCls, "stringWith", new Object[] { "SWTToolbar" }); invoke(dummyBar, "initWithIdentifier", new Class<?>[] { nsstringCls }, new Object[] { nsStrDummyToolbar }); //dummyBar.setVisible(false); invoke(dummyBar, "setVisible", new Class<?>[] { boolean.class }, new Object[] { Boolean.FALSE }); // reflect me //NSWindow nsWindow = shell.view.window(); Object view = shell.getClass().getField("view").get(shell); Object nsWindow = invoke(view, "window"); //nsWindow.setToolbar(dummyBar); invoke(nsWindow, "setToolbar", new Class<?>[] { nstoolbarCls }, new Object[] { dummyBar }); //nsWindow.setShowsToolbarButton(true); invoke(nsWindow, "setShowsToolbarButton", new Class<?>[] { boolean.class }, new Object[] { Boolean.TRUE }); //NSButton toolbarButton = nsWindow.standardWindowButton(NSWindowToolbarButton); Object toolbarButton = invoke(nsWindow, "standardWindowButton", new Class<?>[] { int.class }, new Object[] { new Integer(NSWindowToolbarButton) }); //toolbarButton.setTarget(delegate); invoke(toolbarButton, "setTarget", new Class[] { nsidCls }, new Object[] { delegate }); //OS.objc_msgSend(this.id, OS.sel_setTarget_, anObject != null ? anObject.id : 0); //invoke(osCls, "objc_msgSend", new Object[] { // toolbarButton.getClass().getField("id").get(toolbarButton), // osCls.getField("sel_setTarget_").get(null), // wrapPointer(delegateIdSWTApplication) //}); //toolbarButton.setAction((int) sel_toolbarButtonClicked_); invoke(nsbuttonCls, toolbarButton, "setAction", new Object[] { wrapPointer(sel_toolbarButtonClicked_) }); } // from Program.getImageData, except returns bigger images public static Image getFileIcon (String path, int imageWidthHeight) { Object pool = null; try { //NSAutoreleasePool pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init(); pool = nsautoreleasepoolCls.newInstance(); Object delegateAlloc = invoke(pool, "alloc"); invoke(delegateAlloc, "init"); //NSWorkspace workspace = NSWorkspace.sharedWorkspace(); Object workspace = invoke(nsworkspaceCls, "sharedWorkspace", new Object[] {}); //NSString fullPath = NSString.stringWith(path); Object fullPath = invoke(nsstringCls, "stringWith", new Object[] { path }); if (fullPath != null) { // SWT also had a : // fullPath = workspace.fullPathForApplication(NSString.stringWith(name)); // which might be handy someday, but for now, full path works //NSImage nsImage = workspace.iconForFile(fullPath); Object nsImage = invoke(workspace, "iconForFile", new Class[] { nsstringCls }, new Object[] { fullPath }); if (nsImage != null) { //NSSize size = new NSSize(); Object size = nssizeCls.newInstance(); //size.width = size.height = imageWidthHeight; nssizeCls.getField("width").set(size, imageWidthHeight); nssizeCls.getField("height").set(size, imageWidthHeight); //nsImage.setSize(size); invoke(nsImage, "setSize", new Class[] { nssizeCls }, new Object[] { size }); //nsImage.retain(); invoke(nsImage, "retain"); //Image image = Image.cocoa_new(Display.getCurrent(), SWT.BITMAP, nsImage); Image image = (Image) invoke(Image.class, null, "cocoa_new", new Class[] { Device.class, int.class, nsimageCls }, new Object[] { Display.getCurrent(), SWT.BITMAP, nsImage }); return image; } } } catch (Throwable t) { Debug.printStackTrace(t); } finally { if (pool != null) { invoke(pool, "release"); } } return null; } public static boolean isInitialized() { return initialized; } }