/*******************************************************************************
* Copyright (c) 2008, 2009 Symbian Software Systems 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:
* Andrew Ferguson (Symbian) - Initial implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.doctools;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.WorkbenchJob;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.doctools.IDocCommentOwner;
import org.eclipse.cdt.ui.text.doctools.IDocCommentOwnershipListener;
import org.eclipse.cdt.internal.ui.editor.ITranslationUnitEditorInput;
import org.eclipse.cdt.internal.ui.util.EditorUtility;
import org.eclipse.cdt.internal.ui.util.ExternalEditorInput;
/**
* Listens to change in doc-comment ownership and reinitializes
* the editors (or a safe superset of) that need reopening.
*/
public class EditorReopener implements IDocCommentOwnershipListener {
/*
* @see org.eclipse.cdt.ui.text.doctools.IDocCommentOwnershipListener#ownershipChanged(org.eclipse.core.resources.IResource, boolean, org.eclipse.cdt.ui.text.doctools.IDocCommentOwner, org.eclipse.cdt.ui.text.doctools.IDocCommentOwner)
*/
public void ownershipChanged(IResource resource, boolean recursive,
IDocCommentOwner old, IDocCommentOwner newOwner) {
IWorkbenchWindow window= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if(window!=null) {
try {
IEditorPart[] parts= getEditorsToRepon(window, resource);
if(queryIfNeeded(window.getShell(), parts)) {
reopenEditors(window, parts);
}
} catch(CoreException ce) {
CUIPlugin.log(ce);
}
}
}
/*
* @see org.eclipse.cdt.ui.text.doctools.IDocCommentOwnershipListener#workspaceOwnershipChanged(org.eclipse.cdt.ui.text.doctools.IDocCommentOwner, org.eclipse.cdt.ui.text.doctools.IDocCommentOwner)
*/
public void workspaceOwnershipChanged(IDocCommentOwner old, IDocCommentOwner newOwner) {
IWorkbenchWindow window= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if(window!=null) {
try {
IEditorPart[] parts= getEditorsToRepon(window, null);
if(queryIfNeeded(window.getShell(), parts)) {
reopenEditors(window, parts);
}
} catch(CoreException ce) {
CUIPlugin.log(ce);
}
}
}
/**
* @param window
* @param resource may be null to indicate all CDT editors should be reopened
* @return an array of {@link IEditorPart} objects that might need to be reinitialized
* based on doc-comment ownership of the specified resource changing
*/
/*
* This could be smarter in determining smaller sets of editors to re-open
*/
private IEditorPart[] getEditorsToRepon(IWorkbenchWindow window, IResource resource) {
List<IEditorPart> needReopening= new ArrayList<IEditorPart>();
if(window.getActivePage()!=null) {
IEditorReference[] es= window.getActivePage().getEditorReferences();
for(int i=0; i<es.length; i++) {
IEditorPart part= es[i].getEditor(false);
if(part!=null) {
IEditorInput iei= part.getEditorInput();
if(resource!=null) {
if(iei instanceof IFileEditorInput) {
IFile file= ((IFileEditorInput) iei).getFile();
IProject project= resource.getProject();
if(file.getProject().equals(project) && CoreModel.hasCNature(project)) {
needReopening.add(part);
}
}
} else {
if(iei instanceof ITranslationUnitEditorInput || iei instanceof IFileEditorInput) {
needReopening.add(part);
}
}
}
}
}
return needReopening.toArray(new IEditorPart[needReopening.size()]);
}
private boolean queryIfNeeded(Shell shell, IEditorPart[] editorParts) throws CoreException {
boolean anyUnsaved= false;
for(int j=0; j<editorParts.length; j++)
if(editorParts[j].isSaveOnCloseNeeded())
anyUnsaved= true;
boolean saveAndReopen= !anyUnsaved;
if(anyUnsaved) {
String title= Messages.EditorReopener_ShouldSave_Title;
String msg= Messages.EditorReopener_ShouldSave_Message;
if (MessageDialog.openQuestion(shell, title, msg))
saveAndReopen= true;
}
return saveAndReopen;
}
private void reopenEditors(final IWorkbenchWindow window, final IEditorPart[] editorParts) throws CoreException {
WorkbenchJob job= new WorkbenchJob(Messages.EditorReopener_ReopenJobStart) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
IEditorPart oldActive= window.getActivePage().getActiveEditor();
IEditorPart newActive= null;
for(int j=0; j<editorParts.length; j++) {
IEditorPart oldPart= editorParts[j];
if(oldPart.isDirty()) {
oldPart.doSave(new NullProgressMonitor());
}
window.getActivePage().closeEditor(oldPart, false);
IEditorInput oldInput= oldPart.getEditorInput();
try {
IEditorPart newPart= null;
if(oldInput instanceof IFileEditorInput) {
newPart= EditorUtility.openInEditor(((IFileEditorInput)oldInput).getFile());
} else if(oldInput instanceof ExternalEditorInput) {
ExternalEditorInput eei= (ExternalEditorInput) oldInput;
ICElement element= CoreModel.getDefault().create(eei.getMarkerResource());
newPart= EditorUtility.openInEditor(eei.getPath(), element);
}
if(oldPart == oldActive)
newActive= newPart;
} catch(PartInitException pie) {
CUIPlugin.log(pie);
} catch(CModelException cme) {
CUIPlugin.log(cme);
}
}
if(newActive != null) {
window.getActivePage().activate(newActive);
}
return new Status(IStatus.OK, CUIPlugin.PLUGIN_ID, Messages.EditorReopener_ReopenJobComplete);
}
};
job.schedule();
}
}