1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2003 IBM Corporation and others.
 
   3  * All rights reserved. This program and the accompanying materials 
 
   4  * are made available under the terms of the Common Public License v1.0
 
   5  * which accompanies this distribution, and is available at
 
   6  * http://www.eclipse.org/legal/cpl-v10.html
 
   9  *     IBM Corporation - initial API and implementation
 
  10  *******************************************************************************/
 
  11 package net.sourceforge.phpdt.internal.ui.viewsupport;
 
  13 import java.util.HashSet;
 
  15 import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
 
  16 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
  17 import net.sourceforge.phpeclipse.phpeditor.CompilationUnitAnnotationModelEvent;
 
  18 import net.sourceforge.phpeclipse.ui.WebUI;
 
  20 import org.eclipse.core.resources.IMarker;
 
  21 import org.eclipse.core.resources.IMarkerDelta;
 
  22 import org.eclipse.core.resources.IProject;
 
  23 import org.eclipse.core.resources.IResource;
 
  24 import org.eclipse.core.resources.IResourceChangeEvent;
 
  25 import org.eclipse.core.resources.IResourceChangeListener;
 
  26 import org.eclipse.core.resources.IResourceDelta;
 
  27 import org.eclipse.core.resources.IResourceDeltaVisitor;
 
  28 import org.eclipse.core.runtime.CoreException;
 
  29 import org.eclipse.jface.text.source.AnnotationModelEvent;
 
  30 import org.eclipse.jface.text.source.IAnnotationModel;
 
  31 import org.eclipse.jface.text.source.IAnnotationModelListener;
 
  32 import org.eclipse.jface.text.source.IAnnotationModelListenerExtension;
 
  33 import org.eclipse.jface.util.ListenerList;
 
  34 import org.eclipse.swt.widgets.Display;
 
  37  * Listens to resource deltas and filters for marker changes of type
 
  38  * IMarker.PROBLEM Viewers showing error ticks should register as listener to
 
  41 public class ProblemMarkerManager implements IResourceChangeListener,
 
  42                 IAnnotationModelListener, IAnnotationModelListenerExtension {
 
  45          * Visitors used to look if the element change delta containes a marker
 
  48         private static class ProjectErrorVisitor implements IResourceDeltaVisitor {
 
  50                 private HashSet fChangedElements;
 
  52                 public ProjectErrorVisitor(HashSet changedElements) {
 
  53                         fChangedElements = changedElements;
 
  56                 public boolean visit(IResourceDelta delta) throws CoreException {
 
  57                         IResource res = delta.getResource();
 
  58                         if (res instanceof IProject
 
  59                                         && delta.getKind() == IResourceDelta.CHANGED) {
 
  61                                         IProject project = (IProject) res;
 
  62                                         if (!project.isAccessible()
 
  64                                                                         .hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
 
  65                                                 // only track open Java projects
 
  68                                 } catch (CoreException e) {
 
  69                                         PHPeclipsePlugin.log(e);
 
  73                         checkInvalidate(delta, res);
 
  77                 private void checkInvalidate(IResourceDelta delta, IResource resource) {
 
  78                         int kind = delta.getKind();
 
  79                         if (kind == IResourceDelta.REMOVED || kind == IResourceDelta.ADDED
 
  80                                         || (kind == IResourceDelta.CHANGED && isErrorDelta(delta))) {
 
  81                                 // invalidate the resource and all parents
 
  82                                 while (resource.getType() != IResource.ROOT
 
  83                                                 && fChangedElements.add(resource)) {
 
  84                                         resource = resource.getParent();
 
  89                 private boolean isErrorDelta(IResourceDelta delta) {
 
  90                         if ((delta.getFlags() & IResourceDelta.MARKERS) != 0) {
 
  91                                 IMarkerDelta[] markerDeltas = delta.getMarkerDeltas();
 
  92                                 for (int i = 0; i < markerDeltas.length; i++) {
 
  93                                         if (markerDeltas[i].isSubtypeOf(IMarker.PROBLEM)) {
 
  94                                                 int kind = markerDeltas[i].getKind();
 
  95                                                 if (kind == IResourceDelta.ADDED
 
  96                                                                 || kind == IResourceDelta.REMOVED)
 
  98                                                 int severity = markerDeltas[i].getAttribute(
 
  99                                                                 IMarker.SEVERITY, -1);
 
 100                                                 int newSeverity = markerDeltas[i].getMarker()
 
 101                                                                 .getAttribute(IMarker.SEVERITY, -1);
 
 102                                                 if (newSeverity != severity)
 
 111         private ListenerList fListeners;
 
 113         public ProblemMarkerManager() {
 
 114                 fListeners = new ListenerList(10);
 
 118          * @see IResourceChangeListener#resourceChanged
 
 120         public void resourceChanged(IResourceChangeEvent event) {
 
 121                 HashSet changedElements = new HashSet();
 
 124                         IResourceDelta delta = event.getDelta();
 
 126                                 delta.accept(new ProjectErrorVisitor(changedElements));
 
 127                 } catch (CoreException e) {
 
 128                         PHPeclipsePlugin.log(e.getStatus());
 
 131                 if (!changedElements.isEmpty()) {
 
 132                         IResource[] changes = (IResource[]) changedElements
 
 133                                         .toArray(new IResource[changedElements.size()]);
 
 134                         fireChanges(changes, true);
 
 141          * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
 
 143         public void modelChanged(IAnnotationModel model) {
 
 150          * @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent)
 
 152         public void modelChanged(AnnotationModelEvent event) {
 
 153                 if (event instanceof CompilationUnitAnnotationModelEvent) {
 
 154                         CompilationUnitAnnotationModelEvent cuEvent = (CompilationUnitAnnotationModelEvent) event;
 
 155                         if (cuEvent.includesProblemMarkerAnnotationChanges()) {
 
 156                                 IResource[] changes = new IResource[] { cuEvent
 
 157                                                 .getUnderlyingResource() };
 
 158                                 fireChanges(changes, false);
 
 164          * Adds a listener for problem marker changes.
 
 166         public void addListener(IProblemChangedListener listener) {
 
 167                 if (fListeners.isEmpty()) {
 
 168                         PHPeclipsePlugin.getWorkspace().addResourceChangeListener(this);
 
 169                         WebUI.getDefault().getCompilationUnitDocumentProvider()
 
 170                                         .addGlobalAnnotationModelListener(this);
 
 172                 fListeners.add(listener);
 
 176          * Removes a <code>IProblemChangedListener</code>.
 
 178         public void removeListener(IProblemChangedListener listener) {
 
 179                 fListeners.remove(listener);
 
 180                 if (fListeners.isEmpty()) {
 
 181                         PHPeclipsePlugin.getWorkspace().removeResourceChangeListener(this);
 
 182                         WebUI.getDefault().getCompilationUnitDocumentProvider()
 
 183                                         .removeGlobalAnnotationModelListener(this);
 
 187         private void fireChanges(final IResource[] changes,
 
 188                         final boolean isMarkerChange) {
 
 189                 Display display = SWTUtil.getStandardDisplay();
 
 190                 if (display != null && !display.isDisposed()) {
 
 191                         display.asyncExec(new Runnable() {
 
 193                                         Object[] listeners = fListeners.getListeners();
 
 194                                         for (int i = 0; i < listeners.length; i++) {
 
 195                                                 IProblemChangedListener curr = (IProblemChangedListener) listeners[i];
 
 196                                                 curr.problemsChanged(changes, isMarkerChange);