/** * Copyright (c) 2002-2007 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 - Initial API and implementation */ package org.eclipse.emf.edit.ui.action; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.jface.action.Action; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.command.UnexecutableCommand; import org.eclipse.emf.edit.command.CommandActionDelegate; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.domain.IEditingDomainProvider; import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry; /** * This class is used as a basis for implementing an {@link org.eclipse.jface.action.IAction} * on the menubar, the toolbar, or a pop-up menu by delegating all required * behaviour to a {@link Command}, only when it is guaranteed that the * selection will not change during the life of the action. In other words, * the action itself would be created based on the selection, and destroyed * when the selection changed. All possible aspects of the action are * delegated to the command, namely the enablement state and, if it * implements {@link CommandActionDelegate}, the text, the toolbar icon, and * the tool tip text; however, this need only be done once, at the time the * action is created. * * <p>Subclasses must provide an implementation for {@link #createActionCommand} * that creates the command to perform this action. * They may also override {@link #getDefaultImageDescriptor} to provide a * default icon and {@link #disable} to set the action's state when a command * cannot be created. */ public abstract class StaticSelectionCommandAction extends Action { /** * This records the editing domain of the current editor or viewer. For global * popups, we try to determine the editing domain from the selected * objects themselves. */ protected EditingDomain editingDomain; /** * This records the command. */ protected Command command; /** * This constructs an instance for a command to be executed via * workbenchPart's editing domain. * @since 2.1.0 */ public StaticSelectionCommandAction(IWorkbenchPart workbenchPart) { super(); // try to get editing domain from workbench part if (workbenchPart instanceof IEditingDomainProvider) { editingDomain = ((IEditingDomainProvider)workbenchPart).getEditingDomain(); } } /** * This constructor is simply retained for binary compatibility. It just * calls the {@link #StaticSelectionCommandAction(IWorkbenchPart) new form}. */ public StaticSelectionCommandAction(IEditorPart editorPart) { this((IWorkbenchPart)editorPart); } /** * This constructs an instance for a command to be executed via the given editing domain. * @since 2.4.0 */ public StaticSelectionCommandAction(EditingDomain editingDomain) { this.editingDomain = editingDomain; } /** * This constructs an instance without a specified workbenchPart. */ public StaticSelectionCommandAction() { super(); } /** * This should be implemented to create a command that performs the action. */ protected abstract Command createActionCommand(EditingDomain editingDomain, Collection<?> collection); /** * This extracts the objects from selection, invokes createActionCommand * to create the command, and then configures the action based on the * result. */ public void configureAction(ISelection selection) { // only handle structured selections if (!(selection instanceof IStructuredSelection)) { disable(); } else { // convert the selection to a collection of the selected objects IStructuredSelection sselection = (IStructuredSelection) selection; List<?> list = sselection.toList(); Collection<Object> collection = new ArrayList<Object>(list); // if the editing domain wasn't given by the workbench part, try to get // it from the selection if (editingDomain == null) { for (Object o : collection) { editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(o); if (editingDomain != null) { break; } } } // if we found an editing domain, create command if (editingDomain != null) { command = createActionCommand(editingDomain, collection); setEnabled(command.canExecute()); } // give up if we couldn't create the command; otherwise, use a // CommandActionDelegate to set the action's text, tool-tip, icon, // etc. or just use the default icon if (command == null || command == UnexecutableCommand.INSTANCE) { disable(); } else if (!(command instanceof CommandActionDelegate)) { if (getDefaultImageDescriptor() != null) { setImageDescriptor(getDefaultImageDescriptor()); } } else { CommandActionDelegate commandActionDelegate = (CommandActionDelegate) command; ImageDescriptor imageDescriptor = objectToImageDescriptor(commandActionDelegate.getImage()); if (imageDescriptor != null) { setImageDescriptor(imageDescriptor); } else if (getDefaultImageDescriptor() != null) { setImageDescriptor(getDefaultImageDescriptor()); } if (commandActionDelegate.getText() != null) { setText(commandActionDelegate.getText()); } if (commandActionDelegate.getDescription() != null) { setDescription(commandActionDelegate.getDescription()); } if (commandActionDelegate.getToolTipText() != null) { setToolTipText(commandActionDelegate.getToolTipText()); } } } } /** * This can be overridden to provide the image descriptor used when the * command does not provide one. This implementation simply returns null. */ protected ImageDescriptor getDefaultImageDescriptor() { return null; } /** * This gets invoked when the selection is inappropriate or the command * cannot be created. It puts the action in the correct state for such * error conditions. This implementation disables the action and sets its * icon to the default. */ protected void disable() { setEnabled(false); if (getDefaultImageDescriptor() != null) { setImageDescriptor(getDefaultImageDescriptor()); } } /** * This executes the command. */ @Override public void run() { // this guard is for extra security, but should not be necessary if (editingDomain != null && command != null) { // use up the command editingDomain.getCommandStack().execute(command); } } /** * If necessary, this converts any image representation into an image * descriptor. */ protected ImageDescriptor objectToImageDescriptor(Object object) { return ExtendedImageRegistry.getInstance().getImageDescriptor(object); } }