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

Quick Search    Search Deep

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


1   /*******************************************************************************
2    * Copyright (c) 2000, 2003 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  import java.util.ArrayList;
14  import java.util.List;
15  
16  import org.eclipse.core.runtime.IAdaptable;
17  import org.eclipse.jface.action.IMenuManager;
18  import org.eclipse.jface.viewers.ISelection;
19  import org.eclipse.jface.viewers.ISelectionProvider;
20  import org.eclipse.jface.viewers.IStructuredSelection;
21  import org.eclipse.ui.IWorkbenchPart;
22  
23  /**
24   * This manager is used to populate a popup menu manager with actions
25   * for a given type.
26   */
27  public class ObjectActionContributorManager extends ObjectContributorManager {
28    private static ObjectActionContributorManager sharedInstance;
29    
30    /**
31     * PopupMenuManager constructor.
32     */
33    public ObjectActionContributorManager() {
34      loadContributors();
35    }
36    
37    /**
38     * Returns the class search order starting with <code>extensibleClass</code>.
39     * The search order is defined in this class' comment.
40     */
41    private List computeCombinedOrder(Class inputClass) {
42      List result = new ArrayList(4);
43      Class clazz = inputClass;
44      while (clazz != null) {
45        // add the class
46        result.add(clazz);
47        // add all the interfaces it implements
48        Class[] interfaces = clazz.getInterfaces();
49        for (int i = 0; i < interfaces.length; i++) {
50          result.add(interfaces[i]);
51        }
52        // get the superclass
53        clazz = clazz.getSuperclass();
54      }
55      return result;
56    }
57    
58    /**
59     * Contributes submenus and/or actions applicable to the selection in the
60     * provided viewer into the provided popup menu.
61     */
62    public boolean contributeObjectActions(IWorkbenchPart part, IMenuManager popupMenu, ISelectionProvider selProv) {
63      // Get a selection.  
64      ISelection selection = selProv.getSelection();
65      if (selection == null)
66        return false;
67  
68      // Convert the selection into an element vector.
69      // According to the dictionary, a selection is "one that
70      // is selected", or "a collection of selected things".  
71      // In reflection of this, we deal with one or a collection.
72      List elements = null;
73      if (selection instanceof IStructuredSelection) {
74        elements = ((IStructuredSelection) selection).toList();
75      } else {
76        elements = new ArrayList(1);
77        elements.add(selection);
78      }
79  
80      // Calculate the common class and interfaces.
81      List commonClasses = getCommonClasses(elements);
82      if (commonClasses == null || commonClasses.isEmpty())
83        return false;
84  
85      // Get the resource class. It will be null if any of the
86      // elements are resources themselves or do not adapt to
87      // IResource.
88      Class resourceClass = getCommonResourceClass(elements);
89  
90      // Get the contributors.  
91      // If there is a resource class add it in
92      List contributors = null;
93      if (resourceClass == null) {
94        if (commonClasses.size() == 1) {
95          contributors = getContributors((Class)commonClasses.get(0));
96        } else {
97          contributors = new ArrayList();
98          for (int i = 0; i < commonClasses.size(); i++) {
99            List results = getContributors((Class)commonClasses.get(i));
100           if (results != null)
101             contributors.addAll(results);
102         }
103       }
104     } else {
105       contributors = getContributors((Class)commonClasses.get(0), resourceClass);
106       for (int i = 1; i < commonClasses.size(); i++) {
107         List results = getContributors((Class)commonClasses.get(i));
108         if (results != null)
109           contributors.addAll(results);
110       }
111     }
112     
113     if (contributors == null || contributors.isEmpty())
114       return false;
115 
116     // Do the contributions.  Add menus first, then actions
117     boolean actualContributions = false;
118     ArrayList overrides = new ArrayList(4);
119     for (int i = 0; i < contributors.size(); i++) {
120       IObjectActionContributor contributor = (IObjectActionContributor) contributors.get(i);
121       if (!isApplicableTo(elements, contributor))
122         continue;
123       if (contributor.contributeObjectMenus(popupMenu, selProv))
124         actualContributions = true;
125       contributor.contributeObjectActionIdOverrides(overrides);
126     }
127     for (int i = 0; i < contributors.size(); i++) {
128       IObjectActionContributor contributor = (IObjectActionContributor) contributors.get(i);
129       if (!isApplicableTo(elements, contributor))
130         continue;
131       if (contributor.contributeObjectActions(part, popupMenu, selProv, overrides))
132         actualContributions = true;
133     }
134     return actualContributions;
135   }
136 
137   /**
138    * Returns the common denominator class for
139    * two input classes.
140    */
141   private Class getCommonClass(Class class1, Class class2) {
142     List list1 = computeCombinedOrder(class1);
143     List list2 = computeCombinedOrder(class2);
144     for (int i = 0; i < list1.size(); i++) {
145       for (int j = 0; j < list2.size(); j++) {
146         Class candidate1 = (Class) list1.get(i);
147         Class candidate2 = (Class) list2.get(j);
148         if (candidate1.equals(candidate2))
149           return candidate1;
150       }
151     }
152     // no common class
153     return null;
154   }
155   
156   /**
157    * Returns the common denominator class for the given
158    * collection of objects.
159    */
160   private Class getCommonClass(List objects) {
161     if (objects == null || objects.size() == 0)
162       return null;
163     Class commonClass = objects.get(0).getClass();
164     // try easy
165     if (objects.size() == 1)
166       return commonClass;
167     // try harder
168 
169     for (int i = 1; i < objects.size(); i++) {
170       Object object = objects.get(i);
171       Class newClass = object.getClass();
172       // try the short cut
173       if (newClass.equals(commonClass))
174         continue;
175       // compute common class
176       commonClass = getCommonClass(commonClass, newClass);
177       // give up
178       if (commonClass == null)
179         return null;
180     }
181     return commonClass;
182   }
183 
184   /**
185    * Returns the common denominator class and interfaces for the given
186    * collection of objects.
187    */
188   private List getCommonClasses(List objects) {
189     if (objects == null || objects.size() == 0)
190       return null;
191 
192     // Quickly handle the easy case...
193     if (objects.size() == 1) {
194       List results = new ArrayList(1);
195       results.add(objects.get(0).getClass());
196       return results;
197     }
198 
199     // Compute all the super classes for the first element
200     // and then all of the interfaces for the first element
201     // and it's super classes.
202     List classes = computeClassOrder(objects.get(0).getClass());
203     List interfaces = computeInterfaceOrder(classes);
204     boolean classesEmpty = classes.isEmpty();
205     boolean interfacesEmpty = interfaces.isEmpty();
206     
207     for (int i = 1; i < objects.size(); i++) {
208       // Compute all the super classes for the current element
209       List results = computeClassOrder(objects.get(i).getClass());
210       if (!classesEmpty) {
211         classesEmpty = true;
212         if (results.isEmpty()) {
213           // When no super classes, then it is obvious there
214           // are no common super classes with the first element
215           // so clear its list.
216           classes.clear();
217         } else {
218           // Remove any super classes of the first element that 
219           // are not in the current element's super classes list.
220           for (int j = 0; j < classes.size(); j++) {
221             if (classes.get(j) != null) {
222               classesEmpty = false;
223               if (!results.contains(classes.get(j))) {
224                 classes.set(j, null);              
225               }
226             }
227           }
228         }
229       }
230       
231       if (!interfacesEmpty) {
232         // Compute all the interfaces for the current element
233         // and all of its super classes.
234         results = computeInterfaceOrder(results);
235         interfacesEmpty = true;
236         if (results.isEmpty()) {
237           // When no interfaces, the it is obvious there are
238           // no common interfaces between this current element
239           // and the first element, so clear its list.
240           interfaces.clear();
241         } else {
242           // Remove any interfaces of the first element that
243           // are not in the current element's interfaces list.
244           for (int j = 0; j < interfaces.size(); j++) {
245             if (interfaces.get(j) != null) {
246               interfacesEmpty = false;
247               if (!results.contains(interfaces.get(j))) {
248                 interfaces.set(j, null);
249               }
250             }
251           }
252         }
253       }
254 
255       if (interfacesEmpty && classesEmpty) {
256         // As soon as we detect nothing in common, just exit.
257         return null;
258       }
259     }
260     
261     ArrayList results = new ArrayList(4);
262     ArrayList superClasses = new ArrayList(4);
263     if (!classesEmpty) {
264       for (int j = 0; j < classes.size(); j++) {
265         if (classes.get(j) != null) {
266           superClasses.add(classes.get(j));
267         }
268       }
269       // Just keep the first super class
270       if (!superClasses.isEmpty()) {
271         results.add(superClasses.get(0));
272       }
273     }
274 
275     if (!interfacesEmpty) {
276       // Do no include the interfaces belonging to the common
277       // super classes as these will be calculated again later
278       // in addContributors method.
279       List dropInterfaces = null;
280       if (!superClasses.isEmpty()) {
281         dropInterfaces = computeInterfaceOrder(superClasses);
282       }
283       
284       for (int j = 0; j < interfaces.size(); j++) {
285         if (interfaces.get(j) != null) {
286           if (dropInterfaces != null && !dropInterfaces.contains(interfaces.get(j))) {
287             results.add(interfaces.get(j));
288           }
289         }
290       }
291     }
292     
293     return results;
294   }
295 
296   /**
297    * Returns the shared instance of this manager.
298    */
299   public static ObjectActionContributorManager getManager() {
300     if (sharedInstance == null) {
301       sharedInstance = new ObjectActionContributorManager();
302     }
303     return sharedInstance;
304   }
305   
306   /**
307    * Loads the contributors from the workbench's registry.
308    */
309   private void loadContributors() {
310     ObjectActionContributorReader reader = new ObjectActionContributorReader();
311     reader.readPopupContributors(this);
312   }
313   
314   /**
315    * Returns the common denominator resource class for the given
316    * collection of objects.
317    * Do not return a resource class if the objects are resources
318    * themselves so as to prevent double registration of actions.
319    */
320   private Class getCommonResourceClass(List objects) {
321     if (objects == null || objects.size() == 0) {
322       return null;
323     }
324     Class resourceClass = LegacyResourceSupport.getResourceClass();
325     if (resourceClass == null) {
326       // resources plug-in not loaded - no resources. period.
327       return null;
328     }
329 
330     List testList = new ArrayList();
331 
332     for (int i = 0; i < objects.size(); i++) {
333       Object object = objects.get(i);
334 
335       if (object instanceof IAdaptable) {
336         if (resourceClass.isInstance(object)) {
337           continue;
338         }
339 
340         Object resource = getAdaptedResource((IAdaptable) object);
341 
342         if (resource == null) {
343           //Not a resource and does not adapt. No common resource class
344           return null;
345         }
346         testList.add(resource);
347       } else {
348         return null;
349       }
350     }
351 
352     return getCommonClass(testList);
353   }
354 }