001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.viewsupport;
011:
012: import java.util.HashSet;
013:
014: import org.eclipse.core.runtime.CoreException;
015: import org.eclipse.core.runtime.ListenerList;
016:
017: import org.eclipse.core.resources.IMarker;
018: import org.eclipse.core.resources.IMarkerDelta;
019: import org.eclipse.core.resources.IProject;
020: import org.eclipse.core.resources.IResource;
021: import org.eclipse.core.resources.IResourceChangeEvent;
022: import org.eclipse.core.resources.IResourceChangeListener;
023: import org.eclipse.core.resources.IResourceDelta;
024: import org.eclipse.core.resources.IResourceDeltaVisitor;
025:
026: import org.eclipse.swt.widgets.Display;
027:
028: import org.eclipse.jface.text.source.AnnotationModelEvent;
029: import org.eclipse.jface.text.source.IAnnotationModel;
030: import org.eclipse.jface.text.source.IAnnotationModelListener;
031: import org.eclipse.jface.text.source.IAnnotationModelListenerExtension;
032:
033: import org.eclipse.jdt.internal.ui.JavaPlugin;
034: import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitAnnotationModelEvent;
035: import org.eclipse.jdt.internal.ui.util.SWTUtil;
036:
037: /**
038: * Listens to resource deltas and filters for marker changes of type IMarker.PROBLEM
039: * Viewers showing error ticks should register as listener to
040: * this type.
041: */
042: public class ProblemMarkerManager implements IResourceChangeListener,
043: IAnnotationModelListener, IAnnotationModelListenerExtension {
044:
045: /**
046: * Visitors used to look if the element change delta contains a marker change.
047: */
048: private static class ProjectErrorVisitor implements
049: IResourceDeltaVisitor {
050:
051: private HashSet fChangedElements;
052:
053: public ProjectErrorVisitor(HashSet changedElements) {
054: fChangedElements = changedElements;
055: }
056:
057: public boolean visit(IResourceDelta delta) throws CoreException {
058: IResource res = delta.getResource();
059: if (res instanceof IProject
060: && delta.getKind() == IResourceDelta.CHANGED) {
061: IProject project = (IProject) res;
062: if (!project.isAccessible()) {
063: // only track open Java projects
064: return false;
065: }
066: }
067: checkInvalidate(delta, res);
068: return true;
069: }
070:
071: private void checkInvalidate(IResourceDelta delta,
072: IResource resource) {
073: int kind = delta.getKind();
074: if (kind == IResourceDelta.REMOVED
075: || kind == IResourceDelta.ADDED
076: || (kind == IResourceDelta.CHANGED && isErrorDelta(delta))) {
077: // invalidate the resource and all parents
078: while (resource.getType() != IResource.ROOT
079: && fChangedElements.add(resource)) {
080: resource = resource.getParent();
081: }
082: }
083: }
084:
085: private boolean isErrorDelta(IResourceDelta delta) {
086: if ((delta.getFlags() & IResourceDelta.MARKERS) != 0) {
087: IMarkerDelta[] markerDeltas = delta.getMarkerDeltas();
088: for (int i = 0; i < markerDeltas.length; i++) {
089: if (markerDeltas[i].isSubtypeOf(IMarker.PROBLEM)) {
090: int kind = markerDeltas[i].getKind();
091: if (kind == IResourceDelta.ADDED
092: || kind == IResourceDelta.REMOVED)
093: return true;
094: int severity = markerDeltas[i].getAttribute(
095: IMarker.SEVERITY, -1);
096: int newSeverity = markerDeltas[i].getMarker()
097: .getAttribute(IMarker.SEVERITY, -1);
098: if (newSeverity != severity)
099: return true;
100: }
101: }
102: }
103: return false;
104: }
105: }
106:
107: private ListenerList fListeners;
108:
109: public ProblemMarkerManager() {
110: fListeners = new ListenerList();
111: }
112:
113: /*
114: * @see IResourceChangeListener#resourceChanged
115: */
116: public void resourceChanged(IResourceChangeEvent event) {
117: HashSet changedElements = new HashSet();
118:
119: try {
120: IResourceDelta delta = event.getDelta();
121: if (delta != null)
122: delta.accept(new ProjectErrorVisitor(changedElements));
123: } catch (CoreException e) {
124: JavaPlugin.log(e.getStatus());
125: }
126:
127: if (!changedElements.isEmpty()) {
128: IResource[] changes = (IResource[]) changedElements
129: .toArray(new IResource[changedElements.size()]);
130: fireChanges(changes, true);
131: }
132: }
133:
134: /* (non-Javadoc)
135: * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
136: */
137: public void modelChanged(IAnnotationModel model) {
138: // no action
139: }
140:
141: /* (non-Javadoc)
142: * @see IAnnotationModelListenerExtension#modelChanged(AnnotationModelEvent)
143: */
144: public void modelChanged(AnnotationModelEvent event) {
145: if (event instanceof CompilationUnitAnnotationModelEvent) {
146: CompilationUnitAnnotationModelEvent cuEvent = (CompilationUnitAnnotationModelEvent) event;
147: if (cuEvent.includesProblemMarkerAnnotationChanges()) {
148: IResource[] changes = new IResource[] { cuEvent
149: .getUnderlyingResource() };
150: fireChanges(changes, false);
151: }
152: }
153: }
154:
155: /**
156: * Adds a listener for problem marker changes.
157: */
158: public void addListener(IProblemChangedListener listener) {
159: if (fListeners.isEmpty()) {
160: JavaPlugin.getWorkspace().addResourceChangeListener(this );
161: JavaPlugin.getDefault()
162: .getCompilationUnitDocumentProvider()
163: .addGlobalAnnotationModelListener(this );
164: }
165: fListeners.add(listener);
166: }
167:
168: /**
169: * Removes a <code>IProblemChangedListener</code>.
170: */
171: public void removeListener(IProblemChangedListener listener) {
172: fListeners.remove(listener);
173: if (fListeners.isEmpty()) {
174: JavaPlugin.getWorkspace()
175: .removeResourceChangeListener(this );
176: JavaPlugin.getDefault()
177: .getCompilationUnitDocumentProvider()
178: .removeGlobalAnnotationModelListener(this );
179: }
180: }
181:
182: private void fireChanges(final IResource[] changes,
183: final boolean isMarkerChange) {
184: Display display = SWTUtil.getStandardDisplay();
185: if (display != null && !display.isDisposed()) {
186: display.asyncExec(new Runnable() {
187: public void run() {
188: Object[] listeners = fListeners.getListeners();
189: for (int i = 0; i < listeners.length; i++) {
190: IProblemChangedListener curr = (IProblemChangedListener) listeners[i];
191: curr.problemsChanged(changes, isMarkerChange);
192: }
193: }
194: });
195: }
196: }
197:
198: }
|