/**
* 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() {
}
}
}