KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > carbon > CarbonUIEnhancer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.carbon;
12
13 import java.text.MessageFormat JavaDoc;
14 import java.util.MissingResourceException JavaDoc;
15 import java.util.ResourceBundle JavaDoc;
16
17 import org.eclipse.core.runtime.IProduct;
18 import org.eclipse.core.runtime.Platform;
19 import org.eclipse.jface.action.ActionContributionItem;
20 import org.eclipse.jface.action.IAction;
21 import org.eclipse.swt.internal.Callback;
22 import org.eclipse.swt.internal.carbon.HICommand;
23 import org.eclipse.swt.internal.carbon.OS;
24 import org.eclipse.swt.widgets.Display;
25 import org.eclipse.swt.widgets.Menu;
26 import org.eclipse.swt.widgets.MenuItem;
27 import org.eclipse.swt.widgets.Shell;
28 import org.eclipse.swt.widgets.Widget;
29 import org.eclipse.ui.IStartup;
30 import org.eclipse.ui.IWindowListener;
31 import org.eclipse.ui.IWorkbenchWindow;
32 import org.eclipse.ui.PlatformUI;
33 import org.eclipse.ui.internal.WorkbenchWindow;
34
35 /**
36  * The CarbonUIEnhancer provides the standard "About" and "Preference" menu items
37  * and links them to the corresponding workbench commands.
38  * This must be done in a MacOS X fragment because SWT doesn't provide an abstraction
39  * for the (MacOS X only) application menu and we have to use MacOS specific natives.
40  * The fragment is for the org.eclipse.ui plugin because we need access to the
41  * Workbench "About" and "Preference" actions.
42  */

43 public class CarbonUIEnhancer implements IStartup {
44
45     private static final int kHICommandPreferences = ('p' << 24) + ('r' << 16) + ('e' << 8) + 'f';
46     private static final int kHICommandAbout = ('a' << 24) + ('b' << 16) + ('o' << 8) + 'u';
47     private static final int kHICommandServices = ('s' << 24) + ('e' << 16) + ('r' << 8) + 'v';
48
49     private static final String JavaDoc RESOURCE_BUNDLE = "org.eclipse.ui.carbon.Messages"; //$NON-NLS-1$
50
private static final String JavaDoc TOOLBAR_BUTTON_TOGGLE_FLAGS = "toolbarButtonToggleFlags"; //$NON-NLS-1$
51

52     private String JavaDoc fAboutActionName;
53
54     /**
55      * Default constructor
56      */

57     public CarbonUIEnhancer() {
58         IProduct product = Platform.getProduct();
59         String JavaDoc productName = null;
60         if (product != null)
61             productName = product.getName();
62         
63         ResourceBundle JavaDoc resourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE);
64         try {
65             if (productName != null) {
66                 String JavaDoc format = resourceBundle.getString("AboutAction.format"); //$NON-NLS-1$
67
if (format != null)
68                     fAboutActionName= MessageFormat.format(format, new Object JavaDoc[] { productName } );
69             }
70             if (fAboutActionName == null)
71                 fAboutActionName = resourceBundle.getString("AboutAction.name"); //$NON-NLS-1$
72
} catch (MissingResourceException JavaDoc e) {
73         }
74         
75         if (fAboutActionName == null)
76             fAboutActionName = "About"; //$NON-NLS-1$
77
}
78
79     /* (non-Javadoc)
80      * @see org.eclipse.ui.IStartup#earlyStartup()
81      */

82     public void earlyStartup() {
83         final Display display = Display.getDefault();
84         display.syncExec(new Runnable JavaDoc() {
85             public void run() {
86                 hookApplicationMenu(display);
87                 hookToolbarButtonCallback();
88                 hookWorkbenchListener();
89                 // modify all shells opened on startup
90
IWorkbenchWindow[] windows = PlatformUI.getWorkbench()
91                         .getWorkbenchWindows();
92                 for (int i = 0; i < windows.length; i++) {
93                     modifyWindowShell(windows[i]);
94                 }
95             }
96         });
97     }
98
99     /**
100      * Hooks a listener that tweaks newly opened workbench window shells with
101      * the proper OS flags.
102      *
103      * @since 3.2
104      */

105     protected void hookWorkbenchListener() {
106         PlatformUI.getWorkbench().addWindowListener(new IWindowListener() {
107
108             public void windowActivated(IWorkbenchWindow window) {
109                 // no-op
110
}
111
112             public void windowDeactivated(IWorkbenchWindow window) {
113                 // no-op
114
}
115
116             public void windowClosed(IWorkbenchWindow window) {
117                 // no-op
118
}
119
120             public void windowOpened(IWorkbenchWindow window) {
121                 modifyWindowShell(window);
122             }});
123     }
124
125     /**
126      * Modify the given workbench window shell bits to show the toolbar toggle
127      * button.
128      *
129      * @param window
130      * the window to modify
131      * @since 3.2
132      */

133     protected void modifyWindowShell(IWorkbenchWindow window) {
134         // only add the button when either the coolbar or perspectivebar
135
// is initially visible. This is so that RCP apps can choose to use
136
// this fragment without fear that their explicitly invisble bars
137
// can't be shown.
138
boolean coolBarInitiallyVsible = ((WorkbenchWindow) window)
139                 .getCoolBarVisible();
140         boolean perspectiveBarInitiallyVsible = ((WorkbenchWindow) window)
141                 .getPerspectiveBarVisible();
142
143         if (coolBarInitiallyVsible || perspectiveBarInitiallyVsible) {
144             // modify the newly opened window with the correct OS X
145
// style bits such that it possesses the toolbar button
146
Shell shell = window.getShell();
147             boolean[] switchArray = new boolean[] { coolBarInitiallyVsible,
148                     perspectiveBarInitiallyVsible };
149             shell.setData(TOOLBAR_BUTTON_TOGGLE_FLAGS, switchArray);
150             int windowHandle = OS.GetControlOwner(shell.handle);
151             OS.ChangeWindowAttributes(windowHandle,
152                     OS.kWindowToolbarButtonAttribute, 0);
153         }
154     }
155     
156     /**
157      * Hook the window toolbar button to toggle the visibility of the coolbar
158      * and perspective bar.
159      *
160      * @since 3.2
161      */

162     protected void hookToolbarButtonCallback() {
163         Object JavaDoc target = new Object JavaDoc() {
164             int toolbarProc (int nextHandler, int theEvent, int userData) {
165                 int eventKind = OS.GetEventKind (theEvent);
166                 if (eventKind != OS.kEventWindowToolbarSwitchMode)
167                     return OS.eventNotHandledErr;
168                 
169                 int [] theWindow = new int [1];
170                 OS.GetEventParameter (theEvent, OS.kEventParamDirectObject, OS.typeWindowRef, null, 4, null, theWindow);
171                 
172                 int [] theRoot = new int [1];
173                 OS.GetRootControl (theWindow [0], theRoot);
174                 Widget widget = Display.getCurrent().findWidget(theRoot [0]);
175                 
176                 if (!(widget instanceof Shell)) {
177                     return OS.eventNotHandledErr;
178                 }
179                 Shell shell = (Shell) widget;
180                 IWorkbenchWindow[] windows = PlatformUI.getWorkbench()
181                         .getWorkbenchWindows();
182                 for (int i = 0; i < windows.length; i++) {
183                     if (windows[i].getShell() == shell) {
184                         WorkbenchWindow castedWindow = (WorkbenchWindow) windows[i];
185                         // get the switch flags that were set on the shell by
186
// the window listener
187
boolean[] switchFlags = (boolean[]) shell
188                                 .getData(TOOLBAR_BUTTON_TOGGLE_FLAGS);
189                         if (switchFlags == null)
190                             return OS.eventNotHandledErr;
191                         boolean coolbarVisible = castedWindow
192                                 .getCoolBarVisible();
193                         boolean perspectivebarVisible = castedWindow
194                                 .getPerspectiveBarVisible();
195                         // only toggle the visibility of the components that
196
// were on initially
197
if (switchFlags[0])
198                             castedWindow.setCoolBarVisible(!coolbarVisible);
199                         if (switchFlags[1])
200                             castedWindow
201                                     .setPerspectiveBarVisible(!perspectivebarVisible);
202                         shell.layout();
203                         return OS.noErr;
204                     }
205                 }
206                 return OS.eventNotHandledErr;
207             }
208
209         };
210         
211         final Callback commandCallback = new Callback(target, "toolbarProc", 3); //$NON-NLS-1$
212
int commandProc = commandCallback.getAddress();
213         if (commandProc == 0) {
214             commandCallback.dispose();
215             return; // give up
216
}
217         
218         int[] mask = new int[] { OS.kEventClassWindow, OS.kEventWindowToolbarSwitchMode };
219         OS.InstallEventHandler(OS.GetApplicationEventTarget(), commandProc,
220                 mask.length / 2, mask, 0, null);
221         
222     }
223
224     /**
225      * See Apple Technical Q&A 1079 (http://developer.apple.com/qa/qa2001/qa1079.html)
226      */

227     private void hookApplicationMenu(Display display) {
228
229         // Callback target
230
Object JavaDoc target = new Object JavaDoc() {
231             int commandProc(int nextHandler, int theEvent, int userData) {
232                 if (OS.GetEventKind(theEvent) == OS.kEventProcessCommand) {
233                     HICommand command = new HICommand();
234                     OS.GetEventParameter(theEvent, OS.kEventParamDirectObject,
235                             OS.typeHICommand, null, HICommand.sizeof, null, command);
236                     switch (command.commandID) {
237                     case kHICommandPreferences:
238                         return runAction("preferences"); //$NON-NLS-1$
239
case kHICommandAbout:
240                         return runAction("about"); //$NON-NLS-1$
241
default:
242                         break;
243                     }
244                 }
245                 return OS.eventNotHandledErr;
246             }
247         };
248
249         final Callback commandCallback = new Callback(target, "commandProc", 3); //$NON-NLS-1$
250
int commandProc = commandCallback.getAddress();
251         if (commandProc == 0) {
252             commandCallback.dispose();
253             return; // give up
254
}
255
256         // Install event handler for commands
257
int[] mask = new int[] { OS.kEventClassCommand, OS.kEventProcessCommand };
258         OS.InstallEventHandler(OS.GetApplicationEventTarget(), commandProc,
259                 mask.length / 2, mask, 0, null);
260
261         // create About Eclipse menu command
262
int[] outMenu = new int[1];
263         short[] outIndex = new short[1];
264         if (OS.GetIndMenuItemWithCommandID(0, kHICommandPreferences, 1, outMenu, outIndex) == OS.noErr
265                 && outMenu[0] != 0) {
266             int menu = outMenu[0];
267
268             int l = fAboutActionName.length();
269             char buffer[] = new char[l];
270             fAboutActionName.getChars(0, l, buffer, 0);
271             int str = OS.CFStringCreateWithCharacters(OS.kCFAllocatorDefault, buffer, l);
272             OS.InsertMenuItemTextWithCFString(menu, str, (short) 0, 0, kHICommandAbout);
273             OS.CFRelease(str);
274
275             // add separator between About & Preferences
276
OS.InsertMenuItemTextWithCFString(menu, 0, (short) 1, OS.kMenuItemAttrSeparator, 0);
277
278             // enable pref menu
279
OS.EnableMenuCommand(menu, kHICommandPreferences);
280
281             // disable services menu
282
OS.DisableMenuCommand(menu, kHICommandServices);
283         }
284
285         // schedule disposal of callback object
286
display.disposeExec(new Runnable JavaDoc() {
287             public void run() {
288                 commandCallback.dispose();
289             }
290         });
291     }
292
293     /**
294      * Locate an action with the given id in the current menubar and run it.
295      */

296     private int runAction(String JavaDoc actionId) {
297         IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
298         if (window != null) {
299             Shell shell = window.getShell();
300             Menu menubar = shell.getMenuBar();
301             if (menubar != null) {
302                 for (int i = 0; i < menubar.getItemCount(); i++) {
303                     MenuItem mi = menubar.getItem(i);
304                     Menu m = mi.getMenu();
305                     for (int j = 0; j < m.getItemCount(); j++) {
306                         MenuItem mi2 = m.getItem(j);
307                         Object JavaDoc o = mi2.getData();
308                         if (o instanceof ActionContributionItem) {
309                             ActionContributionItem aci = (ActionContributionItem) o;
310                             String JavaDoc id = aci.getId();
311                             if (id != null && id.equals(actionId)) {
312                                 IAction action = aci.getAction();
313                                 if (action != null && action.isEnabled()) {
314                                     action.run();
315                                     return OS.noErr;
316                                 }
317                             }
318                         }
319                     }
320                 }
321             }
322         }
323         return OS.eventNotHandledErr;
324     }
325 }
326
Popular Tags