### Eclipse Workspace Patch 1.0 #P org.eclipse.ui.navigator Index: schema/navigatorContent.exsd =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/schema/navigatorContent.exsd,v retrieving revision 1.46 diff -u -r1.46 navigatorContent.exsd --- schema/navigatorContent.exsd 12 Sep 2009 06:36:47 -0000 1.46 +++ schema/navigatorContent.exsd 7 Mar 2010 03:57:17 -0000 @@ -38,6 +38,7 @@ + @@ -664,6 +665,37 @@ + + + + Specifies the contribution of a command to the context menu associated with a Common Navigator ViewPart. This is used in conjuction with the <b>viewerCommandMenuBinding</b> element in the <b>viewer</b> extension point. +<br/><br/> +Its function is similar the <b>menuContribution</b> element in the <b>org.eclipse.ui.menus</b> extention point (and replaces its use in the context of the Common Navigator). +<br/><br/> +You should use this element (instead of the <b>menuContribution</b> element) when there is a possibility that the same command may be associated with a given Common Navigator ViewPart instance. Configuring using this element will make sure the command only occurs one time in the context menu, where if you used the <b>menuContribution</b> element the command would be duplicated. + + + + + + + + + + + + + + + + + + + + + + + Index: schema/viewer.exsd =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/schema/viewer.exsd,v retrieving revision 1.23 diff -u -r1.23 viewer.exsd --- schema/viewer.exsd 26 Mar 2009 13:38:48 -0000 1.23 +++ schema/viewer.exsd 7 Mar 2010 03:57:17 -0000 @@ -33,6 +33,8 @@ + + @@ -161,6 +163,68 @@ + + + + Clients may use this to bind commands and handlers to their viewer. Although you can bind commands to a view using the normal mechanisms in the LINKcommand service, using this element is recommended if there will be multple unrelated plugins contributing to the view as it provides two additional benefits: +<ol> +<li>Prevents duplication - in the event that the same command is found to a viewer multiple times (by multiple unrelated plugins), it will be found only once. As is normal when using handlers, they must properly coordinate their activation. +<li>Dynamic handler creation - the specified handler will be created in response to this element, and if it has a constructor that has a LINKViewPart as its argument, that will be invoked, allowing the handler to register for and respond to the view's selection events. +</ol> +Clients may define an <b>includes</b> element to select which commands are visible to the viewer, and similarly an <b>excludes</b> element for commands that should not be made visible to the viewer. +<br><br> +A viewer may have multiple <b>viewerCommandBinding</b>s defined, and their <b>includes</b>/<b>excludes</b> statements will be aggregated to produce the final behavior. +<br><br> +For <b>actionProvider</b> definitions which are not nested under a <b>navigatorContent</b> definition, clients may specify a custom id. If clients do not specify an id, the id defaults to "org.eclipse.ui.navigator.actionProvider.X". For clients that wish to pick up <b>actionProvider</b>s with no specific id, clients must define a <b>viewerActionBinding</b> for the default id. See the examples section for how this is done. + + + + + + + + + + + The id of the common viewer. If the viewer is in a common navigator then the id must match the navigator's id defined in its <b>org.eclipse.ui.views</b> extension. + + + + + + + + + + *** get rid of this one, just start the handlers with the project explorer ** + +Clients may use this to bind commands and handlers to their viewer. Although you can bind commands to a view using the normal mechanisms in the LINKcommand service, using this element is recommended if there will be multple unrelated plugins contributing to the view as it provides two additional benefits: +<ol> +<li>Prevents duplication - in the event that the same command is found to a viewer multiple times (by multiple unrelated plugins), it will be found only once. As is normal when using handlers, they must properly coordinate their activation. +<li>Dynamic handler creation - the specified handler will be created in response to this element, and if it has a constructor that has a LINKViewPart as its argument, that will be invoked, allowing the handler to register for and respond to the view's selection events. +</ol> +Clients may define an <b>includes</b> element to select which commands are visible to the viewer, and similarly an <b>excludes</b> element for commands that should not be made visible to the viewer. +<br><br> +A viewer may have multiple <b>viewerCommandBinding</b>s defined, and their <b>includes</b>/<b>excludes</b> statements will be aggregated to produce the final behavior. +<br><br> +For <b>actionProvider</b> definitions which are not nested under a <b>navigatorContent</b> definition, clients may specify a custom id. If clients do not specify an id, the id defaults to "org.eclipse.ui.navigator.actionProvider.X". For clients that wish to pick up <b>actionProvider</b>s with no specific id, clients must define a <b>viewerActionBinding</b> for the default id. See the examples section for how this is done. + + + + + + + + + + + The id of the common viewer. If the viewer is in a common navigator then the id must match the navigator's id defined in its <b>org.eclipse.ui.views</b> extension. + + + + + + @@ -178,6 +242,12 @@ + + + + + + @@ -200,6 +270,12 @@ + + + + + + @@ -425,6 +501,44 @@ + + + + Indicates the command id or regular expression pattern to be used to find the command(s) to be associated with the viewer. These must be declared using the <b>commandMenuContribution</b> element in the <b>navigatorContent</b> extension point. + + + + + + + Content extensions may be selected exactly by using their content extension id. Clients may also use a regular expression pattern to select any content extensions that have ids that match the pattern. +<p> +Patterns are regular expressions which match unique identifiers. Please see the Java(tm) Platform documentation for <code>java.util.regex.Pattern</code> for further details. + + + + + + + + + + The identification of a handler to bind in the <b>viewerCommandBinding</b>. + + + + + + + Content extensions may be selected exactly by using their content extension id. Clients may also use a regular expression pattern to select any content extensions that have ids that match the pattern. +<p> +Patterns are regular expressions which match unique identifiers. Please see the Java(tm) Platform documentation for <code>java.util.regex.Pattern</code> for further details. + + + + + + Index: src/org/eclipse/ui/internal/navigator/NavigatorContentService.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/NavigatorContentService.java,v retrieving revision 1.44 diff -u -r1.44 NavigatorContentService.java --- src/org/eclipse/ui/internal/navigator/NavigatorContentService.java 5 Mar 2010 07:38:12 -0000 1.44 +++ src/org/eclipse/ui/internal/navigator/NavigatorContentService.java 7 Mar 2010 03:57:17 -0000 @@ -43,7 +43,10 @@ import org.eclipse.jface.viewers.Viewer; import org.eclipse.ui.IMemento; +import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.navigator.dnd.NavigatorDnDService; +import org.eclipse.ui.internal.navigator.extensions.CommandMenuContributionDescriptor; +import org.eclipse.ui.internal.navigator.extensions.CommandMenuContributionDescriptorManager; import org.eclipse.ui.internal.navigator.extensions.ExtensionPriorityComparator; import org.eclipse.ui.internal.navigator.extensions.NavigatorContentDescriptor; import org.eclipse.ui.internal.navigator.extensions.NavigatorContentDescriptorManager; @@ -52,6 +55,11 @@ import org.eclipse.ui.internal.navigator.extensions.NavigatorViewerDescriptorManager; import org.eclipse.ui.internal.navigator.extensions.StructuredViewerManager; import org.eclipse.ui.internal.navigator.sorters.NavigatorSorterService; +import org.eclipse.ui.menus.AbstractContributionFactory; +import org.eclipse.ui.menus.CommandContributionItem; +import org.eclipse.ui.menus.CommandContributionItemParameter; +import org.eclipse.ui.menus.IContributionRoot; +import org.eclipse.ui.menus.IMenuService; import org.eclipse.ui.navigator.IDescriptionProvider; import org.eclipse.ui.navigator.IExtensionActivationListener; import org.eclipse.ui.navigator.IExtensionStateModel; @@ -67,6 +75,7 @@ import org.eclipse.ui.navigator.INavigatorSaveablesService; import org.eclipse.ui.navigator.INavigatorSorterService; import org.eclipse.ui.navigator.INavigatorViewerDescriptor; +import org.eclipse.ui.services.IServiceLocator; /** *

@@ -848,6 +857,46 @@ return result; } + + /** + * Install the commands into the specified viewer + * + * @param viewer + */ + public void bindCommandMenuContributions(StructuredViewer viewer) { + CommandMenuContributionDescriptorManager mgr = CommandMenuContributionDescriptorManager + .getInstance(); + + final IMenuService menuService = (IMenuService) PlatformUI.getWorkbench().getService( + IMenuService.class); + + String urlBase = "popup:" + getViewerId(); //$NON-NLS-1$ + + Iterator it = mgr.getDescriptors().iterator(); + while (it.hasNext()) { + CommandMenuContributionDescriptor desc = (CommandMenuContributionDescriptor) it.next(); + NavigatorViewerDescriptor vd = NavigatorViewerDescriptorManager.getInstance() + .getNavigatorViewerDescriptor(getViewerId()); + if (vd.isVisibleCommand(desc.getCommandId())) { + final CommandMenuContributionDescriptor finalDesc = desc; + + String url = urlBase; + if (desc.getAfter() != null) + url += "?after=" + desc.getAfter(); //$NON-NLS-1$ + + AbstractContributionFactory factory = new AbstractContributionFactory(url, desc.getPluginId()) { + public void createContributionItems(IServiceLocator serviceLocator, + IContributionRoot additions) { + CommandContributionItemParameter cp = new CommandContributionItemParameter(serviceLocator, null, finalDesc.getCommandId(), CommandContributionItem.STYLE_PULLDOWN); + CommandContributionItem item = new CommandContributionItem(cp); + additions.addContributionItem(item, null); + } + }; + menuService.addContributionFactory(factory); + } + } + } + /* * (non-Javadoc) * Index: src/org/eclipse/ui/internal/navigator/extensions/CommandMenuContributionDescriptor.java =================================================================== RCS file: src/org/eclipse/ui/internal/navigator/extensions/CommandMenuContributionDescriptor.java diff -N src/org/eclipse/ui/internal/navigator/extensions/CommandMenuContributionDescriptor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/navigator/extensions/CommandMenuContributionDescriptor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2003, 2010 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.ui.internal.navigator.extensions; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.ui.internal.navigator.extensions.INavigatorContentExtPtConstants; + +/** + * + * + * @since 3.5 + */ +public class CommandMenuContributionDescriptor implements INavigatorContentExtPtConstants { + + private final IConfigurationElement configurationElement; + + private final String commandId; + + private final String after; + + private final String pluginId; + + private String toString; + + /** + * @param aConfigElement + */ + public CommandMenuContributionDescriptor(IConfigurationElement aConfigElement) { + super(); + Assert.isTrue(TAG_COMMAND_MENU_CONTRIBUTION.equals(aConfigElement.getName())); + configurationElement = aConfigElement; + pluginId = configurationElement.getContributor().getName(); + commandId = configurationElement.getAttribute(ATT_COMMAND_ID); + after = configurationElement.getAttribute(ATT_AFTER); + } + + /** + * + * @return The command id. + */ + public String getCommandId() { + return commandId; + } + + /** + * + * @return The after value which is which group the command is placed in in + * the context menu. + */ + public String getAfter() { + return after; + } + + /** + * @return the id of the contributing plugin + */ + public String getPluginId() { + return pluginId; + } + + public String toString() { + if (toString == null) { + toString = "CommandMenuContributionDescriptor[commandId=" + getCommandId() + ", after=" + getAfter() + "]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + } + return toString; + } + +} Index: src/org/eclipse/ui/internal/navigator/extensions/CommandMenuContributionDescriptorManager.java =================================================================== RCS file: src/org/eclipse/ui/internal/navigator/extensions/CommandMenuContributionDescriptorManager.java diff -N src/org/eclipse/ui/internal/navigator/extensions/CommandMenuContributionDescriptorManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/navigator/extensions/CommandMenuContributionDescriptorManager.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2010 Oakland Software Incorporated 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: + * Francis Upton IV, Oakland Software Incorporated - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.navigator.extensions; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.ui.internal.navigator.extensions.NavigatorContentRegistryReader; + +/** + * Manages descriptors consumed from the 'commandMenuContribution' elements of + * the org.eclipse.ui.navigator.navigatorContent extension point. + * + * @since 3.5 + * + */ +public class CommandMenuContributionDescriptorManager { + + private static final CommandMenuContributionDescriptorManager INSTANCE = new CommandMenuContributionDescriptorManager(); + + private CommandMenuContributionDescriptorManager() { + + new RegistryReader().readRegistry(); + } + + /** + * @return the singleton instance of the this class + */ + public static CommandMenuContributionDescriptorManager getInstance() { + return INSTANCE; + } + + private final Set rootDescriptors = new HashSet(); + + private final List rootDescriptorsList = new ArrayList(); + + /** + * @return the descriptors + */ + public List getDescriptors() { + return rootDescriptorsList; + } + + /** + * + * @param descriptor + * A valid descriptor to begin managing. + */ + protected void addActionDescriptor(CommandMenuContributionDescriptor descriptor) { + if (rootDescriptors.contains(descriptor.getCommandId())) { + return; + } + rootDescriptorsList.add(descriptor); + rootDescriptors.add(descriptor.getCommandId()); + } + + private class RegistryReader extends NavigatorContentRegistryReader { + + protected boolean readElement(IConfigurationElement anElement) { + if (TAG_COMMAND_MENU_CONTRIBUTION.equals(anElement.getName())) { + addActionDescriptor(new CommandMenuContributionDescriptor(anElement)); + return true; + } + return super.readElement(anElement); + } + } + +} Index: src/org/eclipse/ui/internal/navigator/extensions/INavigatorContentExtPtConstants.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/extensions/INavigatorContentExtPtConstants.java,v retrieving revision 1.9 diff -u -r1.9 INavigatorContentExtPtConstants.java --- src/org/eclipse/ui/internal/navigator/extensions/INavigatorContentExtPtConstants.java 8 Mar 2009 14:34:56 -0000 1.9 +++ src/org/eclipse/ui/internal/navigator/extensions/INavigatorContentExtPtConstants.java 7 Mar 2010 03:57:19 -0000 @@ -20,6 +20,9 @@ String TAG_ACTION_PROVIDER = "actionProvider"; //$NON-NLS-1$ /** */ + String TAG_COMMAND_MENU_CONTRIBUTION = "commandMenuContribution"; //$NON-NLS-1$ + + /** */ String TAG_NAVIGATOR_CONTENT = "navigatorContent"; //$NON-NLS-1$ /** */ @@ -62,6 +65,12 @@ String ATT_ID = "id"; //$NON-NLS-1$ /** */ + String ATT_COMMAND_ID = "commandId"; //$NON-NLS-1$ + + /** */ + String ATT_AFTER = "after"; //$NON-NLS-1$ + + /** */ String ATT_NAME = "name"; //$NON-NLS-1$ /** */ Index: src/org/eclipse/ui/internal/navigator/extensions/IViewerExtPtConstants.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/extensions/IViewerExtPtConstants.java,v retrieving revision 1.5 diff -u -r1.5 IViewerExtPtConstants.java --- src/org/eclipse/ui/internal/navigator/extensions/IViewerExtPtConstants.java 25 May 2009 20:52:48 -0000 1.5 +++ src/org/eclipse/ui/internal/navigator/extensions/IViewerExtPtConstants.java 7 Mar 2010 03:57:19 -0000 @@ -36,6 +36,12 @@ String TAG_VIEWER_ACTION_BINDING = "viewerActionBinding"; //$NON-NLS-1$ /** */ + String TAG_VIEWER_COMMAND_BINDING = "viewerCommandMenuBinding"; //$NON-NLS-1$ + + /** */ + String TAG_VIEWER_HANDLER_BINDING = "viewerHandlerBinding"; //$NON-NLS-1$ + + /** */ String TAG_POPUP_MENU = "popupMenu"; //$NON-NLS-1$ /** */ Index: src/org/eclipse/ui/internal/navigator/extensions/NavigatorViewerDescriptor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/extensions/NavigatorViewerDescriptor.java,v retrieving revision 1.12 diff -u -r1.12 NavigatorViewerDescriptor.java --- src/org/eclipse/ui/internal/navigator/extensions/NavigatorViewerDescriptor.java 25 May 2009 20:52:48 -0000 1.12 +++ src/org/eclipse/ui/internal/navigator/extensions/NavigatorViewerDescriptor.java 7 Mar 2010 03:57:19 -0000 @@ -48,9 +48,11 @@ static final String ATT_PATTERN = "pattern"; //$NON-NLS-1$ - private static final String TAG_CONTENT_EXTENSION = "contentExtension"; //$NON-NLS-1$ + static final String TAG_CONTENT_EXTENSION = "contentExtension"; //$NON-NLS-1$ - private static final String TAG_ACTION_EXTENSION = "actionExtension"; //$NON-NLS-1$ + static final String TAG_ACTION_EXTENSION = "actionExtension"; //$NON-NLS-1$ + + static final String TAG_COMMAND_MENU_EXTENSION = "commandMenuExtension"; //$NON-NLS-1$ private final String viewerId; @@ -60,6 +62,8 @@ private Binding contentBinding = new Binding(TAG_CONTENT_EXTENSION); + private Binding commandBinding = new Binding(TAG_COMMAND_MENU_EXTENSION); + private MenuInsertionPoint[] customInsertionPoints = null; private boolean allowsPlatformContributions = true; @@ -101,28 +105,6 @@ return popupMenuId != null ? popupMenuId : viewerId; } - /** - * Consume an action binding for this viewer. - * - * @param element - * The IConfigurationElement containing a viewerActionBinding - * element. - */ - public void consumeActionBinding(IConfigurationElement element) { - consumeBinding(element, false); - } - - /** - * Consume a content binding for this viewer. - * - * @param element - * The IConfigurationElement containing a viewerContentBinding - * element. - */ - public void consumeContentBinding(IConfigurationElement element) { - consumeBinding(element, true); - } - public boolean isRootExtension(String aContentExtensionId) { return contentBinding.isRootExtension(aContentExtensionId); } @@ -139,6 +121,10 @@ return actionBinding.isVisibleExtension(anActionExtensionId); } + public boolean isVisibleCommand(String aCommandId) { + return commandBinding.isVisibleExtension(aCommandId); + } + public boolean hasOverriddenRootExtensions() { return contentBinding.hasOverriddenRootExtensions(); } @@ -237,6 +223,20 @@ } /** + * @param binding + */ + public void setCommandBinding(Binding binding) { + commandBinding = binding; + } + + /** + * @return the content Binding + */ + public Binding getCommandBinding() { + return commandBinding; + } + + /** * @param assistants */ public void setDragAssistants(Set assistants) { @@ -328,16 +328,26 @@ return dragAssistants; } - private void consumeBinding(IConfigurationElement element, boolean isContent) { + /** + * @param element + * @param bindingTag + */ + public void consumeBinding(IConfigurationElement element, String bindingTag) { IConfigurationElement[] includesElement = element .getChildren(TAG_INCLUDES); + boolean respectRoots = false; + Binding binding = null; + if (bindingTag.equals(TAG_CONTENT_EXTENSION)) { + binding = contentBinding; + respectRoots = true; + } else if (bindingTag.equals(TAG_ACTION_EXTENSION)) + binding = actionBinding; + else if (bindingTag.equals(TAG_COMMAND_MENU_EXTENSION)) + binding = commandBinding; + if (includesElement.length == 1) { - if (isContent) { - contentBinding.consumeIncludes(includesElement[0], true); - } else { - actionBinding.consumeIncludes(includesElement[0], false); - } + binding.consumeIncludes(includesElement[0], respectRoots); } else if (includesElement.length >= 1) { NavigatorPlugin.logError(0, NLS.bind( CommonNavigatorMessages.Too_many_elements_Warning, @@ -353,12 +363,7 @@ .getChildren(TAG_EXCLUDES); if (excludesElement.length == 1) { - - if (isContent) { - contentBinding.consumeExcludes(excludesElement[0]); - } else { - actionBinding.consumeExcludes(excludesElement[0]); - } + binding.consumeExcludes(excludesElement[0]); } else if (excludesElement.length >= 1) { NavigatorPlugin.logError(0, NLS.bind( CommonNavigatorMessages.Too_many_elements_Warning, @@ -371,4 +376,11 @@ } } + void setupFromParent(NavigatorViewerDescriptor parentDesc) { + setActionBinding(parentDesc.getActionBinding()); + setContentBinding(parentDesc.getContentBinding()); + setCommandBinding(parentDesc.getCommandBinding()); + setDragAssistants(parentDesc.getDragAssistants()); + } + } Index: src/org/eclipse/ui/internal/navigator/extensions/NavigatorViewerDescriptorManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/internal/navigator/extensions/NavigatorViewerDescriptorManager.java,v retrieving revision 1.8 diff -u -r1.8 NavigatorViewerDescriptorManager.java --- src/org/eclipse/ui/internal/navigator/extensions/NavigatorViewerDescriptorManager.java 8 Mar 2009 20:45:04 -0000 1.8 +++ src/org/eclipse/ui/internal/navigator/extensions/NavigatorViewerDescriptorManager.java 7 Mar 2010 03:57:19 -0000 @@ -46,9 +46,7 @@ NavigatorViewerDescriptor desc = (NavigatorViewerDescriptor) it.next(); NavigatorViewerDescriptor parentDesc = (NavigatorViewerDescriptor) viewerDescriptors.get(desc.getInheritBindingsFromViewer()); if (parentDesc != null) { - desc.setActionBinding(parentDesc.getActionBinding()); - desc.setContentBinding(parentDesc.getContentBinding()); - desc.setDragAssistants(parentDesc.getDragAssistants()); + desc.setupFromParent(parentDesc); } } } @@ -179,18 +177,28 @@ } return true; } + + System.out.println("name: " + element.getName()); //$NON-NLS-1$ + if (TAG_VIEWER_CONTENT_BINDING.equals(element.getName())) { String viewerId = element.getAttribute(ATT_VIEWER_ID); NavigatorViewerDescriptor descriptor = getNavigatorViewerDescriptor(viewerId); - descriptor.consumeContentBinding(element); + descriptor.consumeBinding(element, NavigatorViewerDescriptor.TAG_CONTENT_EXTENSION); return true; } if (TAG_VIEWER_ACTION_BINDING.equals(element.getName())) { String viewerId = element.getAttribute(ATT_VIEWER_ID); NavigatorViewerDescriptor descriptor = getNavigatorViewerDescriptor(viewerId); - descriptor.consumeActionBinding(element); + descriptor.consumeBinding(element, NavigatorViewerDescriptor.TAG_ACTION_EXTENSION); return true; - } if (TAG_DRAG_ASSISTANT.equals(element.getName())) { + } + if (TAG_VIEWER_COMMAND_BINDING.equals(element.getName())) { + String viewerId = element.getAttribute(ATT_VIEWER_ID); + NavigatorViewerDescriptor descriptor = getNavigatorViewerDescriptor(viewerId); + descriptor.consumeBinding(element, NavigatorViewerDescriptor.TAG_COMMAND_MENU_EXTENSION); + return true; + } + if (TAG_DRAG_ASSISTANT.equals(element.getName())) { String viewerId = element.getAttribute(ATT_VIEWER_ID); NavigatorViewerDescriptor descriptor = getNavigatorViewerDescriptor(viewerId); descriptor.addDragAssistant(new CommonDragAssistantDescriptor(element)); Index: src/org/eclipse/ui/navigator/CommonNavigator.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/CommonNavigator.java,v retrieving revision 1.47 diff -u -r1.47 CommonNavigator.java --- src/org/eclipse/ui/navigator/CommonNavigator.java 8 Mar 2009 20:45:04 -0000 1.47 +++ src/org/eclipse/ui/navigator/CommonNavigator.java 7 Mar 2010 03:57:19 -0000 @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.ui.navigator; +import org.eclipse.core.commands.IHandler; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.PerformanceStats; import org.eclipse.jface.action.IAction; @@ -432,6 +433,17 @@ return super.getAdapter(adapter); } + + /** + * @param commandId + * @param handler + * + * @since 3.5 + */ + public void bindHandler(String commandId, IHandler handler) { + + } + /** * Returns the IShowInSource for this view. */ Index: src/org/eclipse/ui/navigator/CommonViewer.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/CommonViewer.java,v retrieving revision 1.40 diff -u -r1.40 CommonViewer.java --- src/org/eclipse/ui/navigator/CommonViewer.java 10 Jan 2010 09:48:50 -0000 1.40 +++ src/org/eclipse/ui/navigator/CommonViewer.java 7 Mar 2010 03:57:19 -0000 @@ -109,6 +109,7 @@ setContentProvider(contentService.createCommonContentProvider()); setLabelProvider(new NavigatorDecoratingLabelProvider(contentService.createCommonLabelProvider())); initDragAndDrop(); + contentService.bindCommandMenuContributions(this); } void setCommonNavigator(CommonNavigator navigator) { Index: src/org/eclipse/ui/navigator/INavigatorViewerDescriptor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator/src/org/eclipse/ui/navigator/INavigatorViewerDescriptor.java,v retrieving revision 1.14 diff -u -r1.14 INavigatorViewerDescriptor.java --- src/org/eclipse/ui/navigator/INavigatorViewerDescriptor.java 8 Mar 2009 20:45:04 -0000 1.14 +++ src/org/eclipse/ui/navigator/INavigatorViewerDescriptor.java 7 Mar 2010 03:57:20 -0000 @@ -93,6 +93,19 @@ boolean isVisibleActionExtension(String anActionExtensionId); /** + * Returns true if a command with the given id is 'visible'. A command + * is 'visible' if it matches a viewerCommandMenuBinding for the + * given viewer id. + * + * @param aCommandId + * The id to query + * @return True if the command id matches a viewerCommandMenuBinding for + * the viewer id of this descriptor. + * @since 3.5 + */ + boolean isVisibleCommand(String aCommandId); + + /** * Returns true if the content extension of the given id matches a * viewerContentBinding extension that declares isRoot as true. * #P org.eclipse.ui.navigator.resources Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator.resources/META-INF/MANIFEST.MF,v retrieving revision 1.29 diff -u -r1.29 MANIFEST.MF --- META-INF/MANIFEST.MF 1 Sep 2009 04:32:24 -0000 1.29 +++ META-INF/MANIFEST.MF 7 Mar 2010 03:57:21 -0000 @@ -2,7 +2,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Plugin.name Bundle-SymbolicName: org.eclipse.ui.navigator.resources; singleton:=true -Bundle-Version: 3.4.200.qualifier +Bundle-Version: 3.5.0.qualifier Bundle-Activator: org.eclipse.ui.internal.navigator.resources.plugin.WorkbenchNavigatorPlugin Bundle-Vendor: %Plugin.providerName Bundle-Localization: plugin Index: plugin.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator.resources/plugin.properties,v retrieving revision 1.16 diff -u -r1.16 plugin.properties --- plugin.properties 25 May 2009 20:52:22 -0000 1.16 +++ plugin.properties 7 Mar 2010 03:57:21 -0000 @@ -15,6 +15,8 @@ resourceGoTo.extension.name=Resources Go To workingsets.extension.name=Working Sets Common_Resource_Navigator=Project Explorer + +command.goToResource=Go To Resource filters.startsWithDot.name=.* resources filters.startsWithDot.description=Hides resources that begin with "." Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.navigator.resources/plugin.xml,v retrieving revision 1.42 diff -u -r1.42 plugin.xml --- plugin.xml 22 Jan 2009 23:08:33 -0000 1.42 +++ plugin.xml 7 Mar 2010 03:57:21 -0000 @@ -58,6 +58,22 @@ + + + + + + + + + + + + @@ -313,6 +329,9 @@ class="org.eclipse.ui.internal.navigator.workingsets.WorkingSetSorter" id="org.eclipse.ui.navigator.resources.workingSets.sorter"/> + + - + Index: src/org/eclipse/ui/navigator/resources/CopyHandler.java =================================================================== RCS file: src/org/eclipse/ui/navigator/resources/CopyHandler.java diff -N src/org/eclipse/ui/navigator/resources/CopyHandler.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/navigator/resources/CopyHandler.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,238 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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.ui.navigator.resources; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWTError; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.SelectionListenerAction; +import org.eclipse.ui.part.ResourceTransfer; +import org.eclipse.ui.internal.navigator.resources.plugin.WorkbenchNavigatorMessages; + +/** + * Standard action for copying the currently selected resources to the clipboard. + *

+ * This class may be instantiated; it is not intended to be subclassed. + *

+ * + * @since 3.5 + */ +public class CopyHandler extends AbstractHandler { + + /** + * The id of this action. + */ + public static final String ID = PlatformUI.PLUGIN_ID + ".CopyAction"; //$NON-NLS-1$ + + /** + * The shell in which to show any dialogs. + */ + private Shell shell; + + /** + * System clipboard + */ + private Clipboard clipboard; + + /** + * Associated paste action. May be null + */ + private PasteHandler pasteAction; + + /** + * Creates a new action. + * + * @param shell the shell for any dialogs + * @param clipboard a platform clipboard + */ + public CopyHandler(Shell shell, Clipboard clipboard) { + super(WorkbenchNavigatorMessages.CopyAction_Cop_); + Assert.isNotNull(shell); + Assert.isNotNull(clipboard); + this.shell = shell; + this.clipboard = clipboard; + setToolTipText(WorkbenchNavigatorMessages.CopyAction_Copy_selected_resource_s_); + setId(CopyHandler.ID); + PlatformUI.getWorkbench().getHelpSystem().setHelp(this, "CopyHelpId"); //$NON-NLS-1$ + // TODO INavigatorHelpContextIds.COPY_ACTION); + } + + /** + * Creates a new action. + * + * @param shell the shell for any dialogs + * @param clipboard a platform clipboard + * @param pasteAction a paste action + * + * @since 2.0 + */ + public CopyHandler(Shell shell, Clipboard clipboard, PasteHandler pasteAction) { + this(shell, clipboard); + this.pasteAction = pasteAction; + } + + /** + * The CopyAction implementation of this method defined + * on IAction copies the selected resources to the + * clipboard. + */ + /* (non-Javadoc) + * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + public Object execute(ExecutionEvent event) throws ExecutionException { + List selectedResources = getSelectedResources(); + IResource[] resources = (IResource[]) selectedResources + .toArray(new IResource[selectedResources.size()]); + + // Get the file names and a string representation + final int length = resources.length; + int actualLength = 0; + String[] fileNames = new String[length]; + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < length; i++) { + IPath location = resources[i].getLocation(); + // location may be null. See bug 29491. + if (location != null) { + fileNames[actualLength++] = location.toOSString(); + } + if (i > 0) { + buf.append("\n"); //$NON-NLS-1$ + } + buf.append(resources[i].getName()); + } + // was one or more of the locations null? + if (actualLength < length) { + String[] tempFileNames = fileNames; + fileNames = new String[actualLength]; + for (int i = 0; i < actualLength; i++) { + fileNames[i] = tempFileNames[i]; + } + } + setClipboard(resources, fileNames, buf.toString()); + + // update the enablement of the paste action + // workaround since the clipboard does not suppot callbacks + if (pasteAction != null && pasteAction.getStructuredSelection() != null) { + pasteAction.selectionChanged(pasteAction.getStructuredSelection()); + } + return null; + + } + + /** + * Set the clipboard contents. Prompt to retry if clipboard is busy. + * + * @param resources the resources to copy to the clipboard + * @param fileNames file names of the resources to copy to the clipboard + * @param names string representation of all names + */ + private void setClipboard(IResource[] resources, String[] fileNames, + String names) { + try { + // set the clipboard contents + if (fileNames.length > 0) { + clipboard.setContents(new Object[] { resources, fileNames, + names }, + new Transfer[] { ResourceTransfer.getInstance(), + FileTransfer.getInstance(), + TextTransfer.getInstance() }); + } else { + clipboard.setContents(new Object[] { resources, names }, + new Transfer[] { ResourceTransfer.getInstance(), + TextTransfer.getInstance() }); + } + } catch (SWTError e) { + if (e.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { + throw e; + } + if (MessageDialog + .openQuestion( + shell, + "Problem with copy title", // TODO ResourceNavigatorMessages.CopyToClipboardProblemDialog_title, //$NON-NLS-1$ + "Problem with copy.")) { //$NON-NLS-1$ + setClipboard(resources, fileNames, names); + } + } + } + + /** + * The CopyAction implementation of this + * SelectionListenerAction method enables this action if + * one or more resources of compatible types are selected. + */ + protected boolean updateSelection(IStructuredSelection selection) { + if (!super.updateSelection(selection)) { + return false; + } + + if (getSelectedNonResources().size() > 0) { + return false; + } + + List selectedResources = getSelectedResources(); + if (selectedResources.size() == 0) { + return false; + } + + boolean projSelected = selectionIsOfType(IResource.PROJECT); + boolean fileFoldersSelected = selectionIsOfType(IResource.FILE + | IResource.FOLDER); + if (!projSelected && !fileFoldersSelected) { + return false; + } + + // selection must be homogeneous + if (projSelected && fileFoldersSelected) { + return false; + } + + // must have a common parent + IContainer firstParent = ((IResource) selectedResources.get(0)) + .getParent(); + if (firstParent == null) { + return false; + } + + Iterator resourcesEnum = selectedResources.iterator(); + while (resourcesEnum.hasNext()) { + IResource currentResource = (IResource) resourcesEnum.next(); + if (!currentResource.getParent().equals(firstParent)) { + return false; + } + // resource location must exist + if (currentResource.getLocationURI() == null) { + return false; + } + } + + return true; + } + + +} + Index: src/org/eclipse/ui/navigator/resources/PasteHandler.java =================================================================== RCS file: src/org/eclipse/ui/navigator/resources/PasteHandler.java diff -N src/org/eclipse/ui/navigator/resources/PasteHandler.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/navigator/resources/PasteHandler.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,275 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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.ui.navigator.resources; + +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.CopyFilesAndFoldersOperation; +import org.eclipse.ui.actions.CopyProjectOperation; +import org.eclipse.ui.actions.SelectionListenerAction; +import org.eclipse.ui.part.ResourceTransfer; +import org.eclipse.ui.internal.navigator.resources.plugin.WorkbenchNavigatorMessages; + +/** + * Standard action for pasting resources on the clipboard to the selected resource's location. + *

+ * This class may be instantiated; it is not intended to be subclassed. + *

+ * + * @since 3.5 + */ +public class PasteHandler extends AbstractHandler { + + /** + * The id of this action. + */ + public static final String ID = PlatformUI.PLUGIN_ID + ".PasteAction";//$NON-NLS-1$ + + /** + * The shell in which to show any dialogs. + */ + private Shell shell; + + /** + * System clipboard + */ + private Clipboard clipboard; + + /** + * Creates a new action. + * + * @param shell the shell for any dialogs + * @param clipboard the clipboard + */ + public PasteHandler(Shell shell, Clipboard clipboard) { + super(WorkbenchNavigatorMessages.PasteAction_Past_); + Assert.isNotNull(shell); + Assert.isNotNull(clipboard); + this.shell = shell; + this.clipboard = clipboard; + setToolTipText(WorkbenchNavigatorMessages.PasteAction_Paste_selected_resource_s_); + setId(PasteHandler.ID); + PlatformUI.getWorkbench().getHelpSystem().setHelp(this, "HelpId"); //$NON-NLS-1$ + // TODO INavigatorHelpContextIds.PASTE_ACTION); + } + + /** + * Returns the actual target of the paste action. Returns null + * if no valid target is selected. + * + * @return the actual target of the paste action + */ + private IResource getTarget() { + List selectedResources = getSelectedResources(); + + for (int i = 0; i < selectedResources.size(); i++) { + IResource resource = (IResource) selectedResources.get(i); + + if (resource instanceof IProject && !((IProject) resource).isOpen()) { + return null; + } + if (resource.getType() == IResource.FILE) { + resource = resource.getParent(); + } + if (resource != null) { + return resource; + } + } + return null; + } + + /** + * Returns whether any of the given resources are linked resources. + * + * @param resources resource to check for linked type. may be null + * @return true=one or more resources are linked. false=none of the + * resources are linked + */ + private boolean isLinked(IResource[] resources) { + for (int i = 0; i < resources.length; i++) { + if (resources[i].isLinked()) { + return true; + } + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + public Object execute(ExecutionEvent event) throws ExecutionException { + // TODO Auto-generated method stub + return null; + } + + /** + * Implementation of method defined on IAction. + */ + public void run() { + // try a resource transfer + ResourceTransfer resTransfer = ResourceTransfer.getInstance(); + IResource[] resourceData = (IResource[]) clipboard + .getContents(resTransfer); + + if (resourceData != null && resourceData.length > 0) { + if (resourceData[0].getType() == IResource.PROJECT) { + // enablement checks for all projects + for (int i = 0; i < resourceData.length; i++) { + CopyProjectOperation operation = new CopyProjectOperation( + this.shell); + operation.copyProject((IProject) resourceData[i]); + } + } else { + // enablement should ensure that we always have access to a container + IContainer container = getContainer(); + + CopyFilesAndFoldersOperation operation = new CopyFilesAndFoldersOperation( + this.shell); + operation.copyResources(resourceData, container); + } + return; + } + + // try a file transfer + FileTransfer fileTransfer = FileTransfer.getInstance(); + String[] fileData = (String[]) clipboard.getContents(fileTransfer); + + if (fileData != null) { + // enablement should ensure that we always have access to a container + IContainer container = getContainer(); + + CopyFilesAndFoldersOperation operation = new CopyFilesAndFoldersOperation( + this.shell); + operation.copyFiles(fileData, container); + } + } + + /** + * Returns the container to hold the pasted resources. + */ + private IContainer getContainer() { + List selection = getSelectedResources(); + if (selection.get(0) instanceof IFile) { + return ((IFile) selection.get(0)).getParent(); + } + return (IContainer) selection.get(0); + } + + /** + * The PasteAction implementation of this + * SelectionListenerAction method enables this action if + * a resource compatible with what is on the clipboard is selected. + * + * -Clipboard must have IResource or java.io.File + * -Projects can always be pasted if they are open + * -Workspace folder may not be copied into itself + * -Files and folders may be pasted to a single selected folder in open + * project or multiple selected files in the same folder + */ + protected boolean updateSelection(IStructuredSelection selection) { + if (!super.updateSelection(selection)) { + return false; + } + + final IResource[][] clipboardData = new IResource[1][]; + shell.getDisplay().syncExec(new Runnable() { + public void run() { + // clipboard must have resources or files + ResourceTransfer resTransfer = ResourceTransfer.getInstance(); + clipboardData[0] = (IResource[]) clipboard + .getContents(resTransfer); + } + }); + IResource[] resourceData = clipboardData[0]; + boolean isProjectRes = resourceData != null && resourceData.length > 0 + && resourceData[0].getType() == IResource.PROJECT; + + if (isProjectRes) { + for (int i = 0; i < resourceData.length; i++) { + // make sure all resource data are open projects + // can paste open projects regardless of selection + if (resourceData[i].getType() != IResource.PROJECT + || ((IProject) resourceData[i]).isOpen() == false) { + return false; + } + } + return true; + } + + if (getSelectedNonResources().size() > 0) { + return false; + } + + IResource targetResource = getTarget(); + // targetResource is null if no valid target is selected (e.g., open project) + // or selection is empty + if (targetResource == null) { + return false; + } + + // can paste files and folders to a single selection (file, folder, + // open project) or multiple file selection with the same parent + List selectedResources = getSelectedResources(); + if (selectedResources.size() > 1) { + for (int i = 0; i < selectedResources.size(); i++) { + IResource resource = (IResource) selectedResources.get(i); + if (resource.getType() != IResource.FILE) { + return false; + } + if (!targetResource.equals(resource.getParent())) { + return false; + } + } + } + if (resourceData != null) { + // linked resources can only be pasted into projects + if (isLinked(resourceData) + && targetResource.getType() != IResource.PROJECT + && targetResource.getType() != IResource.FOLDER) { + return false; + } + + if (targetResource.getType() == IResource.FOLDER) { + // don't try to copy folder to self + for (int i = 0; i < resourceData.length; i++) { + if (targetResource.equals(resourceData[i])) { + return false; + } + } + } + return true; + } + TransferData[] transfers = clipboard.getAvailableTypes(); + FileTransfer fileTransfer = FileTransfer.getInstance(); + for (int i = 0; i < transfers.length; i++) { + if (fileTransfer.isSupportedType(transfers[i])) { + return true; + } + } + return false; + } + +} +