/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package net.sourceforge.phpdt.internal.ui.text;
import net.sourceforge.phpdt.core.ElementChangedEvent;
import net.sourceforge.phpdt.core.IElementChangedListener;
import net.sourceforge.phpdt.core.JavaCore;
import net.sourceforge.phpeclipse.PHPeclipsePlugin;
import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.MonoReconciler;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.texteditor.ITextEditor;
/**
* A reconciler that is also activated on editor activation.
*/
public class JavaReconciler extends MonoReconciler {
/**
* Internal part listener for activating the reconciler.
*/
private class PartListener implements IPartListener {
/*
* @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
*/
public void partActivated(IWorkbenchPart part) {
if (part == fTextEditor && hasJavaModelChanged())
JavaReconciler.this.forceReconciling();
}
/*
* @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
*/
public void partBroughtToTop(IWorkbenchPart part) {
}
/*
* @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
*/
public void partClosed(IWorkbenchPart part) {
}
/*
* @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
*/
public void partDeactivated(IWorkbenchPart part) {
if (part == fTextEditor)
setJavaModelChanged(false);
}
/*
* @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
*/
public void partOpened(IWorkbenchPart part) {
}
}
/**
* Internal Shell activation listener for activating the reconciler.
*/
private class ActivationListener extends ShellAdapter {
private Control fControl;
public ActivationListener(Control control) {
fControl = control;
}
/*
* @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellActivated(ShellEvent e) {
if (!fControl.isDisposed() && fControl.isVisible()
&& hasJavaModelChanged())
JavaReconciler.this.forceReconciling();
}
/*
* @see org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse.swt.events.ShellEvent)
*/
public void shellDeactivated(ShellEvent e) {
setJavaModelChanged(false);
}
}
/**
* Internal Java element changed listener
*
* @since 3.0
*/
private class ElementChangedListener implements IElementChangedListener {
/*
* @see net.sourceforge.phpdt.core.IElementChangedListener#elementChanged(net.sourceforge.phpdt.core.ElementChangedEvent)
*/
public void elementChanged(ElementChangedEvent event) {
setJavaModelChanged(true);
}
}
/**
* Internal resource change listener.
*
* @since 3.0
*/
class ResourceChangeListener implements IResourceChangeListener {
private IResource getResource() {
IEditorInput input = fTextEditor.getEditorInput();
if (input instanceof IFileEditorInput) {
IFileEditorInput fileInput = (IFileEditorInput) input;
return fileInput.getFile();
}
return null;
}
/*
* @see IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
*/
public void resourceChanged(IResourceChangeEvent e) {
IResourceDelta delta = e.getDelta();
IResource resource = getResource();
if (delta != null && resource != null) {
IResourceDelta child = delta.findMember(resource.getFullPath());
if (child != null) {
IMarkerDelta[] deltas = child.getMarkerDeltas();
if (deltas.length > 0)
forceReconciling();
}
}
}
}
/** The reconciler's editor */
private ITextEditor fTextEditor;
/** The part listener */
private IPartListener fPartListener;
/** The shell listener */
private ShellListener fActivationListener;
/**
* The mutex that keeps us from running multiple reconcilers on one editor.
* TODO remove once we have ensured that there is only one reconciler per
* editor.
*/
private Object fMutex;
/**
* The Java element changed listener.
*
* @since 3.0
*/
private IElementChangedListener fJavaElementChangedListener;
/**
* Tells whether the Java model sent out a changed event.
*
* @since 3.0
*/
private volatile boolean fHasJavaModelChanged = true;
/**
* The resource change listener.
*
* @since 3.0
*/
private IResourceChangeListener fResourceChangeListener;
private boolean fIninitalProcessDone = false;
/**
* Creates a new reconciler.
*/
public JavaReconciler(ITextEditor editor,
JavaCompositeReconcilingStrategy strategy, boolean isIncremental) {
super(strategy, isIncremental);
fTextEditor = editor;
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898
// when re-using editors, a new reconciler is set up by the source
// viewer
// and the old one uninstalled. However, the old reconciler may still be
// running.
// To avoid having to reconcilers calling
// CompilationUnitEditor.reconciled,
// we synchronized on a lock object provided by the editor.
// The critical section is really the entire run() method of the
// reconciler
// thread, but synchronizing process() only will keep
// JavaReconcilingStrategy
// from running concurrently on the same editor.
// TODO remove once we have ensured that there is only one reconciler
// per editor.
if (editor instanceof PHPUnitEditor)
fMutex = ((PHPUnitEditor) editor).getReconcilerLock();
else
fMutex = new Object(); // Null Object
}
/*
* @see org.eclipse.jface.text.reconciler.IReconciler#install(org.eclipse.jface.text.ITextViewer)
*/
public void install(ITextViewer textViewer) {
super.install(textViewer);
fPartListener = new PartListener();
IWorkbenchPartSite site = fTextEditor.getSite();
IWorkbenchWindow window = site.getWorkbenchWindow();
window.getPartService().addPartListener(fPartListener);
fActivationListener = new ActivationListener(textViewer.getTextWidget());
Shell shell = window.getShell();
shell.addShellListener(fActivationListener);
fJavaElementChangedListener = new ElementChangedListener();
JavaCore.addElementChangedListener(fJavaElementChangedListener);
fResourceChangeListener = new ResourceChangeListener();
IWorkspace workspace = PHPeclipsePlugin.getWorkspace();
workspace.addResourceChangeListener(fResourceChangeListener);
}
/*
* @see org.eclipse.jface.text.reconciler.IReconciler#uninstall()
*/
public void uninstall() {
IWorkbenchPartSite site = fTextEditor.getSite();
IWorkbenchWindow window = site.getWorkbenchWindow();
window.getPartService().removePartListener(fPartListener);
fPartListener = null;
Shell shell = window.getShell();
if (shell != null && !shell.isDisposed())
shell.removeShellListener(fActivationListener);
fActivationListener = null;
JavaCore.removeElementChangedListener(fJavaElementChangedListener);
fJavaElementChangedListener = null;
IWorkspace workspace = PHPeclipsePlugin.getWorkspace();
workspace.removeResourceChangeListener(fResourceChangeListener);
fResourceChangeListener = null;
super.uninstall();
}
/*
* @see org.eclipse.jface.text.reconciler.AbstractReconciler#forceReconciling()
*/
protected void forceReconciling() {
if (!fIninitalProcessDone)
return;
super.forceReconciling();
JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
strategy.notifyListeners(false);
}
/*
* @see org.eclipse.jface.text.reconciler.AbstractReconciler#aboutToReconcile()
* @since 3.0
*/
protected void aboutToBeReconciled() {
JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
strategy.aboutToBeReconciled();
}
/*
* @see org.eclipse.jface.text.reconciler.AbstractReconciler#reconcilerReset()
*/
protected void reconcilerReset() {
super.reconcilerReset();
JavaCompositeReconcilingStrategy strategy = (JavaCompositeReconcilingStrategy) getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
strategy.notifyListeners(true);
}
/*
* @see org.eclipse.jface.text.reconciler.MonoReconciler#initialProcess()
*/
protected void initialProcess() {
// TODO remove once we have ensured that there is only one reconciler
// per editor.
synchronized (fMutex) {
super.initialProcess();
}
fIninitalProcessDone = true;
}
/*
* @see org.eclipse.jface.text.reconciler.MonoReconciler#process(org.eclipse.jface.text.reconciler.DirtyRegion)
*/
protected void process(DirtyRegion dirtyRegion) {
// TODO remove once we have ensured that there is only one reconciler
// per editor.
synchronized (fMutex) {
super.process(dirtyRegion);
}
}
/**
* Tells whether the Java Model has changed or not.
*
* @return true
iff the Java Model has changed
* @since 3.0
*/
private synchronized boolean hasJavaModelChanged() {
return fHasJavaModelChanged;
}
/**
* Sets whether the Java Model has changed or not.
*
* @param state
* true
iff the java model has changed
* @since 3.0
*/
private synchronized void setJavaModelChanged(boolean state) {
fHasJavaModelChanged = state;
}
}
// /**
// * A reconciler that is also activated on editor activation.
// */
// public class JavaReconciler extends MonoReconciler {
//
// /**
// * Internal part listener for activating the reconciler.
// */
// class PartListener implements IPartListener {
//
// /*
// * @see IPartListener#partActivated(IWorkbenchPart)
// */
// public void partActivated(IWorkbenchPart part) {
// if (part == fTextEditor)
// JavaReconciler.this.forceReconciling();
// }
//
// /*
// * @see IPartListener#partBroughtToTop(IWorkbenchPart)
// */
// public void partBroughtToTop(IWorkbenchPart part) {
// }
//
// /*
// * @see IPartListener#partClosed(IWorkbenchPart)
// */
// public void partClosed(IWorkbenchPart part) {
// }
//
// /*
// * @see IPartListener#partDeactivated(IWorkbenchPart)
// */
// public void partDeactivated(IWorkbenchPart part) {
// }
//
// /*
// * @see IPartListener#partOpened(IWorkbenchPart)
// */
// public void partOpened(IWorkbenchPart part) {
// }
// };
//
//
// /** The reconciler's editor */
// private ITextEditor fTextEditor;
// /** The part listener */
// private IPartListener fPartListener;
//
//
// /**
// * Creates a new reconciler.
// */
// public JavaReconciler(ITextEditor editor, IReconcilingStrategy strategy,
// boolean isIncremental) {
// super(strategy, isIncremental);
// fTextEditor= editor;
// }
//
// /*
// * @see IReconciler#install(ITextViewer)
// */
// public void install(ITextViewer textViewer) {
// super.install(textViewer);
//
// fPartListener= new PartListener();
// IWorkbenchPartSite site= fTextEditor.getSite();
// IWorkbenchWindow window= site.getWorkbenchWindow();
// window.getPartService().addPartListener(fPartListener);
// }
//
// /*
// * @see IReconciler#uninstall()
// */
// public void uninstall() {
//
// IWorkbenchPartSite site= fTextEditor.getSite();
// IWorkbenchWindow window= site.getWorkbenchWindow();
// window.getPartService().removePartListener(fPartListener);
// fPartListener= null;
//
// super.uninstall();
// }
//
// /*
// * @see AbstractReconciler#forceReconciling()
// */
// protected void forceReconciling() {
// super.forceReconciling();
// IReconcilingStrategy strategy=
// getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
// if (strategy instanceof JavaReconcilingStrategy) {
// JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy;
// java.notifyParticipants(false);
// }
// }
//
// /*
// * @see AbstractReconciler#reconcilerReset()
// */
// protected void reconcilerReset() {
// super.reconcilerReset();
// IReconcilingStrategy strategy=
// getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
// if (strategy instanceof JavaReconcilingStrategy) {
// JavaReconcilingStrategy java= (JavaReconcilingStrategy) strategy;
// java.notifyParticipants(true);
// }
// }
// }