KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > PluginActionBuilder


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.internal;
12
13 import java.util.ArrayList JavaDoc;
14
15 import org.eclipse.core.runtime.IConfigurationElement;
16 import org.eclipse.core.runtime.Platform;
17 import org.eclipse.jface.action.AbstractGroupMarker;
18 import org.eclipse.jface.action.GroupMarker;
19 import org.eclipse.jface.action.IContributionItem;
20 import org.eclipse.jface.action.IContributionManager;
21 import org.eclipse.jface.action.IMenuManager;
22 import org.eclipse.jface.action.IToolBarManager;
23 import org.eclipse.jface.action.MenuManager;
24 import org.eclipse.jface.action.Separator;
25 import org.eclipse.ui.IWorkbenchActionConstants;
26 import org.eclipse.ui.PlatformUI;
27 import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
28 import org.eclipse.ui.internal.registry.RegistryReader;
29
30 /**
31  * This class contains shared functionality for reading action contributions
32  * from plugins into workbench parts (both editors and views).
33  */

34 public abstract class PluginActionBuilder extends RegistryReader {
35     protected String JavaDoc targetID;
36
37     protected String JavaDoc targetContributionTag;
38
39     protected BasicContribution currentContribution;
40
41     protected ArrayList JavaDoc cache;
42
43     /**
44      * The default constructor.
45      */

46     public PluginActionBuilder() {
47     }
48
49     /**
50      * Contributes submenus and/or actions into the provided menu and tool bar
51      * managers.
52      *
53      * @param menu the menu to contribute to
54      * @param toolbar the toolbar to contribute to
55      * @param appendIfMissing append containers if missing
56      */

57     public final void contribute(IMenuManager menu, IToolBarManager toolbar,
58             boolean appendIfMissing) {
59         if (cache == null) {
60             return;
61         }
62
63         for (int i = 0; i < cache.size(); i++) {
64             BasicContribution contribution = (BasicContribution) cache.get(i);
65             contribution.contribute(menu, appendIfMissing, toolbar,
66                     appendIfMissing);
67         }
68     }
69
70     /**
71      * This factory method returns a new ActionDescriptor for the
72      * configuration element. It should be implemented by subclasses.
73      */

74     protected abstract ActionDescriptor createActionDescriptor(
75             IConfigurationElement element);
76
77     /**
78      * Factory method to create the helper contribution class that will hold
79      * onto the menus and actions contributed.
80      */

81     protected BasicContribution createContribution() {
82         return new BasicContribution();
83     }
84
85     /**
86      * Returns the name of the part ID attribute that is expected
87      * in the target extension.
88      */

89     protected String JavaDoc getTargetID(IConfigurationElement element) {
90         String JavaDoc value = element.getAttribute(IWorkbenchRegistryConstants.ATT_TARGET_ID);
91         return value != null ? value : "???"; //$NON-NLS-1$
92
}
93     
94     /**
95      * Returns the id of this contributions.
96      */

97     protected String JavaDoc getID(IConfigurationElement element) {
98         String JavaDoc value = element.getAttribute(IWorkbenchRegistryConstants.ATT_ID);
99         return value != null ? value : "???"; //$NON-NLS-1$
100
}
101
102     /**
103      * Reads the contributions from the registry for the provided workbench
104      * part and the provided extension point ID.
105      */

106     protected void readContributions(String JavaDoc id, String JavaDoc tag,
107             String JavaDoc extensionPoint) {
108         cache = null;
109         currentContribution = null;
110         targetID = id;
111         targetContributionTag = tag;
112         readRegistry(Platform.getExtensionRegistry(), PlatformUI.PLUGIN_ID,
113                 extensionPoint);
114     }
115
116     /**
117      * Implements abstract method to handle the provided XML element
118      * in the registry.
119      */

120     protected boolean readElement(IConfigurationElement element) {
121         String JavaDoc tag = element.getName();
122
123         // Ignore all object contributions element as these
124
// are handled by the ObjectActionContributorReader.
125
if (tag.equals(IWorkbenchRegistryConstants.TAG_OBJECT_CONTRIBUTION)) {
126             return true;
127         }
128
129         // Found top level contribution element
130
if (tag.equals(targetContributionTag)) {
131             if (targetID != null) {
132                 // Ignore contributions not matching target id
133
String JavaDoc id = getTargetID(element);
134                 if (id == null || !id.equals(targetID)) {
135                     return true;
136                 }
137             }
138
139             // Read its sub-elements
140
currentContribution = createContribution();
141             readElementChildren(element);
142             if (cache == null) {
143                 cache = new ArrayList JavaDoc(4);
144             }
145             cache.add(currentContribution);
146             currentContribution = null;
147             return true;
148         }
149
150         // Found menu contribution sub-element
151
if (tag.equals(IWorkbenchRegistryConstants.TAG_MENU)) {
152             currentContribution.addMenu(element);
153             return true;
154         }
155
156         // Found action contribution sub-element
157
if (tag.equals(IWorkbenchRegistryConstants.TAG_ACTION)) {
158             currentContribution.addAction(createActionDescriptor(element));
159             return true;
160         }
161
162         return false;
163     }
164
165     /**
166      * Helper class to collect the menus and actions defined within a
167      * contribution element.
168      */

169     protected static class BasicContribution {
170         protected ArrayList JavaDoc menus;
171
172         protected ArrayList JavaDoc actions;
173
174         /**
175          * Add a menu.
176          *
177          * @param element the element to base the menu on
178          */

179         public void addMenu(IConfigurationElement element) {
180             if (menus == null) {
181                 menus = new ArrayList JavaDoc(1);
182             }
183             menus.add(element);
184         }
185
186         /**
187          * Add an action.
188          *
189          * @param desc the descriptor
190          */

191         public void addAction(ActionDescriptor desc) {
192             if (actions == null) {
193                 actions = new ArrayList JavaDoc(3);
194             }
195             actions.add(desc);
196         }
197
198         /**
199          * Contributes submenus and/or actions into the provided menu and tool bar
200          * managers.
201          *
202          * The elements added are filtered based on activity enablement.
203          * @param menu the menu to contribute to
204          * @param menuAppendIfMissing whether to append missing groups to menus
205          * @param toolbar the toolbar to contribute to
206          * @param toolAppendIfMissing whether to append missing groups to toolbars
207          */

208         public void contribute(IMenuManager menu, boolean menuAppendIfMissing,
209                 IToolBarManager toolbar, boolean toolAppendIfMissing) {
210             if (menus != null && menu != null) {
211                 for (int i = 0; i < menus.size(); i++) {
212                     IConfigurationElement menuElement = (IConfigurationElement) menus
213                             .get(i);
214                     contributeMenu(menuElement, menu, menuAppendIfMissing);
215                 }
216             }
217
218             if (actions != null) {
219                 for (int i = 0; i < actions.size(); i++) {
220                     ActionDescriptor ad = (ActionDescriptor) actions.get(i);
221                     if (menu != null) {
222                         contributeMenuAction(ad, menu, menuAppendIfMissing);
223                     }
224                     if (toolbar != null) {
225                         contributeToolbarAction(ad, toolbar,
226                                 toolAppendIfMissing);
227                     }
228                 }
229             }
230         }
231
232         /**
233          * Creates a menu from the information in the menu configuration element and
234          * adds it into the provided menu manager. If 'appendIfMissing' is true, and
235          * menu path slot is not found, it will be created and menu will be added
236          * into it. Otherwise, add operation will fail.
237          */

238         protected void contributeMenu(IConfigurationElement menuElement,
239                 IMenuManager mng, boolean appendIfMissing) {
240             // Get config data.
241
String JavaDoc id = menuElement.getAttribute(IWorkbenchRegistryConstants.ATT_ID);
242             String JavaDoc label = menuElement.getAttribute(IWorkbenchRegistryConstants.ATT_LABEL);
243             String JavaDoc path = menuElement.getAttribute(IWorkbenchRegistryConstants.ATT_PATH);
244             if (label == null) {
245                 WorkbenchPlugin.log("Plugin \'" //$NON-NLS-1$
246
+ menuElement.getContributor().getName()
247                         + "\' invalid Menu Extension (label == null): " + id); //$NON-NLS-1$
248
return;
249             }
250
251             // Calculate menu path and group.
252
String JavaDoc group = null;
253             if (path != null) {
254                 int loc = path.lastIndexOf('/');
255                 if (loc != -1) {
256                     group = path.substring(loc + 1);
257                     path = path.substring(0, loc);
258                 } else {
259                     // assume that path represents a slot
260
// so actual path portion should be null
261
group = path;
262                     path = null;
263                 }
264             }
265
266             // Find parent menu.
267
IMenuManager parent = mng;
268             if (path != null) {
269                 parent = mng.findMenuUsingPath(path);
270                 if (parent == null) {
271                     ideLog("Plugin \'" //$NON-NLS-1$
272
+ menuElement.getContributor().getName()
273                                     + "\' invalid Menu Extension (Path \'" //$NON-NLS-1$
274
+ path + "\' is invalid): " + id); //$NON-NLS-1$
275
return;
276                 }
277             }
278
279             // Find reference group.
280
if (group == null) {
281                 group = IWorkbenchActionConstants.MB_ADDITIONS;
282             }
283             IContributionItem sep = parent.find(group);
284             if (sep == null) {
285                 if (appendIfMissing) {
286                     addGroup(parent, group);
287                 } else {
288                     WorkbenchPlugin
289                             .log("Plugin \'" //$NON-NLS-1$
290
+ menuElement.getContributor().getName()
291                                     + "\' invalid Menu Extension (Group \'" //$NON-NLS-1$
292
+ group + "\' is invalid): " + id); //$NON-NLS-1$
293
return;
294                 }
295             }
296
297             // If the menu does not exist create it.
298
IMenuManager newMenu = parent.findMenuUsingPath(id);
299             if (newMenu == null) {
300                 newMenu = new MenuManager(label, id);
301             }
302
303             // Add the menu
304
try {
305                 insertAfter(parent, group, newMenu);
306             } catch (IllegalArgumentException JavaDoc e) {
307                 WorkbenchPlugin
308                         .log("Plugin \'" //$NON-NLS-1$
309
+ menuElement.getContributor().getName()
310                                 + "\' invalid Menu Extension (Group \'" //$NON-NLS-1$
311
+ group + "\' is missing): " + id); //$NON-NLS-1$
312
}
313
314             // Get the menu again as it may be wrapped, otherwise adding
315
// the separators and group markers below will not be wrapped
316
// properly if the menu was just created.
317
newMenu = parent.findMenuUsingPath(id);
318             if (newMenu == null) {
319                 WorkbenchPlugin.log("Could not find new menu: " + id); //$NON-NLS-1$
320
}
321
322             // Create separators.
323
IConfigurationElement[] children = menuElement.getChildren();
324             for (int i = 0; i < children.length; i++) {
325                 String JavaDoc childName = children[i].getName();
326                 if (childName.equals(IWorkbenchRegistryConstants.TAG_SEPARATOR)) {
327                     contributeSeparator(newMenu, children[i]);
328                 } else if (childName.equals(IWorkbenchRegistryConstants.TAG_GROUP_MARKER)) {
329                     contributeGroupMarker(newMenu, children[i]);
330                 }
331             }
332         }
333
334         /**
335          * Contributes action from action descriptor into the provided menu manager.
336          */

337         protected void contributeMenuAction(ActionDescriptor ad,
338                 IMenuManager menu, boolean appendIfMissing) {
339             // Get config data.
340
String JavaDoc mpath = ad.getMenuPath();
341             String JavaDoc mgroup = ad.getMenuGroup();
342             if (mpath == null && mgroup == null) {
343                 return;
344             }
345             // Find parent menu.
346
IMenuManager parent = menu;
347             if (mpath != null) {
348                 parent = parent.findMenuUsingPath(mpath);
349                 if (parent == null) {
350                     ideLog("Plug-in '" + ad.getPluginId() + "' contributed an invalid Menu Extension (Path: '" + mpath + "' is invalid): " + ad.getId()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
351
return;
352                 }
353             }
354
355             // Find reference group.
356
if (mgroup == null) {
357                 mgroup = IWorkbenchActionConstants.MB_ADDITIONS;
358             }
359             IContributionItem sep = parent.find(mgroup);
360             if (sep == null) {
361                 if (appendIfMissing) {
362                     addGroup(parent, mgroup);
363                 } else {
364                     WorkbenchPlugin
365                             .log("Plug-in '" + ad.getPluginId() + "' contributed an invalid Menu Extension (Group: '" + mgroup + "' is invalid): " + ad.getId()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
366
return;
367                 }
368             }
369
370             // Add action.
371
try {
372                 insertAfter(parent, mgroup, ad.getAction());
373             } catch (IllegalArgumentException JavaDoc e) {
374                 WorkbenchPlugin
375                         .log("Plug-in '" + ad.getPluginId() + "' contributed an invalid Menu Extension (Group: '" + mgroup + "' is missing): " + ad.getId()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
376
}
377         }
378
379         /**
380          * Creates a named menu separator from the information in the configuration element.
381          * If the separator already exists do not create a second.
382          */

383         protected void contributeSeparator(IMenuManager menu,
384                 IConfigurationElement element) {
385             String JavaDoc id = element.getAttribute(IWorkbenchRegistryConstants.ATT_NAME);
386             if (id == null || id.length() <= 0) {
387                 return;
388             }
389             IContributionItem sep = menu.find(id);
390             if (sep != null) {
391                 return;
392             }
393             insertMenuGroup(menu, new Separator(id));
394         }
395
396         /**
397          * Creates a named menu group marker from the information in the configuration element.
398          * If the marker already exists do not create a second.
399          */

400         protected void contributeGroupMarker(IMenuManager menu,
401                 IConfigurationElement element) {
402             String JavaDoc id = element.getAttribute(IWorkbenchRegistryConstants.ATT_NAME);
403             if (id == null || id.length() <= 0) {
404                 return;
405             }
406             IContributionItem marker = menu.find(id);
407             if (marker != null) {
408                 return;
409             }
410             insertMenuGroup(menu, new GroupMarker(id));
411         }
412
413         /**
414          * Contributes action from the action descriptor into the provided tool bar manager.
415          */

416         protected void contributeToolbarAction(ActionDescriptor ad,
417                 IToolBarManager toolbar, boolean appendIfMissing) {
418             // Get config data.
419
String JavaDoc tId = ad.getToolbarId();
420             String JavaDoc tgroup = ad.getToolbarGroupId();
421             if (tId == null && tgroup == null) {
422                 return;
423             }
424
425             // Find reference group.
426
if (tgroup == null) {
427                 tgroup = IWorkbenchActionConstants.MB_ADDITIONS;
428             }
429             IContributionItem sep = null;
430             sep = toolbar.find(tgroup);
431             if (sep == null) {
432                 if (appendIfMissing) {
433                     addGroup(toolbar, tgroup);
434                 } else {
435                     WorkbenchPlugin
436                             .log("Plug-in '" + ad.getPluginId() //$NON-NLS-1$
437
+ "' invalid Toolbar Extension (Group \'" //$NON-NLS-1$
438
+ tgroup + "\' is invalid): " + ad.getId()); //$NON-NLS-1$
439
return;
440                 }
441             }
442             // Add action to tool bar.
443
try {
444                 insertAfter(toolbar, tgroup, ad.getAction());
445             } catch (IllegalArgumentException JavaDoc e) {
446                 WorkbenchPlugin
447                         .log("Plug-in '" + ad.getPluginId() //$NON-NLS-1$
448
+ "' invalid Toolbar Extension (Group \'" //$NON-NLS-1$
449
+ tgroup + "\' is missing): " + ad.getId()); //$NON-NLS-1$
450
}
451         }
452
453         /**
454          * Inserts the separator or group marker into the menu. Subclasses may override.
455          */

456         protected void insertMenuGroup(IMenuManager menu,
457                 AbstractGroupMarker marker) {
458             menu.add(marker);
459         }
460
461         /**
462          * Inserts an action after another named contribution item.
463          * Subclasses may override.
464          */

465         protected void insertAfter(IContributionManager mgr, String JavaDoc refId,
466                 PluginAction action) {
467             insertAfter(mgr, refId, new PluginActionContributionItem(action));
468         }
469
470         /**
471          * Inserts a contribution item after another named contribution item.
472          * Subclasses may override.
473          */

474         protected void insertAfter(IContributionManager mgr, String JavaDoc refId,
475                 IContributionItem item) {
476             mgr.insertAfter(refId, item);
477         }
478
479         /**
480          * Adds a group to a contribution manager.
481          * Subclasses may override.
482          */

483         protected void addGroup(IContributionManager mgr, String JavaDoc name) {
484             mgr.add(new Separator(name));
485         }
486
487         /**
488          * Disposes this contribution.
489          *
490          * @since 3.1
491          */

492         public void dispose() {
493             // do nothing
494
}
495         
496         /**
497          * Disposes the actions.
498          *
499          * @since 3.1
500          */

501         protected void disposeActions() {
502             if (actions != null) {
503                 for (int i = 0; i < actions.size(); i++) {
504                     PluginAction proxy = ((ActionDescriptor) actions.get(i))
505                             .getAction();
506                     proxy.dispose();
507                 }
508                 actions = null;
509             }
510         }
511     }
512     
513     private static boolean allowIdeLogging = false;
514     
515     /**
516      * If set to <code>false</code>, some of the logs that can be caused by
517      * use IDE plugins from an RCP app will be ignored.
518      *
519      * @param b
520      * Log the errors or not.
521      * @since 3.3
522      */

523     public static void setAllowIdeLogging(boolean b) {
524         allowIdeLogging = b;
525     }
526     
527     /**
528      * These are log messages that should be ignored by RCP apps when using the
529      * IDE plugins.
530      *
531      * @param msg
532      * @since 3.3
533      */

534     private static void ideLog(String JavaDoc msg) {
535         if (allowIdeLogging) {
536             WorkbenchPlugin.log(msg);
537         }
538     }
539 }
540
Popular Tags