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;
14 import java.util.HashSet;
16 import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
17 //import net.sourceforge.phpeclipse.PHPCore;
18 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
19 import net.sourceforge.phpeclipse.phpeditor.CompilationUnitAnnotationModelEvent;
21 import org.eclipse.core.resources.IMarker;
22 import org.eclipse.core.resources.IMarkerDelta;
23 import org.eclipse.core.resources.IProject;
24 import org.eclipse.core.resources.IResource;
25 import org.eclipse.core.resources.IResourceChangeEvent;
26 import org.eclipse.core.resources.IResourceChangeListener;
27 import org.eclipse.core.resources.IResourceDelta;
28 import org.eclipse.core.resources.IResourceDeltaVisitor;
29 import org.eclipse.core.runtime.CoreException;
30 import org.eclipse.jface.text.source.AnnotationModelEvent;
31 import org.eclipse.jface.text.source.IAnnotationModel;
32 import org.eclipse.jface.text.source.IAnnotationModelListener;
33 import org.eclipse.jface.text.source.IAnnotationModelListenerExtension;
34 import org.eclipse.jface.util.ListenerList;
35 import org.eclipse.swt.widgets.Display;
40 * Listens to resource deltas and filters for marker changes of type IMarker.PROBLEM
41 * Viewers showing error ticks should register as listener to
44 public class ProblemMarkerManager implements IResourceChangeListener, IAnnotationModelListener , IAnnotationModelListenerExtension {
47 * Visitors used to look if the element change delta containes a marker change.
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 && delta.getKind() == IResourceDelta.CHANGED) {
61 IProject project= (IProject) res;
62 if (!project.isAccessible() || !project.hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
63 // only track open Java projects
66 } catch (CoreException e) {
67 PHPeclipsePlugin.log(e);
71 checkInvalidate(delta, res);
75 private void checkInvalidate(IResourceDelta delta, IResource resource) {
76 int kind= delta.getKind();
77 if (kind == IResourceDelta.REMOVED || kind == IResourceDelta.ADDED || (kind == IResourceDelta.CHANGED && isErrorDelta(delta))) {
78 // invalidate the resource and all parents
79 while (resource.getType() != IResource.ROOT && fChangedElements.add(resource)) {
80 resource= resource.getParent();
85 private boolean isErrorDelta(IResourceDelta delta) {
86 if ((delta.getFlags() & IResourceDelta.MARKERS) != 0) {
87 IMarkerDelta[] markerDeltas= delta.getMarkerDeltas();
88 for (int i= 0; i < markerDeltas.length; i++) {
89 if (markerDeltas[i].isSubtypeOf(IMarker.PROBLEM)) {
90 int kind= markerDeltas[i].getKind();
91 if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED)
93 int severity= markerDeltas[i].getAttribute(IMarker.SEVERITY, -1);
94 int newSeverity= markerDeltas[i].getMarker().getAttribute(IMarker.SEVERITY, -1);
95 if (newSeverity != severity)
104 private ListenerList fListeners;
107 public ProblemMarkerManager() {
108 fListeners= new ListenerList(10);
112 * @see IResourceChangeListener#resourceChanged
114 public void resourceChanged(IResourceChangeEvent event) {
115 HashSet changedElements= new HashSet();
118 IResourceDelta delta= event.getDelta();
120 delta.accept(new ProjectErrorVisitor(changedElements));
121 } catch (CoreException e) {
122 PHPeclipsePlugin.log(e.getStatus());
125 if (!changedElements.isEmpty()) {
126 IResource[] changes= (IResource[]) changedElements.toArray(new IResource[changedElements.size()]);
127 fireChanges(changes, true);
131 * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
133 public void modelChanged(IAnnotationModel model) {
138 * @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent)
140 public void modelChanged(AnnotationModelEvent event) {
141 if (event instanceof CompilationUnitAnnotationModelEvent) {
142 CompilationUnitAnnotationModelEvent cuEvent= (CompilationUnitAnnotationModelEvent) event;
143 if (cuEvent.includesProblemMarkerAnnotationChanges()) {
144 IResource[] changes= new IResource[] { cuEvent.getUnderlyingResource() };
145 fireChanges(changes, false);
151 * Adds a listener for problem marker changes.
153 public void addListener(IProblemChangedListener listener) {
154 if (fListeners.isEmpty()) {
155 PHPeclipsePlugin.getWorkspace().addResourceChangeListener(this);
156 PHPeclipsePlugin.getDefault().getCompilationUnitDocumentProvider().addGlobalAnnotationModelListener(this);
158 fListeners.add(listener);
162 * Removes a <code>IProblemChangedListener</code>.
164 public void removeListener(IProblemChangedListener listener) {
165 fListeners.remove(listener);
166 if (fListeners.isEmpty()) {
167 PHPeclipsePlugin.getWorkspace().removeResourceChangeListener(this);
168 PHPeclipsePlugin.getDefault().getCompilationUnitDocumentProvider().removeGlobalAnnotationModelListener(this);
172 private void fireChanges(final IResource[] changes, final boolean isMarkerChange) {
173 Display display= SWTUtil.getStandardDisplay();
174 if (display != null && !display.isDisposed()) {
175 display.asyncExec(new Runnable() {
177 Object[] listeners= fListeners.getListeners();
178 for (int i= 0; i < listeners.length; i++) {
179 IProblemChangedListener curr= (IProblemChangedListener) listeners[i];
180 curr.problemsChanged(changes, isMarkerChange);