blob: ea352062831e7de39cea7b8bb1eaefa731416301 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.texteditor;
import java.util.HashSet;
import java.util.Iterator;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
/**
* A marker annotation model whose underlying source of markers is
* a resource in the workspace.
* <p>
* This class may be instantiated; it is not intended to be subclassed.</p>
*
* @noextend This class is not intended to be subclassed by clients.
*/
public class ResourceMarkerAnnotationModel extends AbstractMarkerAnnotationModel {
/**
* Internal resource change listener.
*/
class ResourceChangeListener implements IResourceChangeListener {
@Override
public void resourceChanged(IResourceChangeEvent e) {
IResourceDelta delta= e.getDelta();
if (delta != null && fResource != null) {
IResourceDelta child= delta.findMember(fResource.getFullPath());
if (child != null)
update(child.getMarkerDeltas());
}
}
}
/** The workspace. */
private IWorkspace fWorkspace;
/** The resource. */
private IResource fResource;
/** The resource change listener. */
private IResourceChangeListener fResourceChangeListener= new ResourceChangeListener();
/**
* Creates a marker annotation model with the given resource as the source
* of the markers.
*
* @param resource the resource
*/
public ResourceMarkerAnnotationModel(IResource resource) {
Assert.isNotNull(resource);
fResource= resource;
fWorkspace= resource.getWorkspace();
}
@Override
protected boolean isAcceptable(IMarker marker) {
return marker != null && fResource.equals(marker.getResource());
}
/**
* Updates this model to the given marker deltas.
*
* @param markerDeltas the array of marker deltas
*/
protected void update(IMarkerDelta[] markerDeltas) {
if (markerDeltas.length == 0)
return;
if (markerDeltas.length == 1) {
IMarkerDelta delta= markerDeltas[0];
switch (delta.getKind()) {
case IResourceDelta.ADDED :
addMarkerAnnotation(delta.getMarker());
break;
case IResourceDelta.REMOVED :
removeMarkerAnnotation(delta.getMarker());
break;
case IResourceDelta.CHANGED :
modifyMarkerAnnotation(delta.getMarker());
break;
}
} else
batchedUpdate(markerDeltas);
fireModelChanged();
}
/**
* Updates this model to the given marker deltas.
*
* @param markerDeltas the array of marker deltas
*/
private void batchedUpdate(IMarkerDelta[] markerDeltas) {
HashSet<IMarker> removedMarkers= new HashSet<>(markerDeltas.length);
HashSet<IMarker> modifiedMarkers= new HashSet<>(markerDeltas.length);
for (int i= 0; i < markerDeltas.length; i++) {
IMarkerDelta delta= markerDeltas[i];
switch (delta.getKind()) {
case IResourceDelta.ADDED:
addMarkerAnnotation(delta.getMarker());
break;
case IResourceDelta.REMOVED:
removedMarkers.add(delta.getMarker());
break;
case IResourceDelta.CHANGED:
modifiedMarkers.add(delta.getMarker());
break;
}
}
if (modifiedMarkers.isEmpty() && removedMarkers.isEmpty())
return;
Iterator<Annotation> e= getAnnotationIterator(false);
while (e.hasNext()) {
Object o= e.next();
if (o instanceof MarkerAnnotation) {
MarkerAnnotation a= (MarkerAnnotation)o;
IMarker marker= a.getMarker();
if (removedMarkers.remove(marker))
removeAnnotation(a, false);
if (modifiedMarkers.remove(marker)) {
Position p= createPositionFromMarker(marker);
if (p != null) {
a.update();
modifyAnnotationPosition(a, p, false);
}
}
if (modifiedMarkers.isEmpty() && removedMarkers.isEmpty())
return;
}
}
Iterator<IMarker> iter= modifiedMarkers.iterator();
while (iter.hasNext())
addMarkerAnnotation(iter.next());
}
@Override
protected void listenToMarkerChanges(boolean listen) {
if (listen)
fWorkspace.addResourceChangeListener(fResourceChangeListener);
else
fWorkspace.removeResourceChangeListener(fResourceChangeListener);
}
@Override
protected void deleteMarkers(final IMarker[] markers) throws CoreException {
fWorkspace.run(new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
for (int i= 0; i < markers.length; ++i) {
markers[i].delete();
}
}
}, null, IWorkspace.AVOID_UPDATE, null);
}
@Override
protected IMarker[] retrieveMarkers() throws CoreException {
return fResource.findMarkers(IMarker.MARKER, true, IResource.DEPTH_ZERO);
}
/**
* Returns the resource serving as the source of markers for this annotation model.
*
* @return the resource serving as the source of markers for this annotation model
* @since 2.0
*/
protected IResource getResource() {
return fResource;
}
}