/****************************************************************************** * Copyright (c) 2002, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation ****************************************************************************/ package org.eclipse.gmf.runtime.common.ui.services.action.internal.contributionitem; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.gmf.runtime.common.core.service.AbstractProviderConfiguration; import org.eclipse.gmf.runtime.common.core.util.Log; import org.eclipse.gmf.runtime.common.core.util.Trace; import org.eclipse.gmf.runtime.common.ui.services.action.contributionitem.IPopupMenuContributionPolicy; import org.eclipse.gmf.runtime.common.ui.services.action.internal.CommonUIServicesActionDebugOptions; import org.eclipse.gmf.runtime.common.ui.services.action.internal.CommonUIServicesActionPlugin; import org.eclipse.gmf.runtime.common.ui.services.action.internal.CommonUIServicesActionStatusCodes; import org.eclipse.gmf.runtime.common.ui.util.IPartSelector; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.text.IMarkSelection; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartSite; /** * A descriptor for an XML-based contribution made by a provider of * contribution items. This class parses an <code>IConfigurationElement</code> * that is associated with a given extension of a contribution item provider * and builds the contribution descriptor in memeory for a more convenient access * * @author melaasar */ public class ProviderContributionDescriptor extends AbstractProviderConfiguration { /** constants corresponding to different symbols in the extention schema */ private static final String PART_CONTRIBUTION = "partContribution"; //$NON-NLS-1$ private static final String PART_MENU_CONTRIBUTION = "partMenu"; //$NON-NLS-1$ private static final String PART_MENUGROUP_CONTRIBUTION = "partMenuGroup"; //$NON-NLS-1$ private static final String PART_ACTION_CONTRIBUTION = "partAction"; //$NON-NLS-1$ private static final String PART_ACTIONGROUP_CONTRIBUTION = "partActionGroup"; //$NON-NLS-1$ private static final String PART_CUSTOM_CONTRIBUTION = "partCustom"; //$NON-NLS-1$ /** * @since 1.3 */ private static final String PART_PREDEFINED_ITEM = "partPredefinedItem"; //$NON-NLS-1$ private static final String POPUP_CONTRIBUTION = "popupContribution"; //$NON-NLS-1$ private static final String POPUP_MENU_CONTRIBUTION = "popupMenu"; //$NON-NLS-1$ private static final String POPUP_MENUGROUP_CONTRIBUTION = "popupMenuGroup"; //$NON-NLS-1$ private static final String POPUP_ACTION_CONTRIBUTION = "popupAction"; //$NON-NLS-1$ private static final String POPUP_ACTIONGROUP_CONTRIBUTION = "popupActionGroup"; //$NON-NLS-1$ private static final String POPUP_CUSTOM_CONTRIBUTION = "popupCustom"; //$NON-NLS-1$ private static final String POPUP_PREDEFINED_ITEM = "popupPredefinedItem"; //$NON-NLS-1$ private static final String STRUCTURED_CRITERIA = "popupStructuredContributionCriteria"; //$NON-NLS-1$ private static final String TEXT_CRITERIA = "popupTextContributionCriteria"; //$NON-NLS-1$ private static final String MARK_CRITERIA = "popupMarkContributionCriteria"; //$NON-NLS-1$ private static final String CONTRIBUTION_ID = "id"; //$NON-NLS-1$ private static final String CONTRIBUTION_TOOLBAR_PATH = "toolbarPath"; //$NON-NLS-1$ private static final String CONTRIBUTION_MENUBAR_PATH = "menubarPath"; //$NON-NLS-1$ private static final String CONTRIBUTION_PATH = "path"; //$NON-NLS-1$ private static final String MENUGROUP_SEPARATOR = "separator"; //$NON-NLS-1$ private static final String OBJECT_CLASS = "objectClass"; //$NON-NLS-1$ private static final String OBJECT_COUNT = "objectCount"; //$NON-NLS-1$ private static final String POLICY_CLASS = "policyClass"; //$NON-NLS-1$ private static final String GLOBAL = "global"; //$NON-NLS-1$ private static final String TEXT = "text"; //$NON-NLS-1$ private static final String DOCUMENT_CLASS = "documentClass"; //$NON-NLS-1$ private static final String REMOVE = "remove"; //$NON-NLS-1$ /** * @since 1.3 */ private static final String REMOVE_FROM_TOOLBAR = "removeFromToolbar"; //$NON-NLS-1$ /** * @since 1.3 */ private static final String REMOVE_FROM_MENUBAR = "removeFromMenubar"; //$NON-NLS-1$ /** the list of all part contributions made by a provider */ private List partContributions = new ArrayList(); /** the list of all popup menu contributions made by a provider */ private List popupContributions = new ArrayList(); /** * Creates a new <code>ProviderContributionDescriptor</code> instance * given a provider configuration element * * @param configElement The provider XML configuration element */ private ProviderContributionDescriptor(IConfigurationElement configElement) { IConfigurationElement configChildren[] = configElement.getChildren(); if (configChildren.length <= 1) Log.info(CommonUIServicesActionPlugin.getDefault(), CommonUIServicesActionStatusCodes.SERVICE_FAILURE, "The contribution item provider has zero contributions"); //$NON-NLS-1$ // sort out the contributions into part and popup related for (int i = 1; i < configChildren.length; i++) { if (configChildren[i].getName().equals(PART_CONTRIBUTION)) { partContributions.add( new PartContributionDescriptor(configChildren[i])); } else if ( configChildren[i].getName().equals(POPUP_CONTRIBUTION)) { popupContributions.add( new PopupContributionDescriptor(configChildren[i])); } } } /** * Builds a new provider contribution descriptor by parsing its configuration element. * * @param configElement A provider configuration element * @return A provider XML contribution descriptor */ public static ProviderContributionDescriptor parse(IConfigurationElement configElement) { assert null != configElement : "null provider configuration element"; //$NON-NLS-1$ return new ProviderContributionDescriptor(configElement); } /** * Determines if the descriptor has any XML-based contributions. * * @return Whether the descriptor contains contribution descriptors or not */ public boolean hasContributions() { return !partContributions.isEmpty() || !popupContributions.isEmpty(); } /** * Determines if the provider contribution descriptor has contributions * for a part with the given id and class. * * @param partId The target part's id * @param partClass The target part's class * @return whether contribution are available or not */ public boolean hasContributionsFor(String partId, Class partClass) { assert null != partId : "null part id"; //$NON-NLS-1$ assert null != partClass : "null part class"; //$NON-NLS-1$ Iterator iter = partContributions.iterator(); while (iter.hasNext()) { PartContributionDescriptor contribution = (PartContributionDescriptor) iter.next(); if (contribution.appliesTo(partId, partClass)) return true; } return false; } /** * Determines if the provider contribution descriptor has contributions * for a given popup menu with a given selection as a context. * * @param popupMenu The target popup menu manager * @param selection The menu context (selection) * @return whether contribution are available or not */ public boolean hasContributionsFor( IMenuManager popupMenu, ISelection selection) { assert null != popupMenu : "null popupMenu"; //$NON-NLS-1$ assert null != selection : "null selection"; //$NON-NLS-1$ String popupId = popupMenu.getId(); Class popupClass = popupMenu.getClass(); Iterator iter = popupContributions.iterator(); while (iter.hasNext()) { PopupContributionDescriptor contribution = (PopupContributionDescriptor) iter.next(); if (contribution.appliesTo(popupId, popupClass, selection)) return true; } return false; } /** * Gets a list of contributions available in the descriptor for a given * part with the given id and class. * * @param partId The target part's id * @param partClass The target part's class * @return a list of contributions */ public List getContributionsFor(String partId, Class partClass) { assert null != partId : "null part id"; //$NON-NLS-1$ assert null != partClass : "null part class"; //$NON-NLS-1$ List contributions = new ArrayList(); Iterator iter = partContributions.iterator(); while (iter.hasNext()) { PartContributionDescriptor contribution = (PartContributionDescriptor) iter.next(); if (contribution.appliesTo(partId, partClass)) { contributions.addAll(contribution.getContributionItems()); } } return contributions; } /** * Gets a list of contributions available in the descriptor for a given * popup menu with a given selection as a context. * * @param popupMenu The target popup menu manager * @param selection The menu context (selection) * @return a list of contributions */ public List getContributionsFor( IMenuManager popupMenu, ISelection selection) { assert null != popupMenu : "null popupMenu"; //$NON-NLS-1$ assert null != selection : "null selection"; //$NON-NLS-1$ List contributions = new ArrayList(); Iterator iter = popupContributions.iterator(); while (iter.hasNext()) { PopupContributionDescriptor contribution = (PopupContributionDescriptor) iter.next(); if (contribution .appliesTo( popupMenu.getId(), popupMenu.getClass(), selection)) { contributions.addAll(contribution.getContributionItems()); } } return contributions; } /** * An abstract descriptor for a contribution made in XML by * a contribution item provider. */ private static abstract class AbstractContributionDescriptor { /** the target id */ private final String targetId; /** the target class name */ private final String targetClassName; /** the list of items contributed by this descriptor */ private List contributionItems = new ArrayList(); /** * Initializes a new contribution descriptor by reading the target * id and class from the contribution configuration element. * * @param configElement The contribution configuration element */ public AbstractContributionDescriptor(IConfigurationElement configElement) { targetId = configElement.getAttribute(ID); targetClassName = configElement.getAttribute(CLASS); if (targetId == null && targetClassName == null) Log.info(CommonUIServicesActionPlugin.getDefault(), CommonUIServicesActionStatusCodes.SERVICE_FAILURE, "Both the target id and class are missing for the contribution"); //$NON-NLS-1$ } /** * Determines whether this contribution is applicable to the given source id & class. * * @param sourceId The source id * @param sourceClass The source class * @return <code>true</code> if applicable <code>false</code> if not */ protected boolean appliesTo(String sourceId, Class sourceClass) { if (targetId != null && sourceId != null) { return targetId.equals(sourceId); } if (targetClassName != null && sourceClass != null) { return isAssignableTo(sourceClass, targetClassName); } return false; } /** * Returns the list of contribution items provided in this descriptor. * * @return a List of contributions items provided by this descriptor */ public List getContributionItems() { return contributionItems; } } /** * A descriptor for a part contribution made by a contribution item provider. */ private static class PartContributionDescriptor extends AbstractContributionDescriptor { /** * Constructs a new descriptor for a part contribution * by parsing all the contirbution items from a configuration element. * * @param configElement The contribution configuration element */ public PartContributionDescriptor(IConfigurationElement configElement) { super(configElement); IConfigurationElement configChildren[] = configElement.getChildren(); if (configChildren.length <= 0) Log.info(CommonUIServicesActionPlugin.getDefault(), CommonUIServicesActionStatusCodes.SERVICE_FAILURE, "The part contribution has zero contribution items"); //$NON-NLS-1$ for (int i = 0; i < configChildren.length; i++) { String contributionType = configChildren[i].getName(); if (contributionType.equals(PART_MENU_CONTRIBUTION)) getContributionItems().add( new PartMenuDescriptor(configChildren[i])); else if (contributionType.equals(PART_MENUGROUP_CONTRIBUTION)) getContributionItems().add( new PartMenuGroupDescriptor(configChildren[i])); else if (contributionType.equals(PART_ACTION_CONTRIBUTION)) getContributionItems().add( new PartActionDescriptor(configChildren[i])); else if (contributionType.equals(PART_CUSTOM_CONTRIBUTION)) getContributionItems().add( new PartCustomDescriptor(configChildren[i])); else if (contributionType.equals(PART_ACTIONGROUP_CONTRIBUTION)) getContributionItems().add( new PartActionGroupDescriptor(configChildren[i])); else if (contributionType.equals(PART_PREDEFINED_ITEM)) getContributionItems().add( new PartPredefinedItemDescriptor(configChildren[i])); } } /* (non-Javadoc) * @see org.eclipse.gmf.runtime.common.ui.services.action.contributionitem.ProviderContributionDescriptor.AbstractContributionDescriptor#appliesTo(java.lang.String, java.lang.Class) */ public boolean appliesTo(String sourceId, Class sourceClass) { return super.appliesTo(sourceId, sourceClass); } } /** * A descriptor for a popup menu contribution made by a contribution item provider. */ private static class PopupContributionDescriptor extends AbstractContributionDescriptor { /** an optional popup menu contribution criteria */ private PopupContributionCriteria[] criteria; /** * Constructs a new descriptor for a popup menu contribution * by parsing all the contirbution items from a configuration element. * * @param configElement The contribution configuration element */ public PopupContributionDescriptor(IConfigurationElement configElement) { super(configElement); criteria = readCriteria(configElement); IConfigurationElement configChildren[] = configElement.getChildren(); if (configChildren.length <= 0) Log.info(CommonUIServicesActionPlugin.getDefault(), CommonUIServicesActionStatusCodes.SERVICE_FAILURE, "The part contribution has zero contribution items"); //$NON-NLS-1$ for (int i = 0; i < configChildren.length; i++) { String contributionType = configChildren[i].getName(); if (contributionType.equals(POPUP_MENU_CONTRIBUTION)) getContributionItems().add( new PopupMenuDescriptor(configChildren[i])); else if (contributionType.equals(POPUP_MENUGROUP_CONTRIBUTION)) getContributionItems().add( new PopupMenuGroupDescriptor(configChildren[i])); else if (contributionType.equals(POPUP_ACTION_CONTRIBUTION)) getContributionItems().add( new PopupActionDescriptor(configChildren[i])); else if (contributionType.equals(POPUP_CUSTOM_CONTRIBUTION)) getContributionItems().add( new PopupCustomDescriptor(configChildren[i])); else if (contributionType.equals(POPUP_ACTIONGROUP_CONTRIBUTION)) getContributionItems().add( new PopupActionGroupDescriptor(configChildren[i])); else if (contributionType.equals(POPUP_PREDEFINED_ITEM)) getContributionItems().add( new PopupPredefinedItemDescriptor(configChildren[i])); } } /** * Reads the contribution criteria if any. Depending on the type of * criteria, the correct descriptor will be instantiated. * @param configElement the configuration element * @return the popup contribution criteria */ protected PopupContributionCriteria[] readCriteria(IConfigurationElement configElement) { IConfigurationElement[] criteriaEl; criteriaEl = configElement.getChildren(STRUCTURED_CRITERIA); if (criteriaEl.length > 0) { PopupContributionCriteria[] pcc = new PopupContributionCriteria[criteriaEl.length]; for (int i = 0; i < criteriaEl.length; i++) { pcc[i] = new PopupStructuredContributionCriteria(criteriaEl[i]); } return pcc; } criteriaEl = configElement.getChildren(TEXT_CRITERIA); if (criteriaEl.length > 0) { PopupContributionCriteria[] pcc = new PopupContributionCriteria[criteriaEl.length]; for (int i = 0; i < criteriaEl.length; i++) { pcc[i] = new PopupTextContributionCriteria(criteriaEl[i]); } return pcc; } criteriaEl = configElement.getChildren(MARK_CRITERIA); if (criteriaEl.length > 0) { PopupContributionCriteria[] pcc = new PopupContributionCriteria[criteriaEl.length]; for (int i = 0; i < criteriaEl.length; i++) { pcc[i] = new PopupMarkContributionCriteria(criteriaEl[i]); } return pcc; } return null; } /** * Determines whether this contribution is applicable to the given source * id & class and for the given selection. * * @param sourceId The source id * @param sourceClass The source class * @param selection The selection (context) * @return <code>true</code> if it applies and <code>false</code> if not */ public boolean appliesTo( String sourceId, Class sourceClass, ISelection selection) { if (!appliesTo(sourceId, sourceClass)) return false; if (criteria != null) { if (!isCriteriaMet(selection)) return false; } return true; } /** * Determines if at least one of the criteria is met in the given * <code>selection</code>. * * @param selection * the selection * @return <code>true</code> if at least one criteria is met, * <code>false/code> otherwise */ protected boolean isCriteriaMet(ISelection selection) { for (int i = 0; i < criteria.length; i++) { if (criteria[i].appliesTo(selection)) return true; } return false; } } /** * An abstract descriptor for a contribution item by a contribution * item provider through XML. */ private static abstract class AbstractContributionItemDescriptor { /** the contribution item id */ private String id; /** * Contructs a new contribution item descriptor by extracting the item's id * from the configuration element. * * @param configElement The configuration element */ public AbstractContributionItemDescriptor(IConfigurationElement configElement) { this.id = configElement.getAttribute(CONTRIBUTION_ID); assert null != id : "The contribution item's id is missing"; //$NON-NLS-1$ } /** * Returns the contribution item id. * * @return The id of the contribution item */ public String getId() { return id; } /** * A utility method to extract the contribution item's menu path within * its target manager from a location in the configuration. * * @param location The supplied location in the configuration * @return The contribution item's menu path in its target manager */ protected static String extractMenuPath(String location) { if (location != null) { int loc = location.lastIndexOf('/'); if (loc != -1) { return location.substring(0, loc == 0 ? 1 : loc); } } return null; } /** * A utility method to extract the contribution item's group within * its target manager from a location in the configuration. * * @param location The supplied location in the configuration * @return The contribution item's group in its target manager */ protected static String extractGroup(String location) { if (location != null) { int loc = location.lastIndexOf('/'); if (loc != -1) { return location.substring(loc + 1); } } return null; } } /** * A descriptor for a part contribution item. */ private static abstract class AbstractPartContributionItemDescriptor extends AbstractContributionItemDescriptor implements IPartSelector { /** the contribution item's menubar path */ private String menubarPath; /** the contribution item's menubar group */ private String menubarGroup; /** the contribution item's toolbar path */ private String toolbarPath; /** the contribution item's toolbar group */ private String toolbarGroup; /** the contribution item's part ID, if specified */ private String targetId; /** the contribution item's part class name or interface name, if specified */ private String targetClassName; /** * Constructs a new part contribution item from its configuration element. * * @param configElement The item's configuration element */ public AbstractPartContributionItemDescriptor(IConfigurationElement configElement) { super(configElement); String location; location = configElement.getAttribute(CONTRIBUTION_MENUBAR_PATH); if (location != null) { menubarPath = extractMenuPath(location); menubarGroup = extractGroup(location); } location = configElement.getAttribute(CONTRIBUTION_TOOLBAR_PATH); if (location != null) { toolbarPath = extractMenuPath(location); toolbarGroup = extractGroup(location); } // extract the part ID or class name from the parent element Object parent = configElement.getParent(); if (parent instanceof IConfigurationElement) { IConfigurationElement parentElement = ((IConfigurationElement) parent); targetId = parentElement.getAttribute(ID); targetClassName = parentElement.getAttribute(CLASS); } } /** * Returns the menubar path if any. * * @return The menubar path if any */ public String getMenubarPath() { return menubarPath; } /** * Returs the menubar group if any. * * @return The menubar group if any */ public String getMenubarGroup() { return menubarGroup; } /** * Returns the toolbar path if any. * * @return The toolbar path if any */ public String getToolbarPath() { return toolbarPath; } /** * Returs the toolbar group if any. * * @return The toolbar group if any */ public String getToolbarGroup() { return toolbarGroup; } /** * Determines whether or not this contribution is applicable to the * given workbench <code>part</code>. * * @param part * the workbench part to be tested * @return <code>true</code> if applicable, <code>false</code> if * not */ public boolean selects(IWorkbenchPart part) { IWorkbenchPartSite site = part.getSite(); if (site != null) { String partId = site.getId(); if (targetId != null && partId != null) { return targetId.equals(partId); } } Class partClass = part.getClass(); if (targetClassName != null && partClass != null) { return isAssignableTo(partClass, targetClassName); } return false; } } /** * A descriptor for a popup menu contribution item. */ public static abstract class AbstractPopupContributionItemDescriptor extends AbstractContributionItemDescriptor implements IPartSelector { /** the contribution item's path */ private String path; /** the contribution item's group */ private String group; /** * Constructs a new part contribution item from its configuration element. * * @param configElement The item's configuration element */ public AbstractPopupContributionItemDescriptor(IConfigurationElement configElement) { super(configElement); String location = configElement.getAttribute(CONTRIBUTION_PATH); if (location != null) { path = extractMenuPath(location); group = extractGroup(location); } else { path = "/"; //$NON-NLS-1$ group = ContributionItemConstants.GROUP_ADDITIONS; } } /** * Returns the contribution item's path if any. * * @return The contribution item's path if any */ public String getPath() { return path; } /** * Returs the contribution item's group if any. * * @return The contribution item's group if any */ public String getGroup() { return group; } /** * Always returns <code>false</code>. * <P> * Popup contributions are always re-contributed when the menu is about * to be shown, so there is no need for them to listen for selection * change on the workbench part. */ public boolean selects(IWorkbenchPart part) { return false; } } /** * A descriptor for a part menu contribution item. */ public static class PartMenuDescriptor extends AbstractPartContributionItemDescriptor { /** * Constructs a new part menu descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PartMenuDescriptor(IConfigurationElement configElement) { super(configElement); } } /** * A descriptor for a part menu group contribution item. */ public static class PartMenuGroupDescriptor extends AbstractPartContributionItemDescriptor { /** whether this menu group is a separator */ private Boolean separator; /** * Constructs a new part menu group descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PartMenuGroupDescriptor(IConfigurationElement configElement) { super(configElement); String sep = configElement.getAttribute(MENUGROUP_SEPARATOR); separator = sep == null ? Boolean.TRUE : Boolean.valueOf(sep); } /** * Returns whether this menu group descriptor is also a separator. * * @return <code>true</code> if separator and <code>false</code> if not */ public boolean isSeparator() { return separator.booleanValue(); } } /** * A descriptor for a part action contribution item. */ public static class PartActionDescriptor extends AbstractPartContributionItemDescriptor { /** whether this action is a global one */ private Boolean isGlobal; /** * Constructs a new part action descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PartActionDescriptor(IConfigurationElement configElement) { super(configElement); String global = configElement.getAttribute(GLOBAL); isGlobal = global == null ? Boolean.FALSE : Boolean.valueOf(global); } /** * Whether this is a global action * * @return <code>true</code> if global, <code>false</code> otherwise */ public boolean isGlobal() { return isGlobal.booleanValue(); } } /** * A descriptor for a part action group contribution item. */ public static class PartActionGroupDescriptor extends AbstractPartContributionItemDescriptor { /** * Constructs a new popup action group descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PartActionGroupDescriptor(IConfigurationElement configElement) { super(configElement); } } /** * A descriptor for a part custom contribution item. */ public static class PartCustomDescriptor extends AbstractPartContributionItemDescriptor { /** * Constructs a new part custom descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PartCustomDescriptor(IConfigurationElement configElement) { super(configElement); } } /** * A descriptor for a contribution item previously defined as an addition to toolbar or menubar. * * @since 1.3 */ public static class PartPredefinedItemDescriptor extends AbstractContributionItemDescriptor { /** the contribution item's path in the menubar*/ private String menubarPath; /** the contribution item's path in the toolbar*/ private String toolbarPath; /** flag to remove the predefined contribution item from the toolbar*/ private boolean removeFromToolbar; /** flag to remove the predefined contribution item from the menu*/ private boolean removeFromMenubar; /** * Constructs a new popup custom descriptor from its configuration element. * * @param configElement The contribution's configuration element */ public PartPredefinedItemDescriptor(IConfigurationElement configElement) { super(configElement); String location = configElement.getAttribute(CONTRIBUTION_MENUBAR_PATH); menubarPath = (location == null) ? "/" //$NON-NLS-1$ : extractMenuPath(location); location = configElement.getAttribute(CONTRIBUTION_TOOLBAR_PATH); toolbarPath = (location == null) ? "/" //$NON-NLS-1$ : extractMenuPath(location); removeFromToolbar = Boolean.valueOf(configElement.getAttribute(REMOVE_FROM_TOOLBAR)).booleanValue(); removeFromMenubar = Boolean.valueOf(configElement.getAttribute(REMOVE_FROM_MENUBAR)).booleanValue(); } /** * Returns the contribution item's path in the toolbar if any, or "/" if not. * * @return The contribution item's path in the toolbar if any, or "/" if not */ public String getToolbarPath() { return toolbarPath; } /** * Returns the contribution item's path in the menu if any, or "/" if not. * * @return The contribution item's path in the menu if any, or "/" if not */ public String getMenubarPath() { return menubarPath; } /** * Returns true if predefined item needs to be removed from the toolbar. * * @return true if predefined item needs to be removed from the toolbar */ public boolean isToBeRemovedFromToolbar() { return removeFromToolbar; } /** * Returns true if predefined item needs to be removed from the menubar. * * @return true if predefined item needs to be removed from the menubar */ public boolean isToBeRemovedFromMenubar() { return removeFromMenubar; } } /** * A descriptor for a popup menu contribution item. */ public static class PopupMenuDescriptor extends AbstractPopupContributionItemDescriptor { /** * Constructs a new popup menu descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PopupMenuDescriptor(IConfigurationElement configElement) { super(configElement); } } /** * A descriptor for a popup menu group contribution item. */ public static class PopupMenuGroupDescriptor extends AbstractPopupContributionItemDescriptor { /** whether this menu group is a separator */ private Boolean separator; /** * Constructs a new popup menu group descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PopupMenuGroupDescriptor(IConfigurationElement configElement) { super(configElement); String sep = configElement.getAttribute(MENUGROUP_SEPARATOR); separator = sep == null ? Boolean.TRUE : Boolean.valueOf(sep); } /** * Returns whether this menu group descriptor is also a separator. * * @return <code>true</code> if separator and <code>false</code> if not */ public boolean isSeparator() { return separator.booleanValue(); } } /** * A descriptor for a popup action contribution item. */ public static class PopupActionDescriptor extends AbstractPopupContributionItemDescriptor { /** * Constructs a new popup action descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PopupActionDescriptor(IConfigurationElement configElement) { super(configElement); } } /** * A descriptor for a popup action group contribution item. */ public static class PopupActionGroupDescriptor extends AbstractPopupContributionItemDescriptor { /** * Constructs a new popup action group descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PopupActionGroupDescriptor(IConfigurationElement configElement) { super(configElement); } } /** * A descriptor for a popup custom contribution item. */ public static class PopupCustomDescriptor extends AbstractPopupContributionItemDescriptor { /** * Constructs a new popup custom descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PopupCustomDescriptor(IConfigurationElement configElement) { super(configElement); } } /** * A descriptor for a predefined contribution item. */ public static class PopupPredefinedItemDescriptor extends AbstractContributionItemDescriptor { /** the contribution item's path */ private String path; /** flag to remove the predefined contribution item */ private boolean remove; /** * Constructs a new popup custom descriptor from its configration element. * * @param configElement The contribution's configuration element */ public PopupPredefinedItemDescriptor(IConfigurationElement configElement) { super(configElement); String location = configElement.getAttribute(CONTRIBUTION_PATH); path = (location == null) ? "/" //$NON-NLS-1$ : extractMenuPath(location); remove = Boolean.valueOf(configElement.getAttribute(REMOVE)) .booleanValue(); } /** * Returns the contribution item's path if any. * * @return The contribution item's path if any */ public String getPath() { return path; } public boolean isToBeRemoved() { return remove; } } /** * The popup menu contribution criteria. Currently the following criteria are supported: * 1) Whether a given contribution policy applies to the selection. */ private static class PopupContributionCriteria { /** the criteria configuration element */ private IConfigurationElement configElement; /** the criteria's policy class name */ private String policyClassName; /** the 'loaded' policy class */ private IPopupMenuContributionPolicy policy = null; /** * Constructs a new popup menu contribution criteria from a configuration element. * * @param configElement The criteria's configuration element */ public PopupContributionCriteria(IConfigurationElement configElement) { this.configElement = configElement; this.policyClassName = configElement.getAttribute(POLICY_CLASS); } /** * Determines if the contribution criteria applies to the given selection. * * @param selection The selection in question * @return whether it applies to it or not */ public boolean appliesTo(ISelection selection) { if (policyClassName != null) { IPopupMenuContributionPolicy thePolicy = getPolicy(); if (thePolicy == null || !thePolicy.appliesTo(selection, configElement)) return false; } return true; } /** * Loads up the policy class (if any) from the configuration element. * * @return The policy class (if any) from the contribution element */ protected IPopupMenuContributionPolicy getPolicy() { if (null == policy) { try { Object extension = configElement.createExecutableExtension( POLICY_CLASS); if (extension instanceof IPopupMenuContributionPolicy) policy = (IPopupMenuContributionPolicy) extension; else Log.info(CommonUIServicesActionPlugin.getDefault(), CommonUIServicesActionStatusCodes.SERVICE_FAILURE, "The supplied policy class name does not implement IPopupMenuContributionPolicy"); //$NON-NLS-1$ } catch (CoreException ce) { Trace.catching(CommonUIServicesActionPlugin.getDefault(), CommonUIServicesActionDebugOptions.EXCEPTIONS_CATCHING, getClass(), "getPolicy", ce); //$NON-NLS-1$ Log.log( CommonUIServicesActionPlugin.getDefault(), ce.getStatus().getSeverity(), CommonUIServicesActionStatusCodes.SERVICE_FAILURE, ce.getStatus().getMessage(), ce.getStatus().getException()); } } return policy; } } /** * The popup menu contribution criteria. Currently the following criteria are supported: * <OL> * <LI>Whether all objects in the selection are assignable from a certain class/interface or adapt to it</LI> * <LI>Whether the number of objects in the selection matches a given number</LI> * </OL> * * All criteria are optional and more could be added in the future. */ private static class PopupStructuredContributionCriteria extends PopupContributionCriteria { /** the object descriptor */ private ObjectDescriptor object; /** the criteria's target count */ private Integer targetCount; /** 'true' if numbers > the provided one should work */ private boolean orHigher; /** * Constructs a new popup menu contribution criteria from a configuration element. * * @param configElement The criteria's configuration element */ public PopupStructuredContributionCriteria(IConfigurationElement configElement) { super(configElement); object = new ObjectDescriptor( configElement, OBJECT_CLASS); String countStr = configElement.getAttribute(OBJECT_COUNT); this.orHigher = false; if (countStr != null) { if (countStr.equals("*")) { //$NON-NLS-1$ this.targetCount = Integer.valueOf("0"); //$NON-NLS-1$ this.orHigher = true; } else if (countStr.equals("+")) { //$NON-NLS-1$ this.targetCount = Integer.valueOf("1"); //$NON-NLS-1$ this.orHigher = true; } else { int plusIndex = countStr.lastIndexOf("+"); //$NON-NLS-1$ if (plusIndex > 0) { this.orHigher = true; countStr = countStr.substring(0, plusIndex); } // Since the string is 'unsafe' we'll wrap the conversion in a try/catch block try { this.targetCount = Integer.valueOf(countStr); } catch (NumberFormatException e) { // TODO Log the exception this.orHigher = true; this.targetCount = Integer.valueOf("1"); //$NON-NLS-1$ } } } } /** * Determines if the contribution criteria applies to the given selection. * * @param selection The selection in question * @return whether it applies to it or not */ public boolean appliesTo(ISelection selection) { if (!(selection instanceof IStructuredSelection)) return false; IStructuredSelection structuredSelection = (IStructuredSelection) selection; Iterator objects = structuredSelection.iterator(); while (objects.hasNext()) { if (!object.sameAs(objects.next())) return false; } if (targetCount != null) { // If 'orHigher' is set then hide if the selection count is < the targetCount if (orHigher) { if (structuredSelection.size() < targetCount.intValue()) return false; } else { if (structuredSelection.size() != targetCount.intValue()) return false; } } return super.appliesTo(selection); } } /** * The popup menu contribution criteria. Currently the following criteria are supported: * <OL> * <LI>Whether the selection has to have a given text</LI> * </OL> * * All criteria are optional and more could be added in the future. */ private static class PopupTextContributionCriteria extends PopupContributionCriteria { /** the text descriptor */ private String text; /** * Constructs a new popup menu contribution criteria from a configuration element. * * @param configElement The criteria's configuration element */ public PopupTextContributionCriteria(IConfigurationElement configElement) { super(configElement); text = configElement.getAttribute(TEXT); } /** * Determines if the contribution criteria applies to the given selection. * * @param selection The selection in question * @return whether it applies to it or not */ public boolean appliesTo(ISelection selection) { if (!(selection instanceof ITextSelection)) return false; ITextSelection textSelection = (ITextSelection) selection; if (text != null) { if (!text.equals(textSelection.getText())) return false; } return super.appliesTo(selection); } } /** * The popup menu contribution criteria. Currently the following criteria are supported: * <OL> * <LI>Whether the mark document conforms to a given document descriptor</LI> * </OL> * * All criteria are optional and more could be added in the future. */ private static class PopupMarkContributionCriteria extends PopupContributionCriteria { /** the document descriptor */ private ObjectDescriptor document; /** * Constructs a new popup menu contribution criteria from a configuration element. * * @param configElement The criteria's configuration element */ public PopupMarkContributionCriteria(IConfigurationElement configElement) { super(configElement); document = new ObjectDescriptor( configElement, DOCUMENT_CLASS); } /** * Determines if the contribution criteria applies to the given selection. * * @param selection The selection in question * @return whether it applies to it or not */ public boolean appliesTo(ISelection selection) { if (!(selection instanceof IMarkSelection)) return false; IMarkSelection markSelection = (IMarkSelection) selection; if (!document.sameAs(markSelection.getDocument())) return false; return super.appliesTo(selection); } } }