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