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