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