/*******************************************************************************
* Copyright © 2000, 2013 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.edt.ide.ui.internal.handlers;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.edt.compiler.core.ast.Name;
import org.eclipse.edt.ide.core.internal.search.PartInfo;
import org.eclipse.edt.ide.core.model.IEGLElement;
import org.eclipse.edt.ide.core.model.IEGLFile;
import org.eclipse.edt.ide.core.model.IEGLProject;
import org.eclipse.edt.ide.core.model.document.IEGLDocument;
import org.eclipse.edt.ide.ui.EDTUIPlugin;
import org.eclipse.edt.ide.ui.internal.UINlsStrings;
import org.eclipse.edt.ide.ui.internal.actions.WorkbenchRunnableAdapter;
import org.eclipse.edt.ide.ui.internal.codemanipulation.AddImportOperation;
import org.eclipse.edt.ide.ui.internal.codemanipulation.OrganizeImportsOperation;
import org.eclipse.edt.ide.ui.internal.codemanipulation.OrganizeImportsOperation.IChooseImportQuery;
import org.eclipse.edt.ide.ui.internal.codemanipulation.OrganizeImportsOperation.SyntaxErrorHelper;
import org.eclipse.edt.ide.ui.internal.dialogs.MultiElementListSelectionDialog;
import org.eclipse.edt.ide.ui.internal.dialogs.ProblemDialog;
import org.eclipse.edt.ide.ui.internal.util.PartInfoLabelProvider;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.operation.IRunnableContext;
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.Region;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.EditorActionBarContributor;
import org.eclipse.ui.progress.IProgressService;
public class AddImportHandler extends EGLHandler {
/** <code>true</code> if the query dialog is showing. */
private boolean fIsQueryShowing= false;
static final class OrganizeImportError extends RuntimeException {
private static final long serialVersionUID= 1L;
}
public void run() {
List eglFiles = getEGLFiles(fSelection);
int selCnt = eglFiles.size();
if(selCnt == 0)
return;
if(selCnt == 1)
{
IEGLFile eglFile = (IEGLFile)(eglFiles.get(0));
runOnSingle(eglFile);
}
else
runOnMultiple(eglFiles);
}
protected void runOnSingle(IEGLFile eglFile)
{
IEditingSupport helper= createViewerHelper();
//EGLOrganizeImportsOperation op = new EGLOrganizeImportsOperation(eglFile, needsave, createChooseImportQuery());
OrganizeImportsOperation op = createOperation(eglFile);
IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
IRunnableContext context= fSite.getWorkbenchWindow();
if (context == null) {
context= progressService;
}
try {
registerHelper(helper);
progressService.runInUI(context, new WorkbenchRunnableAdapter(op, op.getScheduleRule()), op.getScheduleRule());
postRun(op);
}catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
} finally {
deregisterHelper(helper);
}
}
protected void registerHelper(IEditingSupport helper) {
if (fEditor == null)
return;
ISourceViewer viewer= fEditor.getViewer();
if (viewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer;
registry.register(helper);
}
}
protected void postRun(OrganizeImportsOperation op) {
if(op instanceof AddImportOperation)
{
AddImportOperation addOp = (AddImportOperation)op;
IStatus status = addOp.getStatus();
if(!status.isOK())
setStatusBarMessage(status.getMessage());
}
}
protected void setStatusBarMessage(String message) {
IEditorActionBarContributor contributor= fEditor.getEditorSite().getActionBarContributor();
if (contributor instanceof EditorActionBarContributor) {
IStatusLineManager manager= ((EditorActionBarContributor) contributor).getActionBars().getStatusLineManager();
manager.setMessage(message);
}
}
private String getOrganizeSummary(OrganizeImportsOperation op) {
int nImportsAdded= op.getNumberOfImportsAdded();
int nImportsRemoved = op.getNumberOfImportsRemoved();
String[] args = {String.valueOf(nImportsAdded), String.valueOf(nImportsRemoved)};
return MessageFormat.format(UINlsStrings.OrganizeImportsAction_summary, args);
}
protected void deregisterHelper(IEditingSupport helper) {
if (fEditor == null)
return;
ISourceViewer viewer= fEditor.getViewer();
if (viewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry= (IEditingSupportRegistry) viewer;
registry.unregister(helper);
}
}
protected IEditingSupport createViewerHelper() {
return new IEditingSupport() {
public boolean isOriginator(DocumentEvent event, IRegion subjectRegion) {
return true; // assume true, since we only register while we are active
}
public boolean ownsFocusShell() {
return fIsQueryShowing;
}
};
}
protected OrganizeImportsOperation createOperation(IEGLFile eglFile)
{
ISelection selectedText = fEditor.getSelectionProvider().getSelection();
IEGLDocument egldoc = (IEGLDocument)(fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()));
if(selectedText instanceof ITextSelection && egldoc != null)
{
final ITextSelection textSelection= (ITextSelection) selectedText;
int selOffset = textSelection.getOffset();
int selLen = textSelection.getLength();
return new AddImportOperation(eglFile, egldoc, selOffset, selLen, false, createChooseImportQuery());
}
else
return null;
}
protected IChooseImportQuery createChooseImportQuery() {
return new IChooseImportQuery() {
public PartInfo[] chooseImports(Map /*<Name>, <List of <PartInfo> >*/mapOpenChoices) {
int cnt = mapOpenChoices.size();
ArrayList openChoices = new ArrayList(cnt);
ArrayList regionList = new ArrayList(cnt);
Set keys = mapOpenChoices.keySet();
Iterator it = keys.iterator();
while(it.hasNext())
{
Name unrevoledTypeName = (Name)(it.next());
List partInfos = (List)(mapOpenChoices.get(unrevoledTypeName));
Region region = new Region(unrevoledTypeName.getOffset(), unrevoledTypeName.getLength());
regionList.add(region);
//conver partInfos to array
int choicesPerPartCnt = partInfos.size();
PartInfo[] openChoice = (PartInfo[]) partInfos.toArray(new PartInfo[choicesPerPartCnt]);
openChoices.add(openChoice);
}
PartInfo[][] chooseImportChoices = (PartInfo[][])openChoices.toArray(new PartInfo[openChoices.size()][]);
IRegion[] regions = (IRegion[])regionList.toArray(new IRegion[regionList.size()]);
return doChooseImports(chooseImportChoices, regions);
}
};
}
protected PartInfo[] doChooseImports(PartInfo[][] openChoices, final IRegion[] ranges) {
// remember selection
ISelection sel= fEditor != null ? fEditor.getSelectionProvider().getSelection() : null;
PartInfo[] result= null;
ILabelProvider labelProvider= new PartInfoLabelProvider(PartInfoLabelProvider.SHOW_FULLYQUALIFIED);
MultiElementListSelectionDialog dialog= new MultiElementListSelectionDialog(fSite.getShell(), labelProvider) {
protected void handleSelectionChanged() {
super.handleSelectionChanged();
// show choices in editor
doListSelectionChanged(getCurrentPage(), ranges);
}
};
fIsQueryShowing= true;
dialog.setTitle(UINlsStrings.OrganizeImportsAction_selectiondialog_title);
dialog.setMessage(UINlsStrings.OrganizeImportsAction_selectiondialog_message);
dialog.setElements(openChoices);
if (dialog.open() == Window.OK) {
Object[] res= dialog.getResult();
result= new PartInfo[res.length];
for (int i= 0; i < res.length; i++) {
Object[] array= (Object[]) res[i];
if (array.length > 0)
result[i]= (PartInfo) array[0];
}
}
// restore selection
if (sel instanceof ITextSelection) {
ITextSelection textSelection= (ITextSelection) sel;
fEditor.selectAndReveal(textSelection.getOffset(), textSelection.getLength());
}
fIsQueryShowing= false;
return result;
}
protected void doListSelectionChanged(int page, IRegion[] ranges) {
if (fEditor != null && ranges != null && page >= 0 && page < ranges.length) {
IRegion range= ranges[page];
fEditor.selectAndReveal(range.getOffset(), range.getLength());
}
}
private void runOnMultiple(final List eglFiles)
{
String message= UINlsStrings.OrganizeImportsAction_status_description; //$NON-NLS-1$
final MultiStatus status= new MultiStatus(EDTUIPlugin.PLUGIN_ID, IStatus.OK, message, null);
IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
try {
progressService.run(true, true, new WorkbenchRunnableAdapter(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor){
doRunOnMultiple(eglFiles, status, monitor);
}
}));
if(!status.isOK())
{
String title = UINlsStrings.OrganizeImportsAction_status_title;
ProblemDialog.open(fSite.getShell(), title, null, status);
}
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
//cancel by user
} //workspace lock
/* ISchedulingRule rule = modifyRule(eglFiles);
String Jobtitle = EGLUINlsStrings.OrganizeImportsAction_op_description;
WorkspaceJob job = new WorkspaceJob(Jobtitle) {
(non-Javadoc)
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
doRunOnMultiple(eglFiles, status, monitor);
if(isModal(this))
{
//the progress dialog is still open so just open the message
showResults();
}
else
{
//setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE);
//setProperty(IProgressConstants.ACTION_PROPERTY, getOrganizeUsedFormsCompeletedAction());
}
return status;
}
};
job.setRule(rule);
job.setUser(true);
job.schedule();
*/
}
private void doRunOnMultiple(List eglfiles, MultiStatus status, IProgressMonitor monitor) throws OperationCanceledException
{
if(monitor == null)
monitor = new NullProgressMonitor();
monitor.setTaskName(UINlsStrings.OrganizeImportsAction_op_description);
int size = eglfiles.size();
monitor.beginTask("", size); //$NON-NLS-1$
IChooseImportQuery query= new IChooseImportQuery() {
public PartInfo[] chooseImports(Map mapOpenChoices) {
throw new OrganizeImportError();
}
};
try{
for(int i=0; i<size; i++)
{
IEGLFile eglfile = (IEGLFile)(eglfiles.get(i));
String fileLocation = eglfile.getPath().makeRelative().toString();
if(testOnEGLPath(eglfile, fileLocation, status))
{
monitor.subTask(fileLocation);
boolean needsave = ((Boolean)(fileNeedsSave.get(eglfile))).booleanValue();
OrganizeImportsOperation op = new OrganizeImportsOperation(eglfile, needsave, query);
/* try
{
op.run(new SubProgressMonitor(monitor, 1));
} catch (CoreException e) {
e.printStackTrace();
String message = EGLUINlsStrings.OrganizeAction_error_unexpected;
status.add(new Status(IStatus.ERROR, EGLUIPlugin.PLUGIN_ID, IStatus.ERROR, message, e));
}
*/
runInSync(op, status, fileLocation, monitor);
SyntaxErrorHelper syntaxErr = op.getSyntaxError();
if(syntaxErr != null)
{
String msg = MessageFormat.format(UINlsStrings.OrganizeAction_error_syntax, new String[]{fileLocation});
status.add(new Status(IStatus.INFO, EDTUIPlugin.PLUGIN_ID, IStatus.ERROR, msg, null));
}
if(monitor.isCanceled())
throw new OperationCanceledException();
}
}
}
finally
{
monitor.done();
}
}
private boolean testOnEGLPath(IEGLElement eglelem, String fileLocation, MultiStatus status){
IEGLProject eglProj = eglelem.getEGLProject();
if(!eglProj.isOnEGLPath(eglelem))
{
String message = MessageFormat.format(UINlsStrings.OrganizeImportsAction_multi_error_notoncp, new String[]{fileLocation});
status.add(new Status(IStatus.INFO, EDTUIPlugin.PLUGIN_ID, IStatus.ERROR, message, null));
return false;
}
return true;
}
private void runInSync(final OrganizeImportsOperation op, final MultiStatus status, final String fileLocation, final IProgressMonitor monitor)
{
Runnable runnable = new Runnable() {
public void run(){
try
{
op.run(new SubProgressMonitor(monitor, 1));
}
catch (CoreException e) {
e.printStackTrace();
String message = UINlsStrings.OrganizeAction_error_unexpected;
status.add(new Status(IStatus.ERROR, EDTUIPlugin.PLUGIN_ID, IStatus.ERROR, message, e));
}
catch (OrganizeImportError e){
String[] args = {fileLocation};
String message = MessageFormat.format(UINlsStrings.OrganizeImportsAction_multi_error_unresolvable, args);
status.add(new Status(IStatus.INFO, EDTUIPlugin.PLUGIN_ID, IStatus.ERROR, message, e));
}
catch (OperationCanceledException e)
{
//Canceled
monitor.setCanceled(true);
}
}
};
fSite.getShell().getDisplay().syncExec(runnable);
}
public void update() {
// TODO Auto-generated method stub
}
}