/** * Copyright (c) Red Hat, Inc., contributors and others 2013 - 2014. All rights reserved * * Licensed under the Eclipse Public License version 1.0, available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jboss.tools.forge.ui.internal.ext.dialog; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.dialogs.PopupDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.ISelectionService; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.ide.FileStoreEditorInput; import org.eclipse.ui.part.FileEditorInput; import org.jboss.forge.addon.ui.command.UICommand; import org.jboss.forge.addon.ui.context.UIContext; import org.jboss.forge.addon.ui.metadata.UICategory; import org.jboss.forge.addon.ui.util.Categories; import org.jboss.tools.forge.core.furnace.FurnaceRuntime; import org.jboss.tools.forge.core.furnace.FurnaceService; import org.jboss.tools.forge.ui.internal.ForgeUIPlugin; import org.jboss.tools.forge.ui.internal.ext.context.UISelectionImpl; import org.jboss.tools.forge.ui.internal.ext.quickaccess.QuickAccessContents; import org.jboss.tools.forge.ui.internal.ext.quickaccess.QuickAccessElement; import org.jboss.tools.forge.ui.internal.ext.quickaccess.QuickAccessProvider; import org.jboss.tools.forge.ui.internal.ext.quickaccess.impl.ForgeQuickAccessElement; import org.jboss.tools.forge.ui.internal.ext.quickaccess.impl.ForgeQuickAccessProvider; import org.jboss.tools.forge.ui.internal.part.ForgeConsoleView; import org.jboss.tools.forge.ui.notifications.NotificationType; public class UICommandListDialog extends PopupDialog { private final WizardDialogHelper wizardHelper; private static final int MAXIMUM_NUMBER_OF_ELEMENTS = 5; // TODO: when would this list be cleaned up? private static final LinkedList<QuickAccessElement> PREVIOUS_CHOICES_LIST = new LinkedList<>(); public UICommandListDialog(IWorkbenchWindow window) { super(window.getShell(), SWT.RESIZE, true, true, // persist size false, // but not location true, true, "Run a Forge command", "JBoss Forge v." + FurnaceRuntime.INSTANCE.getVersion() + " - Start typing to filter the list"); IStructuredSelection currentSelection = getCurrentSelection(window); ITextSelection textSelection = getTextSelection(window); wizardHelper = new WizardDialogHelper(getParentShell(), currentSelection, textSelection); UISelectionImpl<?> uiSelection = wizardHelper.getContext().getInitialSelection(); if (!uiSelection.isEmpty()) { String currentSelectionLabel; IResource resource = uiSelection.getResource(); if (resource != null) { currentSelectionLabel = resource.getFullPath().toOSString(); } else { currentSelectionLabel = uiSelection.get().toString(); } setTitleText("Current Selection: " + currentSelectionLabel); } } public static ITextSelection getTextSelection(IWorkbenchWindow window) { ISelectionService selectionService = window.getSelectionService(); ISelection selection = selectionService.getSelection(); if (selection instanceof ITextSelection) { return (ITextSelection) selection; } else { return null; } } public static IStructuredSelection getCurrentSelection(IWorkbenchWindow window) { ISelectionService selectionService = window.getSelectionService(); ISelection selection = selectionService.getSelection(); IStructuredSelection currentSelection = null; if (selection instanceof TreeSelection) { currentSelection = (TreeSelection) selection; } else { Object activeEditorFile = getActiveEditorInput(window); if (activeEditorFile != null) { currentSelection = new StructuredSelection(activeEditorFile); } } if (currentSelection == null) { // Try to get from Package Explorer currentSelection = (IStructuredSelection) selectionService.getSelection(JavaUI.ID_PACKAGES); } if (currentSelection == null) { // Try to get from Project Explorer currentSelection = (IStructuredSelection) selectionService.getSelection(IPageLayout.ID_PROJECT_EXPLORER); } if (currentSelection == null) { // Try to get from Navigator View currentSelection = (IStructuredSelection) selectionService .getSelection("org.eclipse.ui.views.ResourceNavigator"); } return currentSelection; } /** * Retrieves the {@link IFile} represented by the active editor */ private static Object getActiveEditorInput(IWorkbenchWindow window) { IWorkbenchPage page = window.getActivePage(); if (page != null) { IEditorPart editor = page.getActiveEditor(); if (editor != null) { return extractFile(editor); } else { IWorkbenchPart part = page.getActivePart(); if (part instanceof ForgeConsoleView) { return ((ForgeConsoleView) part).getConsole().getCurrentResource(); } } } return null; } private static Object extractFile(IEditorPart editor) { IEditorInput editorInput = editor.getEditorInput(); if (editorInput != null) { FileEditorInput fileEditorInput = editorInput.getAdapter(FileEditorInput.class); if (fileEditorInput != null) { return fileEditorInput.getFile(); } FileStoreEditorInput fileStoreEditorInput = editorInput.getAdapter(FileStoreEditorInput.class); if (fileStoreEditorInput != null) { return new File(fileStoreEditorInput.getURI()); } } return null; } @Override protected Color getBackground() { return getShell().getDisplay().getSystemColor(SWT.COLOR_WHITE); } @Override protected Color getForeground() { return getShell().getDisplay().getSystemColor(SWT.COLOR_BLACK); } @Override protected Point getDefaultSize() { return new Point(640, 480); } @Override protected Control createDialogArea(Composite parent) { final Composite result = (Composite) super.createDialogArea(parent); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.verticalSpacing = 9; result.setLayout(layout); final Text text = new Text(result, SWT.SEARCH | SWT.ICON_SEARCH); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { @Override public void run() { try { FurnaceService.INSTANCE.waitUntilContainerIsStarted(); } catch (InterruptedException ie) { ForgeUIPlugin.log(ie); return; } final QuickAccessProvider[] providers; try { providers = getProviders(); } catch (Exception e) { ForgeUIPlugin.log(e); ForgeUIPlugin.displayMessage("Error has occurred. See Error Log for details", e.getMessage(), NotificationType.ERROR); return; } QuickAccessContents quickAccessContents = new QuickAccessContents(providers) { @Override public void updateFeedback(boolean filterTextEmpty, boolean showAllMatches) { } @Override public void doClose() { close(); } @Override public QuickAccessElement getPerfectMatch(String filter) { for (QuickAccessProvider provider : providers) { QuickAccessElement elem = provider.getElementForId(filter); if (elem != null) { return elem; } } return null; } @Override public void handleElementSelected(String textStr, Object selectedElement) { if (selectedElement instanceof ForgeQuickAccessElement) { ForgeQuickAccessElement element = (ForgeQuickAccessElement) selectedElement; addPreviousChoice(element); wizardHelper.openWizard(element.getLabel(), element.getCommand()); } } }; quickAccessContents.hookFilterText(text); quickAccessContents.createTable(result, Window.getDefaultOrientation()); quickAccessContents.toggleShowAllMatches(); text.setFocus(); } }); return result; } /** * Returns each provider by a category */ private QuickAccessProvider[] getProviders() { List<QuickAccessProvider> allProviders = new ArrayList<>(); Collection<QuickAccessElement> allElements = new HashSet<>(); Map<String, List<UICommand>> categories = new TreeMap<>(); for (UICommand command : wizardHelper.getAllCandidatesAsList()) { String categoryName = getCategoryName(wizardHelper.getContext(), command); List<UICommand> list = categories.get(categoryName); if (list == null) { list = new ArrayList<>(); categories.put(categoryName, list); } list.add(command); } // Create Providers for each category Set<ForgeQuickAccessProvider> providers = new TreeSet<>(); for (Entry<String, List<UICommand>> entry : categories.entrySet()) { ForgeQuickAccessProvider provider = new ForgeQuickAccessProvider(entry.getKey(), wizardHelper.getContext(), entry.getValue(), PREVIOUS_CHOICES_LIST, allElements); providers.add(provider); } // In case a command is unavailable, remove from previous choices list PREVIOUS_CHOICES_LIST.retainAll(allElements); // Add PreviousChoicesProvider allProviders.add(new PreviousChoicesProvider()); allProviders.addAll(providers); return allProviders.toArray(new QuickAccessProvider[allProviders.size()]); } private String getCategoryName(UIContext context, UICommand command) { UICategory category = command.getMetadata(context).getCategory(); if (category == null) { category = Categories.createDefault(); } return category.toString(); } private void addPreviousChoice(QuickAccessElement element) { PREVIOUS_CHOICES_LIST.remove(element); if (PREVIOUS_CHOICES_LIST.size() == MAXIMUM_NUMBER_OF_ELEMENTS) { PREVIOUS_CHOICES_LIST.removeLast(); } PREVIOUS_CHOICES_LIST.addFirst(element); } private class PreviousChoicesProvider extends QuickAccessProvider { @Override public String getId() { return "org.jboss.tools.forge.ui.previousChoices"; } @Override public String getName() { return "Previous Choices"; } @Override public ImageDescriptor getImageDescriptor() { return ForgeUIPlugin.getForgeIcon(); } @Override public List<QuickAccessElement> getElements() { return PREVIOUS_CHOICES_LIST; } @Override public List<QuickAccessElement> getElementsSorted() { return PREVIOUS_CHOICES_LIST; } @Override public QuickAccessElement getElementForId(String id) { return null; } @Override protected void doReset() { } } }