blob: 4ff658018e996e1d0423263ff7f81b25ead65060 [file] [log] [blame]
package org.eclipse.ui.internal;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.util.*;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.viewers.*;
import org.eclipse.ui.*;
/**
* This manager is used to populate a popup menu manager with actions
* for a given type.
*/
public class ObjectActionContributorManager extends ObjectContributorManager {
private static ObjectActionContributorManager sharedInstance;
/**
* PopupMenuManager constructor.
*/
public ObjectActionContributorManager() {
loadContributors();
}
/**
* Returns the class search order starting with <code>extensibleClass</code>.
* The search order is defined in this class' comment.
*/
private List computeCombinedOrder(Class inputClass) {
List result = new ArrayList(4);
Class clazz = inputClass;
while (clazz != null) {
// add the class
result.add(clazz);
// add all the interfaces it implements
Class [] interfaces = clazz.getInterfaces();
for (int i=0; i<interfaces.length; i++) {
result.add(interfaces[i]);
}
// get the superclass
clazz = clazz.getSuperclass();
}
return result;
}
/**
* Contributes submenus and/or actions applicable to the selection in the
* provided viewer into the provided popup menu.
*/
public boolean contributeObjectActions(IWorkbenchPart part, IMenuManager popupMenu,
ISelectionProvider selProv)
{
// Get a selection.
ISelection selection = selProv.getSelection();
if (selection == null)
return false;
// Convert the selection into an element vector.
// According to the dictionary, a selection is "one that
// is selected", or "a collection of selected things".
// In reflection of this, we deal with one or a collection.
List elements = new ArrayList();
if (selection instanceof IStructuredSelection) {
IStructuredSelection ssel = (IStructuredSelection) selection;
Iterator enum = ssel.iterator();
while (enum.hasNext()) {
Object obj = enum.next();
elements.add(obj);
}
} else {
elements.add(selection);
}
// Calculate the common class.
Class commonClass = getCommonClass(elements);
if (commonClass == null)
return false;
// Get the resource class. It will be null if any of the
// elements are resources themselves or do not adapt to
// IResource.
Class resourceClass = getCommonResourceClass(elements);
// Get the contributors.
// If there is a resource class add it in
List contributors = null;
if (resourceClass == null)
contributors = getContributors(commonClass);
else
contributors = getContributors(commonClass, resourceClass);
if (contributors == null)
return false;
// Do the contributions. Add menus first, then actions
boolean actualContributions = false;
for (int i = 0; i < contributors.size(); i++) {
IObjectActionContributor contributor = (IObjectActionContributor) contributors.get(i);
if (!isApplicableTo(elements, contributor))
continue;
if (contributor.contributeObjectMenus(popupMenu, selProv))
actualContributions = true;
}
for (int i = 0; i < contributors.size(); i++) {
IObjectActionContributor contributor = (IObjectActionContributor) contributors.get(i);
if (!isApplicableTo(elements, contributor))
continue;
if (contributor.contributeObjectActions(part, popupMenu, selProv))
actualContributions = true;
}
return actualContributions;
}
/**
* Returns the common denominator class for
* two input classes.
*/
private Class getCommonClass(Class class1, Class class2) {
List list1 = computeCombinedOrder(class1);
List list2 = computeCombinedOrder(class2);
for (int i = 0; i < list1.size(); i++) {
for (int j = 0; j < list2.size(); j++) {
Class candidate1 = (Class)list1.get(i);
Class candidate2 = (Class)list2.get(j);
if (candidate1.equals(candidate2)) return candidate1;
}
}
// no common class
return null;
}
/**
* Returns the common denominator class for the given
* collection of objects.
*/
private Class getCommonClass(List objects) {
if (objects == null || objects.size()==0)
return null;
Class commonClass = objects.get(0).getClass();
// try easy
if (objects.size() == 1)
return commonClass;
// try harder
for (int i = 1; i < objects.size(); i++) {
Object object = objects.get(i);
Class newClass = object.getClass();
// try the short cut
if (newClass.equals(commonClass)) continue;
// compute common class
commonClass = getCommonClass(commonClass, newClass);
// give up
if (commonClass==null) return null;
}
return commonClass;
}
/**
* Returns the shared instance of this manager.
*/
public static ObjectActionContributorManager getManager() {
if (sharedInstance == null) {
sharedInstance = new ObjectActionContributorManager();
}
return sharedInstance;
}
/**
* Loads the contributors from the workbench's registry.
*/
private void loadContributors() {
ObjectActionContributorReader reader = new ObjectActionContributorReader();
reader.readPopupContributors(this);
}
/**
* Returns the common denominator resource class for the given
* collection of objects.
* Do not return a resource class if the objects are resources
* themselves so as to prevent double registration of actions.
*/
private Class getCommonResourceClass(List objects) {
if (objects == null || objects.size()==0)
return null;
List testList = new ArrayList();
for (int i = 0; i < objects.size(); i++) {
Object object = objects.get(i);
if(object instanceof IAdaptable){
if(object instanceof IResource)
continue;
IResource resource = getAdaptedResource((IAdaptable) object);
if(resource == null)
//Not a resource and does not adapt. No common resource class
return null;
testList.add(resource);
}
else
return null;
}
return getCommonClass(testList);
}
}