3m9 compatible;
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / viewsupport / ProblemMarkerManager.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.viewsupport;
12
13
14 import java.util.HashSet;
15
16 import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
17 //import net.sourceforge.phpeclipse.PHPCore;
18 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
19 import net.sourceforge.phpeclipse.phpeditor.CompilationUnitAnnotationModelEvent;
20
21 import org.eclipse.core.resources.IMarker;
22 import org.eclipse.core.resources.IMarkerDelta;
23 import org.eclipse.core.resources.IProject;
24 import org.eclipse.core.resources.IResource;
25 import org.eclipse.core.resources.IResourceChangeEvent;
26 import org.eclipse.core.resources.IResourceChangeListener;
27 import org.eclipse.core.resources.IResourceDelta;
28 import org.eclipse.core.resources.IResourceDeltaVisitor;
29 import org.eclipse.core.runtime.CoreException;
30 import org.eclipse.jface.text.source.AnnotationModelEvent;
31 import org.eclipse.jface.text.source.IAnnotationModel;
32 import org.eclipse.jface.text.source.IAnnotationModelListener;
33 import org.eclipse.jface.text.source.IAnnotationModelListenerExtension;
34 import org.eclipse.jface.util.ListenerList;
35 import org.eclipse.swt.widgets.Display;
36
37
38
39 /**
40  * Listens to resource deltas and filters for marker changes of type IMarker.PROBLEM
41  * Viewers showing error ticks should register as listener to
42  * this type.
43  */
44 public class ProblemMarkerManager implements IResourceChangeListener, IAnnotationModelListener , IAnnotationModelListenerExtension {
45
46         /**
47          * Visitors used to look if the element change delta containes a marker change.
48          */
49         private static class ProjectErrorVisitor implements IResourceDeltaVisitor {
50
51                 private HashSet fChangedElements; 
52                 
53                 public ProjectErrorVisitor(HashSet changedElements) {
54                         fChangedElements= changedElements;
55                 }
56                         
57                 public boolean visit(IResourceDelta delta) throws CoreException {
58                         IResource res= delta.getResource();
59                         if (res instanceof IProject && delta.getKind() == IResourceDelta.CHANGED) {
60                                 try {
61                                         IProject project= (IProject) res;
62                                         if (!project.isAccessible() || !project.hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
63                                                 // only track open Java projects
64                                                 return false;
65                                         }
66                                 } catch (CoreException e) {
67                                         PHPeclipsePlugin.log(e);
68                                         return false;
69                                 }
70                         }
71                         checkInvalidate(delta, res);
72                         return true;
73                 }
74                 
75                 private void checkInvalidate(IResourceDelta delta, IResource resource) {
76                         int kind= delta.getKind();
77                         if (kind == IResourceDelta.REMOVED || kind == IResourceDelta.ADDED || (kind == IResourceDelta.CHANGED && isErrorDelta(delta))) {
78                                 // invalidate the resource and all parents
79                                 while (resource.getType() != IResource.ROOT && fChangedElements.add(resource)) {
80                                         resource= resource.getParent();
81                                 }
82                         } 
83                 }       
84                 
85                 private boolean isErrorDelta(IResourceDelta delta) {    
86                         if ((delta.getFlags() & IResourceDelta.MARKERS) != 0) {
87                                 IMarkerDelta[] markerDeltas= delta.getMarkerDeltas();
88                                 for (int i= 0; i < markerDeltas.length; i++) {
89                                         if (markerDeltas[i].isSubtypeOf(IMarker.PROBLEM)) {
90                                                 int kind= markerDeltas[i].getKind();
91                                                 if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED)
92                                                         return true;
93                                                 int severity= markerDeltas[i].getAttribute(IMarker.SEVERITY, -1);
94                                                 int newSeverity= markerDeltas[i].getMarker().getAttribute(IMarker.SEVERITY, -1);
95                                                 if (newSeverity != severity)
96                                                         return true; 
97                                         }
98                                 }
99                         }
100                         return false;
101                 }
102         }
103
104         private ListenerList fListeners;
105         
106         
107         public ProblemMarkerManager() {
108                 fListeners= new ListenerList(10);
109         }
110
111         /*
112          * @see IResourceChangeListener#resourceChanged
113          */     
114         public void resourceChanged(IResourceChangeEvent event) {
115                 HashSet changedElements= new HashSet();
116                 
117                 try {
118                         IResourceDelta delta= event.getDelta();
119                         if (delta != null)
120                                 delta.accept(new ProjectErrorVisitor(changedElements));
121                 } catch (CoreException e) {
122                         PHPeclipsePlugin.log(e.getStatus());
123                 }
124
125                 if (!changedElements.isEmpty()) {
126                         IResource[] changes= (IResource[]) changedElements.toArray(new IResource[changedElements.size()]);
127                         fireChanges(changes, true);
128                 }
129         }
130         /* (non-Javadoc)
131          * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
132          */
133         public void modelChanged(IAnnotationModel model) {
134                 // no action
135         }
136
137         /* (non-Javadoc)
138          * @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent)
139          */
140         public void modelChanged(AnnotationModelEvent event) {
141                 if (event instanceof CompilationUnitAnnotationModelEvent) {
142                         CompilationUnitAnnotationModelEvent cuEvent= (CompilationUnitAnnotationModelEvent) event;
143                         if (cuEvent.includesProblemMarkerAnnotationChanges()) {
144                                 IResource[] changes= new IResource[] { cuEvent.getUnderlyingResource() };
145                                 fireChanges(changes, false);
146                         }
147                 }
148         }       
149         
150         /**
151          * Adds a listener for problem marker changes.
152          */
153         public void addListener(IProblemChangedListener listener) {
154                 if (fListeners.isEmpty()) { 
155                         PHPeclipsePlugin.getWorkspace().addResourceChangeListener(this);
156                         PHPeclipsePlugin.getDefault().getCompilationUnitDocumentProvider().addGlobalAnnotationModelListener(this);
157                 }
158                 fListeners.add(listener);
159         }
160
161         /**
162          * Removes a <code>IProblemChangedListener</code>.
163          */     
164         public void removeListener(IProblemChangedListener listener) {
165                 fListeners.remove(listener);
166                 if (fListeners.isEmpty()) {
167                         PHPeclipsePlugin.getWorkspace().removeResourceChangeListener(this);
168                         PHPeclipsePlugin.getDefault().getCompilationUnitDocumentProvider().removeGlobalAnnotationModelListener(this);
169                 }
170         }
171         
172         private void fireChanges(final IResource[] changes, final boolean isMarkerChange) {
173                 Display display= SWTUtil.getStandardDisplay();
174                 if (display != null && !display.isDisposed()) {
175                         display.asyncExec(new Runnable() {
176                                 public void run() {             
177                                         Object[] listeners= fListeners.getListeners();
178                                         for (int i= 0; i < listeners.length; i++) {
179                                                 IProblemChangedListener curr= (IProblemChangedListener) listeners[i];
180                                                 curr.problemsChanged(changes, isMarkerChange);
181                                         }       
182                                 }
183                         });
184                 }       
185         }
186
187 }