blob: b37775e39db4c366adb5c8406c21e1a08599eff9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 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 Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.ui.javaeditor;
import java.lang.reflect.InvocationTargetException;
import java.util.Comparator;
import com.ibm.icu.text.Collator;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IEditingSupport;
import org.eclipse.jface.text.IEditingSupportRegistry;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.dialogs.FilteredList;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.ui.texteditor.IUpdate;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.search.TypeNameMatch;
import org.eclipse.jdt.internal.corext.codemanipulation.AddImportsOperation;
import org.eclipse.jdt.internal.corext.codemanipulation.AddImportsOperation.IChooseImportQuery;
import org.eclipse.jdt.internal.corext.util.History;
import org.eclipse.jdt.internal.corext.util.QualifiedTypeNameHistory;
import org.eclipse.jdt.ui.IWorkingCopyManager;
import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.actions.ActionUtil;
import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter;
import org.eclipse.jdt.internal.ui.util.ElementValidator;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import org.eclipse.jdt.internal.ui.util.TypeNameMatchLabelProvider;
public class AddImportOnSelectionAction extends Action implements IUpdate {
private static final AddImportComparator ADD_IMPORT_COMPARATOR= new AddImportComparator();
private static final class AddImportComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
if (o1.equals(o2))
return 0;
History<String, String> history= QualifiedTypeNameHistory.getDefault();
int pos1= history.getPosition(o1);
int pos2= history.getPosition(o2);
if (pos1 == pos2)
return Collator.getInstance().compare(o1, o2);
if (pos1 > pos2) {
return -1;
} else {
return 1;
}
}
}
private CompilationUnitEditor fEditor;
public AddImportOnSelectionAction(CompilationUnitEditor editor) {
super(JavaEditorMessages.AddImportOnSelection_label);
setToolTipText(JavaEditorMessages.AddImportOnSelection_tooltip);
setDescription(JavaEditorMessages.AddImportOnSelection_description);
fEditor= editor;
PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.ADD_IMPORT_ON_SELECTION_ACTION);
setEnabled(getCompilationUnit() != null);
}
@Override
public void update() {
setEnabled(fEditor != null && getCompilationUnit() != null);
}
private ICompilationUnit getCompilationUnit () {
if (fEditor == null) {
return null;
}
IWorkingCopyManager manager= JavaPlugin.getDefault().getWorkingCopyManager();
return manager.getWorkingCopy(fEditor.getEditorInput());
}
/*
* @see org.eclipse.jface.action.IAction#run()
*/
@Override
public void run() {
final ICompilationUnit cu= getCompilationUnit();
if (cu == null || fEditor == null)
return;
if (!ElementValidator.checkValidateEdit(cu, getShell(), JavaEditorMessages.AddImportOnSelection_error_title))
return;
if (!ActionUtil.isEditable(fEditor))
return;
ISelection selection= fEditor.getSelectionProvider().getSelection();
if (selection instanceof ITextSelection) {
final ITextSelection textSelection= (ITextSelection) selection;
AddImportOnSelectionAction.SelectTypeQuery query= new SelectTypeQuery(getShell());
AddImportsOperation op= new AddImportsOperation(cu, textSelection.getOffset(), textSelection.getLength(), query, false);
IEditingSupport helper= createViewerHelper(textSelection, query);
try {
registerHelper(helper);
IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
progressService.runInUI(fEditor.getSite().getWorkbenchWindow(), new WorkbenchRunnableAdapter(op, op.getScheduleRule()), op.getScheduleRule());
IStatus status= op.getStatus();
if (!status.isOK()) {
IStatusLineManager manager= getStatusLineManager();
if (manager != null) {
manager.setMessage(status.getMessage());
}
}
} catch (InvocationTargetException e) {
ExceptionHandler.handle(e, getShell(), JavaEditorMessages.AddImportOnSelection_error_title, null);
} catch (InterruptedException e) {
// Do nothing. Operation has been canceled.
} finally {
deregisterHelper(helper);
}
}
}
private IEditingSupport createViewerHelper(final ITextSelection selection, final SelectTypeQuery query) {
return new IEditingSupport() {
@Override
public boolean isOriginator(DocumentEvent event, IRegion subjectRegion) {
return subjectRegion.getOffset() <= selection.getOffset() + selection.getLength() && selection.getOffset() <= subjectRegion.getOffset() + subjectRegion.getLength();
}
@Override
public boolean ownsFocusShell() {
return query.isShowing();
}
};
}
private void registerHelper(IEditingSupport helper) {
ISourceViewer viewer= fEditor.getViewer();
if (viewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer;
registry.register(helper);
}
}
private void deregisterHelper(IEditingSupport helper) {
ISourceViewer viewer= fEditor.getViewer();
if (viewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer;
registry.unregister(helper);
}
}
private Shell getShell() {
return fEditor.getSite().getShell();
}
/**
* Creates a import query that shows a dialog for conflics.
*
* @param shell the parent shell
* @return the created mport query
*/
public static IChooseImportQuery newDialogQuery(Shell shell) {
return new SelectTypeQuery(shell);
}
private static class SelectTypeQuery implements IChooseImportQuery {
private final Shell fShell;
private boolean fIsShowing;
public SelectTypeQuery(Shell shell) {
fShell= shell;
}
@Override
public TypeNameMatch chooseImport(TypeNameMatch[] results, String containerName) {
int nResults= results.length;
if (nResults == 0) {
return null;
} else if (nResults == 1) {
return results[0];
}
if (containerName.length() != 0) {
for (int i= 0; i < nResults; i++) {
TypeNameMatch curr= results[i];
if (containerName.equals(curr.getTypeContainerName())) {
return curr;
}
}
}
fIsShowing= true;
ElementListSelectionDialog dialog= new ElementListSelectionDialog(fShell, new TypeNameMatchLabelProvider(TypeNameMatchLabelProvider.SHOW_FULLYQUALIFIED)) {
@Override
protected FilteredList createFilteredList(Composite parent) {
FilteredList filteredList= super.createFilteredList(parent);
filteredList.setComparator(ADD_IMPORT_COMPARATOR);
return filteredList;
}
};
dialog.setTitle(JavaEditorMessages.AddImportOnSelection_dialog_title);
dialog.setMessage(JavaEditorMessages.AddImportOnSelection_dialog_message);
dialog.setElements(results);
if (dialog.open() == Window.OK) {
fIsShowing= false;
TypeNameMatch result= (TypeNameMatch) dialog.getFirstResult();
QualifiedTypeNameHistory.remember(result.getFullyQualifiedName());
return result;
}
fIsShowing= false;
return null;
}
boolean isShowing() {
return fIsShowing;
}
}
private IStatusLineManager getStatusLineManager() {
return fEditor.getEditorSite().getActionBars().getStatusLineManager();
}
/**
* @return Returns the scheduling rule for this operation
*/
public ISchedulingRule getScheduleRule() {
return ResourcesPlugin.getWorkspace().getRoot();
}
}