blob: 003b203c61db9b39212b899d4731b1a6bb7edf4b [file] [log] [blame]
package org.eclipse.ui.internal;
/************************************************************************
Copyright (c) 2000, 2003 IBM Corporation and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Common Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/cpl-v10.html
Contributors:
IBM - Initial implementation
************************************************************************/
import java.util.ArrayList;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.AbstractGroupMarker;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.registry.RegistryReader;
/**
* This class contains shared functionality for reading action contributions
* from plugins into workbench parts (both editors and views).
*/
public abstract class PluginActionBuilder extends RegistryReader {
public static final String TAG_MENU = "menu"; //$NON-NLS-1$
public static final String TAG_ACTION = "action"; //$NON-NLS-1$
public static final String TAG_SEPARATOR = "separator"; //$NON-NLS-1$
public static final String TAG_GROUP_MARKER = "groupMarker"; //$NON-NLS-1$
public static final String TAG_FILTER = "filter"; //$NON-NLS-1$
public static final String TAG_VISIBILITY = "visibility"; //$NON-NLS-1$
public static final String TAG_ENABLEMENT = "enablement"; //$NON-NLS-1$
public static final String TAG_SELECTION = "selection"; //$NON-NLS-1$
public static final String ATT_TARGET_ID = "targetID"; //$NON-NLS-1$
public static final String ATT_ID = "id"; //$NON-NLS-1$
public static final String ATT_LABEL = "label"; //$NON-NLS-1$
public static final String ATT_ENABLES_FOR = "enablesFor"; //$NON-NLS-1$
public static final String ATT_NAME = "name"; //$NON-NLS-1$
public static final String ATT_PATH = "path"; //$NON-NLS-1$
protected String targetID;
protected String targetContributionTag;
protected BasicContribution currentContribution;
protected ArrayList cache;
/**
* The default constructor.
*/
public PluginActionBuilder() {
}
/**
* Contributes submenus and/or actions into the provided menu and tool bar
* managers.
*/
public final void contribute(IMenuManager menu, IToolBarManager toolbar, boolean appendIfMissing) {
if (cache == null)
return;
for (int i = 0; i < cache.size(); i++) {
BasicContribution contribution = (BasicContribution)cache.get(i);
contribution.contribute(menu, appendIfMissing, toolbar, appendIfMissing);
}
}
/**
* This factory method returns a new ActionDescriptor for the
* configuration element. It should be implemented by subclasses.
*/
protected abstract ActionDescriptor createActionDescriptor(IConfigurationElement element);
/**
* Factory method to create the helper contribution class that will hold
* onto the menus and actions contributed.
*/
protected BasicContribution createContribution() {
return new BasicContribution();
}
/**
* Returns the name of the part ID attribute that is expected
* in the target extension.
*/
protected String getTargetID(IConfigurationElement element) {
String value = element.getAttribute(ATT_TARGET_ID);
return value != null ? value : "???"; //$NON-NLS-1$
}
/**
* Reads the contributions from the registry for the provided workbench
* part and the provided extension point ID.
*/
protected void readContributions(String id, String tag, String extensionPoint) {
cache = null;
currentContribution = null;
targetID = id;
targetContributionTag = tag;
readRegistry(Platform.getPluginRegistry(), PlatformUI.PLUGIN_ID, extensionPoint);
}
/**
* Implements abstract method to handle the provided XML element
* in the registry.
*/
protected boolean readElement(IConfigurationElement element) {
String tag = element.getName();
// Ignore all object contributions element as these
// are handled by the ObjectActionContributorReader.
if (tag.equals(ObjectActionContributorReader.TAG_OBJECT_CONTRIBUTION)) {
return true;
}
// Found top level contribution element
if (tag.equals(targetContributionTag)) {
if (targetID != null) {
// Ignore contributions not matching target id
String id = getTargetID(element);
if (id == null || !id.equals(targetID))
return true;
}
// Read it's sub-elements
currentContribution = createContribution();
readElementChildren(element);
if (cache == null)
cache = new ArrayList(4);
cache.add(currentContribution);
currentContribution = null;
return true;
}
// Found menu contribution sub-element
if (tag.equals(TAG_MENU)) {
currentContribution.addMenu(element);
return true;
}
// Found action contribution sub-element
if (tag.equals(TAG_ACTION)) {
currentContribution.addAction(createActionDescriptor(element));
return true;
}
return false;
}
/**
* Helper class to collect the menus and actions defined within a
* contribution element.
*/
protected static class BasicContribution {
protected ArrayList menus;
protected ArrayList actions;
public void addMenu(IConfigurationElement element) {
if (menus == null)
menus = new ArrayList(1);
menus.add(element);
}
public void addAction(ActionDescriptor desc) {
if (actions == null)
actions = new ArrayList(3);
actions.add(desc);
}
/**
* Contributes submenus and/or actions into the provided menu and tool bar
* managers.
*/
public void contribute(IMenuManager menu, boolean menuAppendIfMissing, IToolBarManager toolbar, boolean toolAppendIfMissing) {
if (menus != null && menu != null) {
for (int i = 0; i < menus.size(); i++) {
IConfigurationElement menuElement = (IConfigurationElement) menus.get(i);
contributeMenu(menuElement, menu, menuAppendIfMissing);
}
}
if (actions != null) {
for (int i = 0; i < actions.size(); i++) {
ActionDescriptor ad = (ActionDescriptor) actions.get(i);
if (menu != null)
contributeMenuAction(ad, menu, menuAppendIfMissing);
if (toolbar != null)
contributeToolbarAction(ad, toolbar, toolAppendIfMissing);
}
}
}
/**
* Creates a menu from the information in the menu configuration element and
* adds it into the provided menu manager. If 'appendIfMissing' is true, and
* menu path slot is not found, it will be created and menu will be added
* into it. Otherwise, add operation will fail.
*/
protected void contributeMenu(IConfigurationElement menuElement, IMenuManager mng, boolean appendIfMissing) {
// Get config data.
String id = menuElement.getAttribute(ATT_ID);
String label = menuElement.getAttribute(ATT_LABEL);
String path = menuElement.getAttribute(ATT_PATH);
if (label == null) {
WorkbenchPlugin.log("Invalid Menu Extension (label == null): " + id); //$NON-NLS-1$
return;
}
// Calculate menu path and group.
String group = null;
if (path != null) {
int loc = path.lastIndexOf('/');
if (loc != -1) {
group = path.substring(loc + 1);
path = path.substring(0, loc);
} else {
// assume that path represents a slot
// so actual path portion should be null
group = path;
path = null;
}
}
// Find parent menu.
IMenuManager parent = mng;
if (path != null) {
parent = mng.findMenuUsingPath(path);
if (parent == null) {
WorkbenchPlugin.log("Invalid Menu Extension (Path is invalid): " + id); //$NON-NLS-1$
return;
}
}
// Find reference group.
if (group == null)
group = IWorkbenchActionConstants.MB_ADDITIONS;
IContributionItem sep = parent.find(group);
if (sep == null) {
if (appendIfMissing)
addGroup(parent, group);
else {
WorkbenchPlugin.log("Invalid Menu Extension (Group is invalid): " + id); //$NON-NLS-1$
return;
}
}
// If the menu does not exist create it.
IMenuManager newMenu = parent.findMenuUsingPath(id);
if (newMenu == null)
newMenu = new MenuManager(label, id);
// Add the menu
try {
insertAfter(parent, group, newMenu);
} catch (IllegalArgumentException e) {
WorkbenchPlugin.log("Invalid Menu Extension (Group is missing): " + id); //$NON-NLS-1$
}
// Get the menu again as it may be wrapped, otherwise adding
// the separators and group markers below will not be wrapped
// properly if the menu was just created.
newMenu = parent.findMenuUsingPath(id);
if (newMenu == null)
WorkbenchPlugin.log("Could not find new menu: " + id); //$NON-NLS-1$
// Create separators.
IConfigurationElement[] children = menuElement.getChildren();
for (int i = 0; i < children.length; i++) {
String childName = children[i].getName();
if (childName.equals(TAG_SEPARATOR)) {
contributeSeparator(newMenu, children[i]);
} else if (childName.equals(TAG_GROUP_MARKER)) {
contributeGroupMarker(newMenu, children[i]);
}
}
}
/**
* Contributes action from action descriptor into the provided menu manager.
*/
protected void contributeMenuAction(ActionDescriptor ad, IMenuManager menu, boolean appendIfMissing) {
// Get config data.
String mpath = ad.getMenuPath();
String mgroup = ad.getMenuGroup();
if (mpath == null && mgroup == null)
return;
// Find parent menu.
IMenuManager parent = menu;
if (mpath != null) {
parent = parent.findMenuUsingPath(mpath);
if (parent == null) {
WorkbenchPlugin.log("Invalid Menu Extension (Path is invalid): " + ad.getId()); //$NON-NLS-1$
return;
}
}
// Find reference group.
if (mgroup == null)
mgroup = IWorkbenchActionConstants.MB_ADDITIONS;
IContributionItem sep = parent.find(mgroup);
if (sep == null) {
if (appendIfMissing)
addGroup(parent, mgroup);
else {
WorkbenchPlugin.log("Invalid Menu Extension (Group is invalid): " + ad.getId()); //$NON-NLS-1$
return;
}
}
// Add action.
try {
insertAfter(parent, mgroup, ad.getAction());
} catch (IllegalArgumentException e) {
WorkbenchPlugin.log("Invalid Menu Extension (Group is missing): " + ad.getId()); //$NON-NLS-1$
}
}
/**
* Creates a named menu separator from the information in the configuration element.
* If the separator already exists do not create a second.
*/
protected void contributeSeparator(IMenuManager menu, IConfigurationElement element) {
String id = element.getAttribute(ATT_NAME);
if (id == null || id.length() <= 0)
return;
IContributionItem sep = menu.find(id);
if (sep != null)
return;
insertMenuGroup(menu, new Separator(id));
}
/**
* Creates a named menu group marker from the information in the configuration element.
* If the marker already exists do not create a second.
*/
protected void contributeGroupMarker(IMenuManager menu, IConfigurationElement element) {
String id = element.getAttribute(ATT_NAME);
if (id == null || id.length() <= 0)
return;
IContributionItem marker = menu.find(id);
if (marker != null)
return;
insertMenuGroup(menu, new GroupMarker(id));
}
/**
* Contributes action from the action descriptor into the provided tool bar manager.
*/
protected void contributeToolbarAction(ActionDescriptor ad, IToolBarManager toolbar, boolean appendIfMissing) {
// Get config data.
String tpath = ad.getToolbarPath();
String tgroup = ad.getToolbarGroup();
if (tpath == null && tgroup == null)
return;
// Find reference group.
if (tgroup == null)
tgroup = IWorkbenchActionConstants.MB_ADDITIONS;
IContributionItem sep = null;
sep = toolbar.find(tgroup);
if (sep == null) {
if (appendIfMissing) {
addGroup(toolbar, tgroup);
} else {
WorkbenchPlugin.log("Invalid Toolbar Extension (Group is invalid): " + ad.getId()); //$NON-NLS-1$
return;
}
}
// Add action to tool bar.
try {
insertAfter(toolbar, tgroup, ad.getAction());
} catch (IllegalArgumentException e) {
WorkbenchPlugin.log("Invalid Toolbar Extension (Group is missing): " + ad.getId()); //$NON-NLS-1$
}
}
/**
* Inserts the separator or group marker into the menu. Subclasses may override.
*/
protected void insertMenuGroup(IMenuManager menu, AbstractGroupMarker marker) {
menu.add(marker);
}
/**
* Inserts an action after another named contribution item.
* Subclasses may override.
*/
protected void insertAfter(IContributionManager mgr, String refId, PluginAction action) {
insertAfter(mgr, refId, new PluginActionContributionItem(action));
}
/**
* Inserts a contribution item after another named contribution item.
* Subclasses may override.
*/
protected void insertAfter(IContributionManager mgr, String refId, IContributionItem item) {
mgr.insertAfter(refId, item);
}
/**
* Adds a group to a contribution manager.
* Subclasses may override.
*/
protected void addGroup(IContributionManager mgr, String name) {
mgr.add(new Separator(name));
}
}
}