blob: 19689cbbdd9347a0d0e67d479edd2ab2482d50bd [file] [log] [blame]
package org.eclipse.ui.internal.incubator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.NotEnabledException;
import org.eclipse.core.commands.NotHandledException;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.LegacyActionTools;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.SubContributionItem;
import org.eclipse.jface.bindings.Binding;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.IPreferenceNode;
import org.eclipse.jface.preference.IPreferencePage;
import org.eclipse.jface.preference.PreferenceManager;
import org.eclipse.jface.preference.PreferenceNode;
import org.eclipse.jface.resource.DeviceResourceException;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreePathViewerSorter;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
import org.eclipse.ui.internal.WorkbenchImages;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.WorkbenchWindow;
import org.eclipse.ui.internal.actions.NewWizardShortcutAction;
import org.eclipse.ui.internal.dialogs.WorkbenchPreferenceDialog;
import org.eclipse.ui.internal.keys.BindingService;
import org.eclipse.ui.internal.progress.ProgressManagerUtil;
import org.eclipse.ui.keys.IBindingService;
import org.eclipse.ui.views.IViewDescriptor;
import org.eclipse.ui.wizards.IWizardCategory;
import org.eclipse.ui.wizards.IWizardDescriptor;
/**
* Experimental Action for search-based navigation to UI elements such as
* editors, views, commands.
*
*/
public class CtrlEAction extends AbstractHandler {
private static final String DIRTY_MARK = "*"; //$NON-NLS-1$
private IWorkbenchWindow window;
protected String rememberedText;
protected Map previousPicksMap = new HashMap();
private LinkedList previousPicksList = new LinkedList();
/**
* The constructor.
*/
public CtrlEAction() {
}
public Object execute(ExecutionEvent executionEvent) {
// need to get commands here because opening the popup changes which
// commands are "handled"
BindingService bindingService = (BindingService) PlatformUI
.getWorkbench().getService(IBindingService.class);
Binding[] bindings = bindingService.getBindings();
SortedSet commands = new TreeSet();
for (int i = 0; i < bindings.length; i++) {
Binding binding = bindings[i];
ParameterizedCommand command = binding.getParameterizedCommand();
if (command != null && command.getCommand().isHandled()) {
commands.add(command);
}
}
window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (window == null) {
return null;
}
FilteringInfoPopup popup = new MyInfoPopup(ProgressManagerUtil.getDefaultParent(), commands);
popup.setInput(new Object());
TreeItem[] rootItems = ((Tree) popup.getTreeViewer().getControl())
.getItems();
if (rootItems.length > 0)
((Tree) popup.getTreeViewer().getControl())
.setTopItem(rootItems[0]);
popup.open();
return null;
}
private final static class QuickAccessTreeSorter extends
TreePathViewerSorter {
public int compare(Viewer viewer, Object e1, Object e2) {
ILabelProvider labelProvider = (ILabelProvider) ((TreeViewer) viewer)
.getLabelProvider();
String name1 = stripDirtyIndicator(labelProvider.getText(e1));
String name2 = stripDirtyIndicator(labelProvider.getText(e2));
return getComparator().compare(name1, name2);
}
public void sort(Viewer viewer, TreePath parentPath, Object[] elements) {
if (parentPath == null) {
return;
}
Object parent = parentPath.getLastSegment();
if (parent instanceof Node) {
Node node = (Node) parent;
// TODO replace with a proper check
if (node.name.equals(IncubatorMessages.CtrlEAction_Previous)) {
return;
}
}
super.sort(viewer, parentPath, elements);
}
}
/**
* @since 3.2
*
*/
private final class MyInfoPopup extends FilteringInfoPopup {
private SortedSet commands;
/**
* @param shell
* @param commands
*/
public MyInfoPopup(Shell shell, SortedSet commands) {
super(shell, SWT.RESIZE, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE,
false);
MyInfoPopup.this.commands = commands;
getTreeViewer().setContentProvider(
new MyContentProvider(MyInfoPopup.this.commands));
}
protected TreeViewer createTreeViewer(Composite parent, int style) {
TreeViewer viewer = new TreeViewer(parent, style);
viewer.setLabelProvider(new MyLabelProvider());
viewer.setComparator(new QuickAccessTreeSorter());
return viewer;
}
protected void selectFirstMatch() {
String text = getFilterText().getText();
Object element = previousPicksMap.get(text);
if (element != null) {
getTreeViewer().setSelection(new StructuredSelection(element),
true);
return;
}
super.selectFirstMatch();
}
protected String getMatchName(Object element) {
String name = ((ILabelProvider) getTreeViewer().getLabelProvider()).getText(element);
return stripDirtyIndicator(name);
}
protected Point getInitialSize() {
if (!MyInfoPopup.this.getPersistBounds()) {
return new Point(300, 400);
}
return super.getInitialSize();
}
protected Point getInitialLocation(Point initialSize) {
if (!MyInfoPopup.this.getPersistBounds()) {
Point size = new Point(300, 400);
Rectangle parentBounds = MyInfoPopup.this.getParentShell()
.getBounds();
int x = parentBounds.x + parentBounds.width / 2 - size.x / 2;
int y = parentBounds.y + parentBounds.height / 2 - size.y / 2;
return new Point(x, y);
}
return super.getInitialLocation(initialSize);
}
protected IDialogSettings getDialogSettings() {
String sectionName = getId();
IDialogSettings settings = WorkbenchPlugin.getDefault()
.getDialogSettings();
if (settings == null) {
settings = WorkbenchPlugin.getDefault().getDialogSettings()
.addNewSection(sectionName);
}
return settings;
}
protected String getId() {
return "org.eclipse.ui.internal.incubator.ctrlE"; //$NON-NLS-1$
}
public boolean close() {
rememberedText = getFilterText().getText();
return super.close();
}
protected void handleElementSelected(Object selectedElement) {
addPreviousPick(selectedElement);
IWorkbenchPage activePage = window.getActivePage();
if (activePage != null) {
if (selectedElement instanceof IViewDescriptor) {
IViewDescriptor viewDescriptor = (IViewDescriptor) selectedElement;
try {
activePage.showView(viewDescriptor.getId());
return;
} catch (PartInitException e) {
}
}
if (selectedElement instanceof IPerspectiveDescriptor) {
IPerspectiveDescriptor perspectiveDescriptor = (IPerspectiveDescriptor) selectedElement;
activePage.setPerspective(perspectiveDescriptor);
}
if (selectedElement instanceof IEditorReference) {
IEditorReference editorReference = (IEditorReference) selectedElement;
IWorkbenchPart part = editorReference.getPart(true);
if (part != null) {
activePage.activate(part);
}
return;
}
if (selectedElement instanceof PreferenceNode) {
PreferenceNode preferenceNode = (PreferenceNode) selectedElement;
WorkbenchPreferenceDialog dialog = WorkbenchPreferenceDialog
.createDialogOn(window.getShell(), preferenceNode
.getId());
dialog.open();
return;
}
if (selectedElement instanceof IWizardDescriptor) {
IWizardDescriptor wizardDescriptor = (IWizardDescriptor) selectedElement;
NewWizardShortcutAction wizardAction = new NewWizardShortcutAction(
window, wizardDescriptor);
wizardAction.run();
return;
}
if (selectedElement instanceof ParameterizedCommand) {
IHandlerService handlerService = (IHandlerService) window
.getWorkbench().getService(IHandlerService.class);
ParameterizedCommand command = (ParameterizedCommand) selectedElement;
try {
handlerService.executeCommand(command, null);
} catch (ExecutionException e) {
e.printStackTrace();
} catch (NotDefinedException e) {
e.printStackTrace();
} catch (NotEnabledException e) {
e.printStackTrace();
} catch (NotHandledException e) {
e.printStackTrace();
}
return;
}
if (selectedElement instanceof ActionContributionItem) {
ActionContributionItem item = (ActionContributionItem) selectedElement;
item.getAction().run();
return;
}
}
}
public void setInput(Object information) {
getTreeViewer().setAutoExpandLevel(2);
getTreeViewer().setInput(information);
}
}
private static class Node {
private String name;
private String imageId;
Node(String name, String imageId) {
this.name = name;
this.imageId = imageId;
}
public String toString() {
return name;
}
/**
* @return
*/
public String getImageId() {
return imageId;
}
}
private final class MyContentProvider implements ITreeContentProvider {
private Object input;
private Node previousNode = new Node(
IncubatorMessages.CtrlEAction_Previous, IWorkbenchGraphicConstants.IMG_OBJ_NODE);
private Node editorNode = new Node(
IncubatorMessages.CtrlEAction_Editors, IWorkbenchGraphicConstants.IMG_OBJ_NODE);
private Node viewNode = new Node(IncubatorMessages.CtrlEAction_Views,
IWorkbenchGraphicConstants.IMG_VIEW_DEFAULTVIEW_MISC);
private Node perspectiveNode = new Node(
IncubatorMessages.CtrlEAction_Perspectives,
IWorkbenchGraphicConstants.IMG_ETOOL_DEF_PERSPECTIVE);
private Node commandNode = new Node(
IncubatorMessages.CtrlEAction_Commands, IWorkbenchGraphicConstants.IMG_OBJ_NODE);
private Node menusNode = new Node(IncubatorMessages.CtrlEAction_Menus,
IWorkbenchGraphicConstants.IMG_OBJ_NODE);
private Node newNode = new Node(IncubatorMessages.CtrlEAction_New, IWorkbenchGraphicConstants.IMG_OBJ_NODE);
private Node preferencesNode = new Node(
IncubatorMessages.CtrlEAction_Preferences, IWorkbenchGraphicConstants.IMG_OBJ_NODE);
private SortedSet commands;
/**
* @param commands
*/
public MyContentProvider(SortedSet commands) {
MyContentProvider.this.commands = commands;
}
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof Node) {
if (previousNode.equals(parentElement)) {
return getPreviousPicks();
} else if (editorNode.equals(parentElement)) {
if(window.getActivePage() != null) {
return window.getActivePage().getEditorReferences();
}
} else if (viewNode.equals(parentElement)) {
return PlatformUI.getWorkbench().getViewRegistry()
.getViews();
} else if (perspectiveNode.equals(parentElement)) {
return PlatformUI.getWorkbench().getPerspectiveRegistry()
.getPerspectives();
} else if (commandNode.equals(parentElement)) {
return commands.toArray();
} else if (preferencesNode.equals(parentElement)) {
List elements = PlatformUI.getWorkbench()
.getPreferenceManager().getElements(
PreferenceManager.PRE_ORDER);
Set uniqueElements = new LinkedHashSet(elements);
return uniqueElements.toArray();
} else if (menusNode.equals(parentElement)) {
MenuManager menu = ((WorkbenchWindow) window)
.getMenuBarManager();
Set result = new HashSet();
collectContributions(menu, result);
return result.toArray();
} else if (newNode.equals(parentElement)) {
IWizardCategory rootCategory = WorkbenchPlugin.getDefault()
.getNewWizardRegistry().getRootCategory();
List result = new ArrayList();
collectWizards(rootCategory, result);
return result.toArray();
}
}
if (parentElement == input) {
return new Node[] { previousNode, editorNode, viewNode,
perspectiveNode, commandNode, menusNode, newNode,
preferencesNode };
}
return new Object[0];
}
private void collectContributions(MenuManager menu, Set result) {
IContributionItem[] items = menu.getItems();
for (int i = 0; i < items.length; i++) {
IContributionItem item = items[i];
if (item instanceof SubContributionItem) {
item = ((SubContributionItem) item).getInnerItem();
}
if (item instanceof MenuManager) {
collectContributions((MenuManager) item, result);
} else if (item instanceof ActionContributionItem) {
result.add(item);
}
}
}
private void collectWizards(IWizardCategory category, List result) {
result.addAll(Arrays.asList(category.getWizards()));
IWizardCategory[] childCategories = category.getCategories();
for (int i = 0; i < childCategories.length; i++) {
collectWizards(childCategories[i], result);
}
}
public Object getParent(Object element) {
return null;
}
public boolean hasChildren(Object element) {
return getChildren(element).length > 0;
}
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
this.input = newInput;
}
}
private static final class MyLabelProvider extends LabelProvider {
private LocalResourceManager resourceManager = new LocalResourceManager(
JFaceResources.getResources());
public Image getImage(Object element) {
Image image = null;
if (element instanceof Node) {
Node node = (Node) element;
image = findOrCreateImage(WorkbenchImages
.getImageDescriptor(node.getImageId()));
}
else if (element instanceof IEditorReference) {
IEditorReference editorReference = (IEditorReference) element;
image = editorReference.getTitleImage();
}
else if (element instanceof IViewDescriptor) {
IViewDescriptor viewDescriptor = (IViewDescriptor) element;
image = findOrCreateImage(viewDescriptor.getImageDescriptor());
}
else if (element instanceof IPerspectiveDescriptor) {
IPerspectiveDescriptor perspectiveDescriptor = (IPerspectiveDescriptor) element;
image = findOrCreateImage(perspectiveDescriptor
.getImageDescriptor());
}
else if (element instanceof IPreferenceNode) {
IPreferenceNode preferenceNode = (IPreferenceNode) element;
image = preferenceNode.getLabelImage();
}
else if (element instanceof IWizardDescriptor) {
IWizardDescriptor wizardDescriptor = (IWizardDescriptor) element;
image = findOrCreateImage(wizardDescriptor.getDescriptionImage());
}
if (image == null) {
image = WorkbenchImages.getImage(IWorkbenchGraphicConstants.IMG_OBJ_ELEMENT);
}
return image;
}
/**
* @param imageDescriptor
* @return image, or null
* @throws DeviceResourceException
*/
private Image findOrCreateImage(ImageDescriptor imageDescriptor) {
if (imageDescriptor == null) {
return null;
}
Image image = (Image) resourceManager.find(imageDescriptor);
if (image == null) {
try {
image = resourceManager.createImage(imageDescriptor);
} catch (DeviceResourceException e) {
WorkbenchPlugin.log(e);
}
}
return image;
}
public void dispose() {
resourceManager.dispose();
resourceManager = null;
super.dispose();
}
public String getText(Object element) {
String separator = " - "; //$NON-NLS-1$
if (element instanceof IEditorReference) {
IEditorReference editorReference = (IEditorReference) element;
StringBuffer result = new StringBuffer();
if (editorReference.isDirty()) {
result.append(DIRTY_MARK);
}
result.append(editorReference.getName());
result.append(separator);
result.append(editorReference.getTitleToolTip());
return result.toString();
}
if (element instanceof IViewDescriptor) {
IViewDescriptor viewDescriptor = (IViewDescriptor) element;
return viewDescriptor.getLabel();
}
if (element instanceof IPerspectiveDescriptor) {
IPerspectiveDescriptor perspectiveDescriptor = (IPerspectiveDescriptor) element;
return perspectiveDescriptor.getLabel();
}
if (element instanceof IPreferenceNode) {
IPreferenceNode preferenceNode = (IPreferenceNode) element;
IPreferencePage page = preferenceNode.getPage();
if (page != null && page.getDescription() != null
&& page.getDescription().length() != 0) {
return preferenceNode.getLabelText() + separator
+ page.getDescription();
}
return preferenceNode.getLabelText();
}
if (element instanceof IWizardDescriptor) {
IWizardDescriptor wizardDescriptor = (IWizardDescriptor) element;
return wizardDescriptor.getLabel() + separator
+ wizardDescriptor.getDescription();
}
if (element instanceof ActionContributionItem) {
ActionContributionItem item = (ActionContributionItem) element;
IAction action = item.getAction();
if (action.getToolTipText() != null
&& action.getToolTipText().length() != 0) {
return LegacyActionTools.removeMnemonics(action.getText())
+ separator + action.getToolTipText();
}
return LegacyActionTools.removeMnemonics(action.getText());
}
if (element instanceof ParameterizedCommand) {
ParameterizedCommand command = (ParameterizedCommand) element;
try {
Command nestedCommand = command.getCommand();
if (nestedCommand != null
&& nestedCommand.getDescription() != null
&& nestedCommand.getDescription().length() != 0) {
return command.getName() + separator
+ nestedCommand.getDescription();
}
return command.getName();
} catch (NotDefinedException e) {
return command.toString();
}
}
return super.getText(element);
}
}
/**
* @param element
*/
private void addPreviousPick(Object element) {
previousPicksList.remove(element);
previousPicksList.addFirst(element);
previousPicksMap.put(rememberedText, element);
}
/**
* @return
*/
private Object[] getPreviousPicks() {
return previousPicksList.toArray();
}
private static String stripDirtyIndicator(String elementName) {
if (elementName.startsWith(DIRTY_MARK)) {
elementName = elementName.substring(1);
}
return elementName;
}
}