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;
18 import net.sourceforge.phpeclipse.ui.WebUI;
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;
34 //import org.eclipse.jface.util.ListenerList;
35 import org.eclipse.core.runtime.ListenerList;
36 import org.eclipse.swt.widgets.Display;
39 * Listens to resource deltas and filters for marker changes of type
40 * IMarker.PROBLEM Viewers showing error ticks should register as listener to
43 public class ProblemMarkerManager implements IResourceChangeListener,
44 IAnnotationModelListener, IAnnotationModelListenerExtension {
47 * Visitors used to look if the element change delta containes a marker
50 private static class ProjectErrorVisitor implements IResourceDeltaVisitor {
52 private HashSet fChangedElements;
54 public ProjectErrorVisitor(HashSet changedElements) {
55 fChangedElements = changedElements;
58 public boolean visit(IResourceDelta delta) throws CoreException {
59 IResource res = delta.getResource();
60 if (res instanceof IProject
61 && delta.getKind() == IResourceDelta.CHANGED) {
63 IProject project = (IProject) res;
64 if (!project.isAccessible()
66 .hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
67 // only track open Java projects
70 } catch (CoreException e) {
71 PHPeclipsePlugin.log(e);
75 checkInvalidate(delta, res);
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();
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)
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)
113 private ListenerList fListeners;
115 public ProblemMarkerManager() {
116 fListeners = new ListenerList();
120 * @see IResourceChangeListener#resourceChanged
122 public void resourceChanged(IResourceChangeEvent event) {
123 HashSet changedElements = new HashSet();
126 IResourceDelta delta = event.getDelta();
128 delta.accept(new ProjectErrorVisitor(changedElements));
129 } catch (CoreException e) {
130 PHPeclipsePlugin.log(e.getStatus());
133 if (!changedElements.isEmpty()) {
134 IResource[] changes = (IResource[]) changedElements
135 .toArray(new IResource[changedElements.size()]);
136 fireChanges(changes, true);
143 * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
145 public void modelChanged(IAnnotationModel model) {
152 * @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent)
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);
166 * Adds a listener for problem marker changes.
168 public void addListener(IProblemChangedListener listener) {
169 if (fListeners.isEmpty()) {
170 PHPeclipsePlugin.getWorkspace().addResourceChangeListener(this);
171 WebUI.getDefault().getCompilationUnitDocumentProvider()
172 .addGlobalAnnotationModelListener(this);
174 fListeners.add(listener);
178 * Removes a <code>IProblemChangedListener</code>.
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);
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() {
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);