Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/ui/internal/PluginActionBuilder.java


1   /*******************************************************************************
2    * Copyright (c) 2000, 2004 IBM Corporation and others.
3    * All rights reserved. This program and the accompanying materials 
4    * are made available under the terms of the Common Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/cpl-v10.html
7    * 
8    * Contributors:
9    *     IBM Corporation - initial API and implementation
10   *******************************************************************************/
11  package org.eclipse.ui.internal;
12  
13  
14  import java.util.ArrayList;
15  
16  import org.eclipse.core.runtime.IConfigurationElement;
17  import org.eclipse.core.runtime.Platform;
18  import org.eclipse.jface.action.AbstractGroupMarker;
19  import org.eclipse.jface.action.GroupMarker;
20  import org.eclipse.jface.action.IContributionItem;
21  import org.eclipse.jface.action.IContributionManager;
22  import org.eclipse.jface.action.IMenuManager;
23  import org.eclipse.jface.action.IToolBarManager;
24  import org.eclipse.jface.action.MenuManager;
25  import org.eclipse.jface.action.Separator;
26  import org.eclipse.ui.IWorkbenchActionConstants;
27  import org.eclipse.ui.PlatformUI;
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    public static final String TAG_MENU = "menu"; //$NON-NLS-1$
36    public static final String TAG_ACTION = "action"; //$NON-NLS-1$
37    public static final String TAG_SEPARATOR = "separator"; //$NON-NLS-1$
38    public static final String TAG_GROUP_MARKER = "groupMarker"; //$NON-NLS-1$
39    public static final String TAG_FILTER = "filter"; //$NON-NLS-1$
40    public static final String TAG_VISIBILITY = "visibility"; //$NON-NLS-1$
41    public static final String TAG_ENABLEMENT = "enablement"; //$NON-NLS-1$
42    public static final String TAG_SELECTION = "selection"; //$NON-NLS-1$
43  
44    public static final String ATT_TARGET_ID = "targetID"; //$NON-NLS-1$
45    public static final String ATT_ID = "id"; //$NON-NLS-1$
46    public static final String ATT_LABEL = "label"; //$NON-NLS-1$
47    public static final String ATT_ENABLES_FOR = "enablesFor"; //$NON-NLS-1$
48    public static final String ATT_NAME = "name"; //$NON-NLS-1$
49    public static final String ATT_PATH = "path"; //$NON-NLS-1$
50  
51    protected String targetID;
52    protected String targetContributionTag;
53    protected BasicContribution currentContribution;
54    protected ArrayList cache;
55  
56    /**
57     * The default constructor.
58     */
59    public PluginActionBuilder() {
60    }
61  
62    /**
63     * Contributes submenus and/or actions into the provided menu and tool bar
64     * managers.
65     */
66    public final void contribute(IMenuManager menu, IToolBarManager toolbar, boolean appendIfMissing) {
67      if (cache == null)
68        return;
69  
70      for (int i = 0; i < cache.size(); i++) {
71        BasicContribution contribution = (BasicContribution)cache.get(i);
72        contribution.contribute(menu, appendIfMissing, toolbar, appendIfMissing);
73      }
74    }
75    
76    /**
77     * This factory method returns a new ActionDescriptor for the
78     * configuration element.  It should be implemented by subclasses.
79     */
80    protected abstract ActionDescriptor createActionDescriptor(IConfigurationElement element);
81    
82    /**
83     * Factory method to create the helper contribution class that will hold
84     * onto the menus and actions contributed.
85     */
86    protected BasicContribution createContribution() {
87      return new BasicContribution();
88    }
89    
90    /**
91     * Returns the name of the part ID attribute that is expected
92     * in the target extension.
93     */
94    protected String getTargetID(IConfigurationElement element) {
95      String value = element.getAttribute(ATT_TARGET_ID);
96      return value != null ? value : "???"; //$NON-NLS-1$
97    }
98    
99    /**
100    * Reads the contributions from the registry for the provided workbench
101    * part and the provided extension point ID.
102    */
103   protected void readContributions(String id, String tag, String extensionPoint) {
104     cache = null;
105     currentContribution = null;
106     targetID = id;
107     targetContributionTag = tag;
108     readRegistry(Platform.getExtensionRegistry(), PlatformUI.PLUGIN_ID, extensionPoint);
109   }
110   
111   /**
112    * Implements abstract method to handle the provided XML element
113    * in the registry.
114    */
115   protected boolean readElement(IConfigurationElement element) {
116     String tag = element.getName();
117 
118     // Ignore all object contributions element as these
119     // are handled by the ObjectActionContributorReader.
120     if (tag.equals(ObjectActionContributorReader.TAG_OBJECT_CONTRIBUTION)) {
121       return true;
122     }
123 
124     // Found top level contribution element    
125     if (tag.equals(targetContributionTag)) {
126       if (targetID != null) {
127         // Ignore contributions not matching target id
128         String id = getTargetID(element);
129         if (id == null || !id.equals(targetID))
130           return true;
131       }
132       
133       // Read it's sub-elements
134       currentContribution = createContribution();
135       readElementChildren(element);
136       if (cache == null)
137         cache = new ArrayList(4);
138       cache.add(currentContribution);
139       currentContribution = null;
140       return true;
141     }
142     
143 
144     // Found menu contribution sub-element    
145     if (tag.equals(TAG_MENU)) {
146       currentContribution.addMenu(element);
147       return true;
148     }
149     
150     // Found action contribution sub-element
151     if (tag.equals(TAG_ACTION)) {
152       currentContribution.addAction(createActionDescriptor(element));
153       return true;
154     }
155     
156     return false;
157   }
158 
159   
160   /**
161    * Helper class to collect the menus and actions defined within a
162    * contribution element.
163    */
164   protected static class BasicContribution {
165     protected ArrayList menus;
166     protected ArrayList actions;
167     
168     public void addMenu(IConfigurationElement element) {
169       if (menus == null)
170         menus = new ArrayList(1);
171       menus.add(element);
172     }
173     
174     public void addAction(ActionDescriptor desc) {
175       if (actions == null)
176         actions = new ArrayList(3);
177       actions.add(desc);
178     }
179 
180     /**
181      * Contributes submenus and/or actions into the provided menu and tool bar
182      * managers.
183      */
184     public void contribute(IMenuManager menu, boolean menuAppendIfMissing, IToolBarManager toolbar, boolean toolAppendIfMissing) {
185       if (menus != null && menu != null) {
186         for (int i = 0; i < menus.size(); i++) {
187           IConfigurationElement menuElement = (IConfigurationElement) menus.get(i);
188           contributeMenu(menuElement, menu, menuAppendIfMissing);
189         }
190       }
191       
192       if (actions != null) {
193         for (int i = 0; i < actions.size(); i++) {
194           ActionDescriptor ad = (ActionDescriptor) actions.get(i);
195           if (menu != null)
196             contributeMenuAction(ad, menu, menuAppendIfMissing);
197           if (toolbar != null)
198             contributeToolbarAction(ad, toolbar, toolAppendIfMissing);
199         }
200       }
201     }
202   
203     /**
204      * Creates a menu from the information in the menu configuration element and
205      * adds it into the provided menu manager. If 'appendIfMissing' is true, and
206      * menu path slot is not found, it will be created and menu will be added
207      * into it. Otherwise, add operation will fail.
208      */
209     protected void contributeMenu(IConfigurationElement menuElement, IMenuManager mng, boolean appendIfMissing) {
210       // Get config data.
211       String id = menuElement.getAttribute(ATT_ID);
212       String label = menuElement.getAttribute(ATT_LABEL);
213       String path = menuElement.getAttribute(ATT_PATH);
214       if (label == null) {
215         WorkbenchPlugin.log("Invalid Menu Extension (label == null): " + id); //$NON-NLS-1$
216         return;
217       }
218 
219       // Calculate menu path and group.
220       String group = null;
221       if (path != null) {
222         int loc = path.lastIndexOf('/');
223         if (loc != -1) {
224           group = path.substring(loc + 1);
225           path = path.substring(0, loc);
226         } else {
227           // assume that path represents a slot
228           // so actual path portion should be null
229           group = path;
230           path = null;
231         }
232       }
233 
234       // Find parent menu.
235       IMenuManager parent = mng;
236       if (path != null) {
237         parent = mng.findMenuUsingPath(path);
238         if (parent == null) {
239           WorkbenchPlugin.log("Invalid Menu Extension (Path is invalid): " + id); //$NON-NLS-1$
240           return;
241         }
242       }
243 
244       // Find reference group.
245       if (group == null)
246         group = IWorkbenchActionConstants.MB_ADDITIONS;
247       IContributionItem sep = parent.find(group);
248       if (sep == null) {
249         if (appendIfMissing)
250           addGroup(parent, group);
251         else {
252           WorkbenchPlugin.log("Invalid Menu Extension (Group is invalid): " + id); //$NON-NLS-1$
253           return;
254         }
255       }
256 
257       // If the menu does not exist create it.
258       IMenuManager newMenu = parent.findMenuUsingPath(id);
259       if (newMenu == null)
260         newMenu = new MenuManager(label, id);
261 
262       // Add the menu
263       try {
264         insertAfter(parent, group, newMenu);
265       } catch (IllegalArgumentException e) {
266         WorkbenchPlugin.log("Invalid Menu Extension (Group is missing): " + id); //$NON-NLS-1$
267       }
268 
269       // Get the menu again as it may be wrapped, otherwise adding
270       // the separators and group markers below will not be wrapped
271       // properly if the menu was just created.
272       newMenu = parent.findMenuUsingPath(id);
273       if (newMenu == null)
274         WorkbenchPlugin.log("Could not find new menu: " + id); //$NON-NLS-1$
275 
276       // Create separators.
277       IConfigurationElement[] children = menuElement.getChildren();
278       for (int i = 0; i < children.length; i++) {
279         String childName = children[i].getName();
280         if (childName.equals(TAG_SEPARATOR)) {
281           contributeSeparator(newMenu, children[i]);
282         } else if (childName.equals(TAG_GROUP_MARKER)) {
283           contributeGroupMarker(newMenu, children[i]);
284         }
285       }
286     }
287   
288     /**
289      * Contributes action from action descriptor into the provided menu manager.
290      */
291     protected void contributeMenuAction(ActionDescriptor ad, IMenuManager menu, boolean appendIfMissing) {
292       // Get config data.
293       String mpath = ad.getMenuPath();
294       String mgroup = ad.getMenuGroup();
295       if (mpath == null && mgroup == null)
296         return;
297 
298       // Find parent menu.
299       IMenuManager parent = menu;
300       if (mpath != null) {
301         parent = parent.findMenuUsingPath(mpath);
302         if (parent == null) {
303           WorkbenchPlugin.log("Invalid Menu Extension (Path is invalid): " + ad.getId()); //$NON-NLS-1$
304           return;
305         }
306       }
307 
308       // Find reference group.
309       if (mgroup == null)
310         mgroup = IWorkbenchActionConstants.MB_ADDITIONS;
311       IContributionItem sep = parent.find(mgroup);
312       if (sep == null) {
313         if (appendIfMissing)
314           addGroup(parent, mgroup);
315         else {
316           WorkbenchPlugin.log("Invalid Menu Extension (Group is invalid): " + ad.getId()); //$NON-NLS-1$
317           return;
318         }
319       }
320 
321       // Add action.
322       try {
323         insertAfter(parent, mgroup, ad.getAction());
324       } catch (IllegalArgumentException e) {
325         WorkbenchPlugin.log("Invalid Menu Extension (Group is missing): " + ad.getId()); //$NON-NLS-1$
326       }
327     }
328   
329     /**
330      * Creates a named menu separator from the information in the configuration element.
331      * If the separator already exists do not create a second.
332      */
333     protected void contributeSeparator(IMenuManager menu, IConfigurationElement element) {
334       String id = element.getAttribute(ATT_NAME);
335       if (id == null || id.length() <= 0)
336         return;
337       IContributionItem sep = menu.find(id);
338       if (sep != null)
339         return;
340       insertMenuGroup(menu, new Separator(id));
341     }
342   
343     /**
344      * Creates a named menu group marker from the information in the configuration element.
345      * If the marker already exists do not create a second.
346      */
347     protected void contributeGroupMarker(IMenuManager menu, IConfigurationElement element) {
348       String id = element.getAttribute(ATT_NAME);
349       if (id == null || id.length() <= 0)
350         return;
351       IContributionItem marker = menu.find(id);
352       if (marker != null)
353         return;
354       insertMenuGroup(menu, new GroupMarker(id));
355     }
356   
357     /**
358      * Contributes action from the action descriptor into the provided tool bar manager.
359      */
360     protected void contributeToolbarAction(ActionDescriptor ad, IToolBarManager toolbar, boolean appendIfMissing) {
361       // Get config data.
362       String tId = ad.getToolbarId();
363       String tgroup = ad.getToolbarGroupId();
364       if (tId == null && tgroup == null)
365         return;
366 
367       // Find reference group.
368       if (tgroup == null)
369         tgroup = IWorkbenchActionConstants.MB_ADDITIONS;
370       IContributionItem sep = null;
371       sep = toolbar.find(tgroup);
372       if (sep == null) {
373         if (appendIfMissing) {
374           addGroup(toolbar, tgroup);
375         } else {
376           WorkbenchPlugin.log("Invalid Toolbar Extension (Group is invalid): " + ad.getId()); //$NON-NLS-1$
377           return;
378         }
379       }
380       // Add action to tool bar.
381       try {
382         insertAfter(toolbar, tgroup, ad.getAction());
383       } catch (IllegalArgumentException e) {
384         WorkbenchPlugin.log("Invalid Toolbar Extension (Group is missing): " + ad.getId()); //$NON-NLS-1$
385       }
386     }
387   
388     /**
389      * Inserts the separator or group marker into the menu. Subclasses may override.
390      */
391     protected void insertMenuGroup(IMenuManager menu, AbstractGroupMarker marker) {
392       menu.add(marker);
393     }
394   
395     /**
396      * Inserts an action after another named contribution item.
397      * Subclasses may override.
398      */
399     protected void insertAfter(IContributionManager mgr, String refId, PluginAction action) {
400       insertAfter(mgr, refId, new PluginActionContributionItem(action));
401     }
402   
403     /**
404      * Inserts a contribution item after another named contribution item.
405      * Subclasses may override.
406      */
407     protected void insertAfter(IContributionManager mgr, String refId, IContributionItem item) {
408       mgr.insertAfter(refId, item);
409     }
410   
411     /**
412      * Adds a group to a contribution manager.
413      * Subclasses may override.
414      */
415     protected void addGroup(IContributionManager mgr, String name) {
416       mgr.add(new Separator(name));
417     }
418   }
419 }