blob: c269140ea8fa83af44a38c29c813d88e56d75b27 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 University of Illinois at Urbana-Champaign 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:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.rephraserengine.ui.menus;
import java.util.LinkedList;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.rephraserengine.core.refactorings.IEditorRefactoring;
import org.eclipse.rephraserengine.core.refactorings.IResourceRefactoring;
import org.eclipse.rephraserengine.core.resources.IResourceFilter;
import org.eclipse.rephraserengine.internal.ui.actions.RefactoringAction;
import org.eclipse.rephraserengine.ui.WorkbenchSelectionInfo;
import org.eclipse.rephraserengine.ui.refactoring.CustomUserInputPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.internal.Workbench;
import org.eclipse.ui.menus.CommandContributionItem;
/**
* A dynamically-populated set of menu items for the Refactor menu in the menu bar and for various
* pop-up menus.
* <p>
* This class iterates through the contributions to the <i>refactorings</i> extension point and uses
* them to populate the menu.
* <ul>
* <li> When a <i>resourceRefactoring</i> is contributed, if there is some way to get at least one
* {@link IResource} from the current selection in the workbench, then that refactoring is
* shown in the menu.
* <li> When a <i>editorRefactoring<i> is selected, if an editor is active and there is an
* {@link ITextSelection} available from that editor, then that refactoring is
* shown in the menu.
* <li> When a <i>command</i> is contributed, the Eclipse Platform determines how it is displayed,
* whether it is enabled, etc. It is always shown in the menu, but it might be disabled
* depending on the current selection.
* </ul>
*
* @author Jeff Overbey
*
* @since 1.0
*/
@SuppressWarnings("restriction")
public final class RefactorMenu extends CompoundContributionItem
{
private static final String REFACTORING_EXTENSION_POINT_ID = "org.eclipse.rephraserengine.ui.refactoring.refactorings"; //$NON-NLS-1$
private WorkbenchSelectionInfo selection;
@Override
protected IContributionItem[] getContributionItems()
{
selection = new WorkbenchSelectionInfo();
LinkedList<IContributionItem> result = loadRefactoringsFromExtensionPoint();
return fixMenu(result);
}
private IContributionItem[] fixMenu(LinkedList<IContributionItem> result)
{
// The last item in a menu should never be a separator, and there
// should never be two separators in a row (e.g., if this menu is
// followed by another group of commands). Both of those look
// strange, and they can be avoided by never ending the list of
// contribution items with a separator.
if (!result.isEmpty() && result.getLast() instanceof SeparatorContributionItem)
result.removeLast();
// Adds an informative item ("No refactorings available") when
// necessary, since an empty menu looks like a bug.
if (result.isEmpty())
return new IContributionItem[] { new EmptyMenuContributionItem() };
return result.toArray(new IContributionItem[result.size()]);
}
private LinkedList<IContributionItem> loadRefactoringsFromExtensionPoint()
{
return loadRefactoringsFrom(Platform.getExtensionRegistry().getConfigurationElementsFor(REFACTORING_EXTENSION_POINT_ID));
}
private LinkedList<IContributionItem> loadRefactoringsFrom(IConfigurationElement[] configs)
{
LinkedList<IContributionItem> result = new LinkedList<IContributionItem>();
for (IConfigurationElement elt : configs)
{
try
{
processConfigElt(elt, result);
}
catch (CoreException e)
{
e.printStackTrace();
}
}
return result;
}
private void processConfigElt(IConfigurationElement elt, LinkedList<IContributionItem> result)
throws CoreException
{
if (elt.getName().equals("resourceFilter")) //$NON-NLS-1$
{
IResourceFilter resourceFilter = (IResourceFilter)elt.createExecutableExtension("class"); //$NON-NLS-1$
selection = new WorkbenchSelectionInfo(resourceFilter); // since resourceFilter changed
}
else if (elt.getName().equals("group")) //$NON-NLS-1$
{
if (!result.isEmpty() && !(result.getLast() instanceof SeparatorContributionItem))
result.add(new SeparatorContributionItem());
result.addAll(loadRefactoringsFrom(elt.getChildren()));
}
else if (elt.getName().equals("resourceRefactoring")) //$NON-NLS-1$
{
addResourceRefactoring(elt, result);
}
else if (elt.getName().equals("editorRefactoring")) //$NON-NLS-1$
{
addEditorRefactoring(elt, result);
}
else if (elt.getName().equals("command")) //$NON-NLS-1$
{
addCommand(elt, result);
}
}
@SuppressWarnings("rawtypes")
private void addResourceRefactoring(IConfigurationElement elt,
LinkedList<IContributionItem> result) throws CoreException
{
if (selection.someFilesAreSelected())
{
if (elt.getAttribute("class") != null && environmentOK(elt)) //$NON-NLS-1$
{
try
{
IResourceRefactoring refactoring = (IResourceRefactoring)elt.createExecutableExtension("class"); //$NON-NLS-1$
String label = elt.getAttribute("label"); //$NON-NLS-1$
CustomUserInputPage customInputPage =
elt.getAttribute("inputPage") == null //$NON-NLS-1$
? null
: (CustomUserInputPage)elt.createExecutableExtension("inputPage"); //$NON-NLS-1$
result.add(new ResourceRefactoringContributionItem(
refactoring,
label,
customInputPage,
selection));
}
catch (Throwable t)
{
t.printStackTrace();
}
}
else if (elt.getAttribute("command") != null) //$NON-NLS-1$
{
result.add(commandContribution(elt.getAttribute("command"))); //$NON-NLS-1$
}
}
}
@SuppressWarnings("rawtypes")
private void addEditorRefactoring(IConfigurationElement elt,
LinkedList<IContributionItem> result) throws CoreException
{
if (selection.editingAnIFile() && selection.isTextSelectedInEditor())
{
if (elt.getAttribute("class") != null && environmentOK(elt)) //$NON-NLS-1$
{
try
{
IEditorRefactoring refactoring = (IEditorRefactoring)elt.createExecutableExtension("class"); //$NON-NLS-1$
String label = elt.getAttribute("label"); //$NON-NLS-1$
CustomUserInputPage customInputPage =
elt.getAttribute("inputPage") == null //$NON-NLS-1$
? null
: (CustomUserInputPage)elt.createExecutableExtension("inputPage"); //$NON-NLS-1$
result.add(new EditorRefactoringContributionItem(
refactoring,
label,
customInputPage,
selection.getFileInEditor(),
selection.getSelectionInEditor()));
}
catch (Throwable t)
{
t.printStackTrace();
}
}
else if (elt.getAttribute("command") != null) //$NON-NLS-1$
{
result.add(commandContribution(elt.getAttribute("command"))); //$NON-NLS-1$
}
}
}
private boolean environmentOK(IConfigurationElement elt)
{
if (elt.getAttribute("require_env") != null) //$NON-NLS-1$
return System.getenv(elt.getAttribute("require_env")) != null; //$NON-NLS-1$
else
return true;
}
private void addCommand(IConfigurationElement elt, LinkedList<IContributionItem> result)
{
result.add(commandContribution(elt.getAttribute("id"))); //$NON-NLS-1$
}
@SuppressWarnings("deprecation")
private CommandContributionItem commandContribution(String commandID)
{
// CommandContributionItemParameter param = new CommandContributionItemParameter(
// Workbench.getInstance().getServiceLocator(), // Service locator
// null, // ID
// commandID, // Command ID
// CommandContributionItem.STYLE_PUSH); // Style
// return new CommandContributionItem(param);
return new CommandContributionItem(
Workbench.getInstance().getActiveWorkbenchWindow(), // Service locator
null, // ID
commandID, // Command ID
null,
null,
null,
null,
null,
null,
null,
CommandContributionItem.STYLE_PUSH); // Style
}
@SuppressWarnings("rawtypes")
private static class ResourceRefactoringContributionItem extends ContributionItem
{
private IResourceRefactoring refactoring;
private String label;
private CustomUserInputPage customInputPage;
private WorkbenchSelectionInfo selection;
public ResourceRefactoringContributionItem(
IResourceRefactoring refactoring,
String label,
CustomUserInputPage customInputPage,
WorkbenchSelectionInfo selection)
{
this.refactoring = refactoring;
this.label = label != null ? label : refactoring.getName() + "..."; //$NON-NLS-1$
this.customInputPage = customInputPage;
this.selection = selection;
}
@Override public void fill(Menu parent, int index)
{
MenuItem menuItem = new MenuItem(parent, SWT.NONE, index);
menuItem.setText(label);
menuItem.addSelectionListener(new SelectionAdapter()
{
@SuppressWarnings("unchecked")
@Override public void widgetSelected(SelectionEvent e)
{
refactoring.initialize(selection.getAllFilesInSelectedResources());
new RefactoringAction(refactoring, customInputPage).run();
}
});
}
};
@SuppressWarnings("rawtypes")
private static class EditorRefactoringContributionItem extends ContributionItem
{
private IEditorRefactoring refactoring;
private String label;
private CustomUserInputPage customInputPage;
private IFile fileInEditor;
private ITextSelection textSelection;
public EditorRefactoringContributionItem(
IEditorRefactoring refactoring,
String label,
CustomUserInputPage customInputPage,
IFile fileInEditor,
ITextSelection textSelection)
{
this.refactoring = refactoring;
this.label = label != null ? label : refactoring.getName() + "..."; //$NON-NLS-1$
this.customInputPage = customInputPage;
this.fileInEditor = fileInEditor;
this.textSelection = textSelection;
}
@Override public void fill(Menu parent, int index)
{
MenuItem menuItem = new MenuItem(parent, SWT.NONE, index);
menuItem.setText(label);
menuItem.addSelectionListener(new SelectionAdapter()
{
@SuppressWarnings("unchecked")
@Override public void widgetSelected(SelectionEvent e)
{
refactoring.initialize(fileInEditor, textSelection);
new RefactoringAction(refactoring, customInputPage).run();
}
});
}
}
private static class SeparatorContributionItem extends ContributionItem
{
@Override public void fill(Menu parent, int index)
{
new MenuItem(parent, SWT.SEPARATOR, index);
}
};
private static class EmptyMenuContributionItem extends ContributionItem
{
@Override public void fill(Menu parent, int index)
{
MenuItem item = new MenuItem(parent, SWT.NONE, index);
item.setText(Messages.RefactorMenu_NoRefactoringsAvailable);
item.setEnabled(false);
}
};
}