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;
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;
33 //import org.eclipse.jface.util.ListenerList;
34 import org.eclipse.core.runtime.ListenerList;
35 import org.eclipse.swt.widgets.Display;
38 * Listens to resource deltas and filters for marker changes of type
39 * IMarker.PROBLEM Viewers showing error ticks should register as listener to
42 public class ProblemMarkerManager implements IResourceChangeListener,
43 IAnnotationModelListener, IAnnotationModelListenerExtension {
46 * Visitors used to look if the element change delta containes a marker
49 private static class ProjectErrorVisitor implements IResourceDeltaVisitor {
51 private HashSet fChangedElements;
53 public ProjectErrorVisitor(HashSet changedElements) {
54 fChangedElements = changedElements;
57 public boolean visit(IResourceDelta delta) throws CoreException {
58 IResource res = delta.getResource();
59 if (res instanceof IProject
60 && delta.getKind() == IResourceDelta.CHANGED) {
62 IProject project = (IProject) res;
63 if (!project.isAccessible()
65 .hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
66 // only track open Java projects
69 } catch (CoreException e) {
70 PHPeclipsePlugin.log(e);
74 checkInvalidate(delta, res);
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();
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)
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)
112 private ListenerList fListeners;
114 public ProblemMarkerManager() {
115 fListeners = new ListenerList();
119 * @see IResourceChangeListener#resourceChanged
121 public void resourceChanged(IResourceChangeEvent event) {
122 HashSet changedElements = new HashSet();
125 IResourceDelta delta = event.getDelta();
127 delta.accept(new ProjectErrorVisitor(changedElements));
128 } catch (CoreException e) {
129 PHPeclipsePlugin.log(e.getStatus());
132 if (!changedElements.isEmpty()) {
133 IResource[] changes = (IResource[]) changedElements
134 .toArray(new IResource[changedElements.size()]);
135 fireChanges(changes, true);
142 * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
144 public void modelChanged(IAnnotationModel model) {
151 * @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent)
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);
165 * Adds a listener for problem marker changes.
167 public void addListener(IProblemChangedListener listener) {
168 if (fListeners.isEmpty()) {
169 PHPeclipsePlugin.getWorkspace().addResourceChangeListener(this);
170 PHPeclipsePlugin.getDefault().getCompilationUnitDocumentProvider()
171 .addGlobalAnnotationModelListener(this);
173 fListeners.add(listener);
177 * Removes a <code>IProblemChangedListener</code>.
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);
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() {
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);