urls = classLoader.getResources(JarFile.MANIFEST_NAME);
+ while (urls.hasMoreElements()) {
+ URL url = (URL) urls.nextElement();
+ InputStream inputStream = url.openStream();
+ if (inputStream != null) {
+ Manifest manifest = new Manifest(inputStream);
+ Attributes mainAttributes = manifest.getMainAttributes();
+ String bundleId = mainAttributes.getValue("Bundle-SymbolicName");
+ if (bundleId != null && bundleId.startsWith("org.jboss.tools.vpe.browsersim")) {
+ version = mainAttributes.getValue("Bundle-Version");
+ return version;
+
+ }
+ }
+ }
+
+ // If Manifest Version is not in jar
+ URL url1 = getClass().getClassLoader().getResource(".");
+ if ("file".equals(url1.getProtocol())) {
+ File manifestFile;
+ File binDir = new File(url1.getFile());
+ File browsersimDir = binDir.getParentFile();
+ manifestFile = new File(browsersimDir, JarFile.MANIFEST_NAME);
+ FileInputStream inputStream = new FileInputStream(manifestFile);
+ Manifest manifestFromFile = new Manifest(inputStream);
+
+ version = manifestFromFile.getMainAttributes().getValue("Bundle-version");
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+
+ }
+
+ return version;
+
+ }
+
+ public void showAboutDialog(Shell shell){
+ String message;
+ String version = getManifestVersion();
+ if (version != null) {
+ message = MessageFormat.format(Messages.BrowserSim_ABOUT_MESSAGE,getManifestVersion());
+ } else {
+ message = MessageFormat.format(Messages.BrowserSim_ABOUT_MESSAGE, "");
+ }
+ new MessageBoxWithLinks(shell,
+ message,
+ icons[BROWSERSIM_ICON_32PX_INDEX],
+ Messages.BrowserSim_ABOUT).open();
+ }
+
+
private ResizableSkinSizeAdvisor getSizeAdvisor() {
if (sizeAdvisor == null) {
sizeAdvisor = new ResizableSkinSizeAdvisor() {
@@ -677,4 +810,67 @@
return sizeAdvisor;
}
+
+ public void addMacOsMenuApplicationHandler(final BrowserSim browserSim) {
+
+
+ CocoaUIEnhancer enhancer = new CocoaUIEnhancer("BrowserSim");
+
+ Listener quitListener = new Listener() {
+
+ @Override
+ public void handleEvent(Event event) {
+ // Quit Listener has no implementation, cause quit event is handled by controlHandler,
+ // but it must be in CocoaUIEnchancer released by EPL
+ }
+ };
+
+ Runnable macAboutAction = new Runnable() {
+
+ @Override
+ public void run() {
+
+ Shell shell;
+ if (browserSim.skin != null && browserSim.skin != null
+ && browserSim.skin.getShell() != null) {
+ shell = browserSim.skin.getShell();
+ } else {
+ shell = new Shell();
+ }
+
+ showAboutDialog(shell);
+
+ }
+ };
+
+ Runnable macPreferencesAction = new Runnable() {
+
+ @Override
+ public void run() {
+
+ Shell shell;
+ if (browserSim != null && browserSim.skin != null
+ && browserSim.skin.getShell() != null) {
+ shell = browserSim.skin.getShell();
+ } else {
+ shell = new Shell();
+ }
+
+ DevicesList newDevicesList = new ManageDevicesDialog(shell,
+ SWT.APPLICATION_MODAL | SWT.SHELL_TRIM,
+ devicesListHolder.getDevicesList()).open();
+ if (newDevicesList != null) {
+ devicesListHolder.setDevicesList(newDevicesList);
+ devicesListHolder.notifyObservers();
+ }
+
+ }
+ };
+
+ enhancer.hookApplicationMenu(display, quitListener, macAboutAction, macPreferencesAction);
+
+
+ }
+
+
}
Index: src/org/jboss/tools/vpe/browsersim/ui/CocoaUIEnhancer.java
===================================================================
--- src/org/jboss/tools/vpe/browsersim/ui/CocoaUIEnhancer.java (revision 0)
+++ src/org/jboss/tools/vpe/browsersim/ui/CocoaUIEnhancer.java (working copy)
@@ -0,0 +1,284 @@
+package org.jboss.tools.vpe.browsersim.ui;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.C;
+import org.eclipse.swt.internal.Callback;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Provide a hook to connecting the Preferences, About and Quit menu items of the Mac OS X
+ * Application menu when using the SWT Cocoa bindings.
+ *
+ * This code does not require the Cocoa SWT JAR in order to be compiled as it uses reflection to
+ * access the Cocoa specific API methods. It does, however, depend on JFace (for IAction), but you
+ * could easily modify the code to use SWT Listeners instead in order to use this class in SWT only
+ * applications.
+ *
+ *
+ * This code was influenced by the CarbonUIEnhancer from Agynami with the implementation being modified from the org.eclipse.ui.internal.cocoa.CocoaUIEnhancer.
+ *
+ */
+public class CocoaUIEnhancer {
+
+ 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;
+
+ static long sel_toolbarButtonClicked_;
+ static long sel_preferencesMenuItemSelected_;
+ static long sel_aboutMenuItemSelected_;
+
+ static Callback proc3Args;
+
+ final private String appName;
+
+ /**
+ * Construct a new CocoaUIEnhancer.
+ *
+ * @param appName
+ * The name of the application. It will be used to customize the About and Quit menu
+ * items. If you do not wish to customize the About and Quit menu items, just pass
+ * null here.
+ */
+ public CocoaUIEnhancer( String appName ) {
+ this.appName = appName;
+ }
+
+ /**
+ * 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, Listener quitListener, final Runnable aboutAction,
+ final Runnable preferencesAction ) {
+ // This is our callbackObject whose 'actionProc' method will be called when the About or
+ // Preferences menuItem is invoked.
+ //
+ // Connect the given IAction objects to the actionProce method.
+ //
+ Object target = new Object() {
+ @SuppressWarnings( "unused" )
+ int actionProc( int id, int sel, int arg0 ) {
+ if ( sel == sel_aboutMenuItemSelected_ ) {
+ aboutAction.run();
+ } else if ( sel == sel_preferencesMenuItemSelected_ ) {
+ preferencesAction.run();
+ } else {
+ // Unknown selection!
+ }
+ // Return value is not used.
+ return 99;
+ }
+ };
+
+ try {
+ // Initialize the menuItems.
+ initialize( target );
+ } catch ( Exception e ) {
+ throw new IllegalStateException( e );
+ }
+
+ // Connect the quit/exit menu.
+ if ( !display.isDisposed() ) {
+// display.addListener( SWT.Close, quitListener );
+ }
+
+ // Schedule disposal of callback object
+ display.disposeExec( new Runnable() {
+ public void run() {
+ invoke( proc3Args, "dispose" );
+ }
+ } );
+ }
+
+ private void initialize( Object callbackObject )
+ throws Exception {
+
+ Class> osCls = classForName( "org.eclipse.swt.internal.cocoa.OS" );
+
+ // Register names in objective-c.
+ if ( sel_toolbarButtonClicked_ == 0 ) {
+ // sel_toolbarButtonClicked_ = registerName( osCls, "toolbarButtonClicked:" ); //$NON-NLS-1$
+ sel_preferencesMenuItemSelected_ = registerName( osCls, "preferencesMenuItemSelected:" ); //$NON-NLS-1$
+ sel_aboutMenuItemSelected_ = registerName( osCls, "aboutMenuItemSelected:" ); //$NON-NLS-1$
+ }
+
+ // Create an SWT Callback object that will invoke the actionProc method of our internal
+ // callbackObject.
+ proc3Args = new Callback( callbackObject, "actionProc", 3 ); //$NON-NLS-1$
+ Method getAddress = Callback.class.getMethod( "getAddress", new Class[0] );
+ Object object = getAddress.invoke( proc3Args, (Object[]) null );
+ long proc3 = convertToLong( object );
+ if ( proc3 == 0 ) {
+ SWT.error( SWT.ERROR_NO_MORE_CALLBACKS );
+ }
+
+ Class> nsmenuCls = classForName( "org.eclipse.swt.internal.cocoa.NSMenu" );
+ Class> nsmenuitemCls = classForName( "org.eclipse.swt.internal.cocoa.NSMenuItem" );
+ Class> nsstringCls = classForName( "org.eclipse.swt.internal.cocoa.NSString" );
+ Class> nsapplicationCls = classForName( "org.eclipse.swt.internal.cocoa.NSApplication" );
+
+ // 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 = invoke( osCls, "objc_lookUpClass", new Object[] { "SWTApplicationDelegate" } );
+ long cls = convertToLong( object );
+
+ // Add the action callbacks for Preferences and About menu items.
+ invoke( osCls, "class_addMethod", new Object[] {
+ wrapPointer( cls ),
+ wrapPointer( sel_preferencesMenuItemSelected_ ),
+ wrapPointer( proc3 ),
+ "@:@" } ); //$NON-NLS-1$
+ invoke( osCls, "class_addMethod", new Object[] {
+ wrapPointer( cls ),
+ wrapPointer( sel_aboutMenuItemSelected_ ),
+ wrapPointer( proc3 ),
+ "@:@" } ); //$NON-NLS-1$
+
+ // 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 menu command
+ Object aboutMenuItem =
+ invoke( nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer( kAboutMenuItem ) } );
+ if ( appName != null ) {
+ Object nsStr = invoke( nsstringCls, "stringWith", new Object[] { "About " + appName } );
+ invoke( nsmenuitemCls, aboutMenuItem, "setTitle", new Object[] { nsStr } );
+ }
+ // Rename the quit action.
+ if ( appName != null ) {
+ Object quitMenuItem =
+ invoke( nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer( kQuitMenuItem ) } );
+ Object nsStr = invoke( nsstringCls, "stringWith", new Object[] { "Quit " + appName } );
+ invoke( nsmenuitemCls, quitMenuItem, "setTitle", new Object[] { nsStr } );
+ }
+
+ // Enable the Preferences menuItem.
+ Object prefMenuItem =
+ invoke( nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer( kPreferencesMenuItem ) } );
+ invoke( nsmenuitemCls, prefMenuItem, "setEnabled", new Object[] { true } );
+
+ // 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_ ) } );
+ }
+
+ private 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 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;
+ }
+
+ 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 static Object invoke( Class> clazz, String methodName, Object[] args ) {
+ return invoke( clazz, null, methodName, args );
+ }
+
+ 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 Class> classForName( String classname ) {
+ try {
+ Class> cls = Class.forName( classname );
+ return cls;
+ } catch ( ClassNotFoundException e ) {
+ throw new IllegalStateException( 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.getDeclaredMethod( methodName, paramTypes );
+ return m.invoke( null, arguments );
+ } catch ( Exception e ) {
+ throw new IllegalStateException( e );
+ }
+ }
+
+ private Object invoke( Object obj, String methodName ) {
+ return invoke( obj, methodName, (Class>[]) null, (Object[]) null );
+ }
+
+ private Object invoke( Object obj, String methodName, Class>[] paramTypes, Object... arguments ) {
+ try {
+ Method m = obj.getClass().getDeclaredMethod( methodName, paramTypes );
+ return m.invoke( obj, arguments );
+ } catch ( Exception e ) {
+ throw new IllegalStateException( e );
+ }
+ }
+}
Index: src/org/jboss/tools/vpe/browsersim/ui/ExceptionNotifier.java
===================================================================
--- src/org/jboss/tools/vpe/browsersim/ui/ExceptionNotifier.java (revision 41070)
+++ src/org/jboss/tools/vpe/browsersim/ui/ExceptionNotifier.java (working copy)
@@ -14,14 +14,6 @@
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.program.Program;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Link;
-import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.jboss.tools.vpe.browsersim.browser.PlatformUtil;
@@ -50,70 +42,25 @@
}
showErrorMessageWithLinks(parentShell, message);
}
-
+
public static void showErrorMessage(Shell shell, String message) {
System.err.println(message);
-
+
MessageBox messageBox = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
messageBox.setText(Messages.BrowserSim_ERROR);
messageBox.setMessage(message);
messageBox.open();
}
-
+
public static void showErrorMessageWithLinks(Shell shell, String message) {
System.err.println(message);
-
- ErrorMessageBoxWithLinks messageBox = new ErrorMessageBoxWithLinks(shell);
- messageBox.setText(Messages.BrowserSim_ERROR);
- messageBox.setMessage(message);
+
+ MessageBoxWithLinks messageBox = new MessageBoxWithLinks(shell,
+ message, shell.getDisplay().getSystemImage(SWT.ICON_ERROR),
+ Messages.BrowserSim_ERROR);
messageBox.open();
}
}
-/**
- * Behaves like MessageBox with styles SWT.OK and SWT.ICON_ERROR, but allows HTML links is messages.
- * @author Yahor Radtsevich (yradtsevich)
- *
- */
-class ErrorMessageBoxWithLinks extends CustomMessageBox {
- private String message;
-
- public ErrorMessageBoxWithLinks(Shell parent) {
- super(parent, parent.getDisplay().getSystemImage(SWT.ICON_ERROR));
- message = ""; //$NON-NLS-1$
- }
-
- @Override
- protected void createWidgets() {
- super.createWidgets();
-
- Link link = new Link(getMessageComposite(), SWT.WRAP);
- link.setText(message);
- link.setBackground(getMessageCompositeBackground());
- link.addListener (SWT.Selection, new Listener () {
- public void handleEvent(Event event) {
- Program.launch(event.text);
- }
- });
-
- Button ok = new Button(getButtonsComposite(), SWT.PUSH);
- ok.setText(Messages.ExceptionNotifier_OK);
- ok.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- getShell().close();
- }
- });
- GridData okLayoutData = new GridData(SWT.END, SWT.CENTER, true, true);
- okLayoutData.widthHint = 88;
- ok.setLayoutData(okLayoutData);
- getShell().setDefaultButton(ok);
- getShell().pack();
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-}
Index: src/org/jboss/tools/vpe/browsersim/ui/CustomMessageBox.java
===================================================================
--- src/org/jboss/tools/vpe/browsersim/ui/CustomMessageBox.java (revision 41070)
+++ src/org/jboss/tools/vpe/browsersim/ui/CustomMessageBox.java (working copy)
@@ -48,7 +48,7 @@
}
protected void createWidgets() {
- shell = new Shell(getParent(), SWT.DIALOG_TRIM);
+ shell = new Shell(getParent(), SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
GridLayout shellLayout = new GridLayout(1, true);
shellLayout.marginHeight = 0;
shellLayout.marginWidth = 0;
Index: src/org/jboss/tools/vpe/browsersim/ui/EditDeviceDialog.java
===================================================================
--- src/org/jboss/tools/vpe/browsersim/ui/EditDeviceDialog.java (revision 41070)
+++ src/org/jboss/tools/vpe/browsersim/ui/EditDeviceDialog.java (working copy)
@@ -87,7 +87,7 @@
* Create contents of the dialog.
*/
private void createContents() {
- shell = new Shell(getParent(), SWT.DIALOG_TRIM | SWT.MIN | SWT.MAX);
+ shell = new Shell(getParent(), getStyle());
shell.setSize(450, 300);
shell.setText(Messages.EditDeviceDialog_EDIT_DEVICE);
shell.setLayout(new GridLayout(2, false));
Index: src/org/jboss/tools/vpe/browsersim/ui/Messages.java
===================================================================
--- src/org/jboss/tools/vpe/browsersim/ui/Messages.java (revision 41070)
+++ src/org/jboss/tools/vpe/browsersim/ui/Messages.java (working copy)
@@ -23,6 +23,8 @@
public static String BrowserSim_COULD_NOT_OPEN_DEFAULT_BROWSER;
public static String BrowserSim_DEVICES;
public static String BrowserSim_ERROR;
+ public static String BrowserSim_HELP;
+ public static String BrowserSim_ABOUT;
public static String BrowserSim_EXIT;
public static String BrowserSim_FILE;
public static String BrowserSim_OPEN_IN_DEFAULT_BROWSER;
@@ -31,6 +33,7 @@
public static String BrowserSim_TURN_RIGHT;
public static String BrowserSim_USE_SKINS;
public static String BrowserSim_VIEW_PAGE_SOURCE;
+ public static String BrowserSim_ABOUT_MESSAGE;
public static String EditDeviceDialog_CANCEL;
public static String EditDeviceDialog_EDIT_DEVICE;
public static String EditDeviceDialog_HEIGHT;