blob: 73b81d02222f140a6d529803ba62bc70294d05f2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.views.markers.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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.runtime.CoreException;
import org.eclipse.jface.util.ListenerList;
/**
* Registry that tracks resource markers and maintains a sorted, filtered list of the markers.
* Notifies listeners of changes in these markers.
*/
public class MarkerRegistry implements IResourceChangeListener, ITableViewContentProvider {
private IFilter filter;
private IResource input;
private String[] types = new String[0];
private ListenerList listeners = new ListenerList();
public MarkerRegistry() {
}
/**
* Disposes the registry, releasing all listeners
* and any other allocated resources.
*/
public void dispose() {
listeners.clear();
setInput(null);
}
/**
* @return a filtered, sorted list of markers.
*/
public Object[] getElements() {
Object[] elements = getUnfilteredElements();
if (filter != null) {
Object[] filteredItems = filter.filter(elements);
return filteredItems;
}
return elements;
}
/**
* @return an unfiltered list of elements
*/
public Object[] getUnfilteredElements() {
if (input == null) {
return new Object[0];
}
List elements = new ArrayList();
for (int i = 0; i < types.length; i++) {
try {
IMarker[] newMarkers = input.findMarkers(types[i], true, IResource.DEPTH_INFINITE);
elements.addAll(Arrays.asList(newMarkers));
}
catch (CoreException e) {
}
}
return elements.toArray();
}
/**
* @return the registry's filter or <code>null</code> if no filter has been assigned
* to the registry.
*/
public IFilter getFilter() {
return filter;
}
/**
* @return the registry's input resource
*/
public IResource getInput() {
return input;
}
/**
* Sets the registry's filter
*
* @param filter
*/
public void setFilter(IFilter filter) {
if (this.filter == null || !this.filter.equals(filter)) {
this.filter = filter;
}
}
/**
* Sets the registry's input resource
*
* @param resource
*/
public void setInput(IResource resource) {
if (input != null) {
if (input.equals(resource))
return;
input.getWorkspace().removeResourceChangeListener(this);
}
input = resource;
if (input != null)
resource.getWorkspace().addResourceChangeListener(this);
}
/**
* @return the base marker types that the registry is tracking
*/
public String[] getTypes() {
return types;
}
/**
* Sets the base marker types to track. By default the registry will search for
* all markers of these types and their subtypes.
*
* @param types
*/
public void setTypes(String[] types) {
if (types == null)
this.types = new String[0];
else
this.types = types;
}
/**
* Convenience method used if only interested in one base marker type.
*
* @param type
*/
public void setType(String type) {
setTypes(new String[] { type });
}
/* (non-Javadoc)
* @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
*/
public void resourceChanged(IResourceChangeEvent event) {
// gather all marker changes from the delta.
// be sure to do this in the calling thread,
// as the delta is destroyed when this method returns
final List additions = new ArrayList();
final List removals = new ArrayList();
final List changes = new ArrayList();
IResourceDelta delta = event.getDelta();
if (delta == null)
return;
getMarkerDeltas(delta, additions, removals, changes);
//filter additions and changes but not removals since they have already been deleted
filterList(additions);
filterList(changes);
notifyListeners(additions, removals, changes);
}
/**
* Recursively walks over the resource delta and gathers all marker deltas. Marker
* deltas are placed into one of the two given lists depending on the type of delta
* (add or remove).
*/
private void getMarkerDeltas(IResourceDelta delta, List additions, List removals, List changes) {
IMarkerDelta[] markerDeltas = delta.getMarkerDeltas();
for (int i = 0; i < markerDeltas.length; i++) {
IMarkerDelta markerDelta = markerDeltas[i];
IMarker marker = markerDelta.getMarker();
switch (markerDelta.getKind()) {
case IResourceDelta.ADDED: {
boolean added = false;
for (int j = 0; j < types.length && !added; j++) {
if (markerDelta.isSubtypeOf(types[j])) {
additions.add(marker);
added = true;
}
}
break;
}
case IResourceDelta.REMOVED: {
boolean added = false;
for (int j = 0; j < types.length && !added; j++) {
if (markerDelta.isSubtypeOf(types[j])) {
removals.add(marker);
added = true;
}
}
break;
}
case IResourceDelta.CHANGED: {
boolean added = false;
for (int j = 0; j < types.length && !added; j++) {
if (markerDelta.isSubtypeOf(types[j])) {
changes.add(marker);
added = true;
}
}
break;
}
}
}
//recurse on child deltas
IResourceDelta[] children = delta.getAffectedChildren();
for (int i = 0; i < children.length; i++) {
getMarkerDeltas(children[i], additions, removals, changes);
}
}
private void notifyListeners(List additions, List removals, List changes) {
Object[] listeners = this.listeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
IItemsChangedListener listener = (IItemsChangedListener) listeners[i];
listener.itemsChanged(additions, removals, changes);
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.views.internal.tableview.ITableViewContentProvider#addItemsChangedListener(org.eclipse.ui.views.internal.tableview.IItemsChangedListener)
*/
public void addItemsChangedListener(IItemsChangedListener listener) {
listeners.add(listener);
}
/* (non-Javadoc)
* @see org.eclipse.ui.views.internal.tableview.ITableViewContentProvider#removeItemsChangedListener(org.eclipse.ui.views.internal.tableview.IItemsChangedListener)
*/
public void removeItemsChangedListener(IItemsChangedListener listener) {
listeners.remove(listener);
}
/**
* @return
*/
public int getItemCount() {
//TODO do this more efficiently
return getElements().length;
}
public int getRawItemCount() {
//TODO do this more efficiently
return getUnfilteredElements().length;
}
private void filterList(List list) {
if (filter == null || list == null) {
return;
}
int i = 0;
while (i < list.size()) {
if (filter.select(list.get(i))) {
i++;
}
else {
list.remove(i);
}
}
}
}