1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.menubar; 18 19 import org.eclipse.jface.action.IAction; 20 import org.eclipse.jface.action.IMenuManager; 21 import org.eclipse.jface.action.Separator; 22 import org.eclipse.swt.SWT; 23 import org.eclipse.swt.events.SelectionAdapter; 24 import org.eclipse.swt.events.SelectionEvent; 25 import org.eclipse.swt.widgets.Display; 26 import org.eclipse.swt.widgets.Menu; 27 import org.eclipse.swt.widgets.MenuItem; 28 29 30 /** 31 * On Mac, {@link MenuBarEnhancer#setupMenu} plugs a listener on the About and the 32 * Preferences menu items of the standard "application" menu in the menu bar. 33 * On Windows or Linux, it adds relevant items to a given {@link Menu} linked to 34 * the same listeners. 35 */ 36 public final class MenuBarEnhancer { 37 MenuBarEnhancer()38 private MenuBarEnhancer() { 39 } 40 41 /** 42 * Creates an instance of {@link IMenuBarEnhancer} specific to the current platform 43 * and invoke its {@link IMenuBarEnhancer#setupMenu} to updates the menu bar. 44 * <p/> 45 * Depending on the platform, this will either hook into the existing About menu item 46 * and a Preferences or Options menu item or add new ones to the given {@code swtMenu}. 47 * Depending on the platform, the menu items might be decorated with the 48 * given {@code appName}. 49 * <p/> 50 * Potential errors are reported through {@link IMenuBarCallback}. 51 * 52 * @param appName Name used for the About menu item and similar. Must not be null. 53 * @param swtMenu For non-mac platform this is the menu where the "About" and 54 * the "Options" menu items are created. Typically the menu might be 55 * called "Tools". Must not be null. 56 * @param callbacks Callbacks called when "About" and "Preferences" menu items are invoked. 57 * Must not be null. 58 * @return A actual {@link IMenuBarEnhancer} implementation. Never null. 59 * This is currently not of any use for the caller but is left in case 60 * we want to expand the functionality later. 61 */ setupMenu( String appName, final Menu swtMenu, IMenuBarCallback callbacks)62 public static IMenuBarEnhancer setupMenu( 63 String appName, 64 final Menu swtMenu, 65 IMenuBarCallback callbacks) { 66 67 IMenuBarEnhancer enhancer = getEnhancer(callbacks); 68 69 // Default implementation for generic platforms 70 if (enhancer == null) { 71 enhancer = new IMenuBarEnhancer() { 72 73 public MenuBarMode getMenuBarMode() { 74 return MenuBarMode.GENERIC; 75 } 76 77 public void setupMenu( 78 String appName, 79 Display display, 80 final IMenuBarCallback callbacks) { 81 if (swtMenu.getItemCount() > 0) { 82 new MenuItem(swtMenu, SWT.SEPARATOR); 83 } 84 85 // Note: we use "Preferences" on Mac and "Options" on Windows/Linux. 86 final MenuItem pref = new MenuItem(swtMenu, SWT.NONE); 87 pref.setText("&Options..."); 88 89 final MenuItem about = new MenuItem(swtMenu, SWT.NONE); 90 about.setText("&About..."); 91 92 pref.addSelectionListener(new SelectionAdapter() { 93 @Override 94 public void widgetSelected(SelectionEvent e) { 95 try { 96 pref.setEnabled(false); 97 callbacks.onPreferencesMenuSelected(); 98 super.widgetSelected(e); 99 } finally { 100 pref.setEnabled(true); 101 } 102 } 103 }); 104 105 about.addSelectionListener(new SelectionAdapter() { 106 @Override 107 public void widgetSelected(SelectionEvent e) { 108 try { 109 about.setEnabled(false); 110 callbacks.onAboutMenuSelected(); 111 super.widgetSelected(e); 112 } finally { 113 about.setEnabled(true); 114 } 115 } 116 }); 117 } 118 }; 119 } 120 121 enhancer.setupMenu(appName, swtMenu.getDisplay(), callbacks); 122 return enhancer; 123 } 124 125 setupMenuManager( String appName, Display display, final IMenuManager menuManager, final IAction aboutAction, final IAction preferencesAction, final IAction quitAction)126 public static IMenuBarEnhancer setupMenuManager( 127 String appName, 128 Display display, 129 final IMenuManager menuManager, 130 final IAction aboutAction, 131 final IAction preferencesAction, 132 final IAction quitAction) { 133 134 IMenuBarCallback callbacks = new IMenuBarCallback() { 135 public void printError(String format, Object... args) { 136 System.err.println(String.format(format, args)); 137 } 138 139 public void onPreferencesMenuSelected() { 140 if (preferencesAction != null) { 141 preferencesAction.run(); 142 } 143 } 144 145 public void onAboutMenuSelected() { 146 if (aboutAction != null) { 147 aboutAction.run(); 148 } 149 } 150 }; 151 152 IMenuBarEnhancer enhancer = getEnhancer(callbacks); 153 154 // Default implementation for generic platforms 155 if (enhancer == null) { 156 enhancer = new IMenuBarEnhancer() { 157 158 public MenuBarMode getMenuBarMode() { 159 return MenuBarMode.GENERIC; 160 } 161 162 public void setupMenu( 163 String appName, 164 Display display, 165 final IMenuBarCallback callbacks) { 166 if (!menuManager.isEmpty()) { 167 menuManager.add(new Separator()); 168 } 169 170 if (aboutAction != null) { 171 menuManager.add(aboutAction); 172 } 173 if (preferencesAction != null) { 174 menuManager.add(preferencesAction); 175 } 176 if (quitAction != null) { 177 if (aboutAction != null || preferencesAction != null) { 178 menuManager.add(new Separator()); 179 } 180 menuManager.add(quitAction); 181 } 182 } 183 }; 184 } 185 186 enhancer.setupMenu(appName, display, callbacks); 187 return enhancer; 188 } 189 getEnhancer(IMenuBarCallback callbacks)190 private static IMenuBarEnhancer getEnhancer(IMenuBarCallback callbacks) { 191 IMenuBarEnhancer enhancer = null; 192 String p = SWT.getPlatform(); 193 String className = null; 194 if ("cocoa".equals(p)) { //$NON-NLS-1$ 195 className = "com.android.menubar.internal.MenuBarEnhancerCocoa"; //$NON-NLS-1$ 196 } 197 198 if (System.getenv("DEBUG_SWTMENUBAR") != null) { 199 callbacks.printError("DEBUG SwtMenuBar: SWT=%1$s, class=%2$s", p, className); 200 } 201 202 if (className != null) { 203 try { 204 Class<?> clazz = Class.forName(className); 205 enhancer = (IMenuBarEnhancer) clazz.newInstance(); 206 } catch (Exception e) { 207 // Log an error and fallback on the default implementation. 208 callbacks.printError( 209 "Failed to instantiate %1$s: %2$s", //$NON-NLS-1$ 210 className, 211 e.toString()); 212 } 213 } 214 return enhancer; 215 } 216 } 217