blob: 435d4b117215918ac6beef9b9f3c38304b4df27b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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
* Cagatay Kavukcuoglu <cagatayk@acm.org> - Filter for markers in same project
*******************************************************************************/
package org.eclipse.ui.views.tasklist;
import java.util.Arrays;
import java.util.HashSet;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.ui.IContainmentAdapter;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
class TasksFilter extends ViewerFilter implements Cloneable {
public static final String[] ROOT_TYPES = new String[] { IMarker.PROBLEM,
IMarker.TASK };
// Filter on resource constants
static final int ON_ANY_RESOURCE = 0;
static final int ON_SELECTED_RESOURCE_ONLY = 1;
static final int ON_SELECTED_RESOURCE_AND_CHILDREN = 2;
static final int ON_ANY_RESOURCE_OF_SAME_PROJECT = 3; // added by cagatayk@acm.org
static final int ON_WORKING_SET = 4;
// Description filter kind constants
static final int FILTER_CONTAINS = 0;
static final int FILTER_DOES_NOT_CONTAIN = 1;
//final static int MINIMUM_MARKER_LIMIT = 10;
final static int DEFAULT_MARKER_LIMIT = 2000;
//final static int MAXIMUM_MARKER_LIMIT = 20000;
String[] types;
int onResource;
IWorkingSet workingSet;
boolean filterOnDescription;
int descriptionFilterKind;
String descriptionFilter;
boolean filterOnSeverity;
int severityFilter;
boolean filterOnPriority;
int priorityFilter;
boolean filterOnCompletion;
int completionFilter;
private boolean filterOnMarkerLimit = true;
private int markerLimit = DEFAULT_MARKER_LIMIT;
private static final String TAG_ID = "id"; //$NON-NLS-1$
private static final String TAG_TYPE = "type"; //$NON-NLS-1$
private static final String TAG_ON_RESOURCE = "onResource"; //$NON-NLS-1$
private static final String TAG_WORKING_SET = "workingSet"; //$NON-NLS-1$
private static final String TAG_FILTER_ON_DESCRIPTION = "filterOnDescription"; //$NON-NLS-1$
private static final String TAG_DESCRIPTION_FILTER_KIND = "descriptionFilterKind"; //$NON-NLS-1$
private static final String TAG_DESCRIPTION_FILTER = "descriptionFilter"; //$NON-NLS-1$
private static final String TAG_FILTER_ON_SEVERITY = "filterOnSeverity"; //$NON-NLS-1$
private static final String TAG_SEVERITY_FILTER = "severityFilter"; //$NON-NLS-1$
private static final String TAG_FILTER_ON_PRIORITY = "filterOnPriority"; //$NON-NLS-1$
private static final String TAG_PRIORITY_FILTER = "priorityFilter"; //$NON-NLS-1$
private static final String TAG_FILTER_ON_COMPLETION = "filterOnCompletion"; //$NON-NLS-1$
private static final String TAG_COMPLETION_FILTER = "completionFilter"; //$NON-NLS-1$
private static final String TAG_FILTER_ON_MARKER_LIMIT = "filterOnMarkerLimit"; //$NON-NLS-1$
private static final String TAG_MARKER_LIMIT = "markerLimit"; //$NON-NLS-1$
public TasksFilter() {
reset();
}
boolean getFilterOnMarkerLimit() {
return filterOnMarkerLimit;
}
void setFilterOnMarkerLimit(boolean filterOnMarkerLimit) {
this.filterOnMarkerLimit = filterOnMarkerLimit;
}
int getMarkerLimit() {
return markerLimit;
}
void setMarkerLimit(int markerLimit) {
if (markerLimit < 1) {
markerLimit = TasksFilter.DEFAULT_MARKER_LIMIT;
}
//if (markerLimit < TasksFilter.MINIMUM_MARKER_LIMIT) {
// markerLimit = TasksFilter.MINIMUM_MARKER_LIMIT;
//} else if (markerLimit > TasksFilter.MAXIMUM_MARKER_LIMIT) {
// markerLimit = TasksFilter.MAXIMUM_MARKER_LIMIT;
//}
this.markerLimit = markerLimit;
}
boolean checkDescription(String desc) {
if (desc == null) { // be paranoid
desc = ""; //$NON-NLS-1$
}
boolean contains = containsSubstring(desc, descriptionFilter);
return descriptionFilterKind == FILTER_CONTAINS ? contains : !contains;
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new Error(); // shouldn't happen
}
}
boolean containsSubstring(String string, String substring) {
int strLen = string.length();
int subLen = substring.length();
int len = strLen - subLen;
for (int i = 0; i <= len; ++i) {
if (string.regionMatches(true, i, substring, 0, subLen)) {
return true;
}
}
return false;
}
/**
* Returns if the given resource is enclosed by a working set element.
* The IContainmentAdapter of each working set element is used for the
* containment test. If there is no IContainmentAdapter for a working
* set element, a simple resource based test is used.
*
* @param element resource to test for enclosure by a working set
* element
* @return true if element is enclosed by a working set element and
* false otherwise.
*/
private boolean isEnclosed(IResource element) {
IPath elementPath = element.getFullPath();
IAdaptable[] workingSetElements = workingSet.getElements();
if (elementPath.isEmpty() || elementPath.isRoot()) {
return false;
}
for (int i = 0; i < workingSetElements.length; i++) {
IAdaptable workingSetElement = workingSetElements[i];
IContainmentAdapter containmentAdapter = (IContainmentAdapter) workingSetElement
.getAdapter(IContainmentAdapter.class);
// if there is no IContainmentAdapter defined for the working
// set element type fall back to using resource based
// containment check
if (containmentAdapter != null) {
if (containmentAdapter.contains(workingSetElement, element,
IContainmentAdapter.CHECK_CONTEXT
| IContainmentAdapter.CHECK_IF_CHILD
| IContainmentAdapter.CHECK_IF_DESCENDANT))
return true;
} else if (isEnclosedResource(element, elementPath,
workingSetElement)) {
return true;
}
}
return false;
}
/**
* Returns if the given resource is enclosed by a working set element.
* A resource is enclosed if it is either a parent of a working set
* element, a child of a working set element or a working set element
* itself.
* Simple path comparison is used. This is only guaranteed to return
* correct results for resource working set elements.
*
* @param element resource to test for enclosure by a working set
* element
* @param elementPath full, absolute path of the element to test
* @return true if element is enclosed by a working set element and
* false otherwise.
*/
private boolean isEnclosedResource(IResource element, IPath elementPath,
IAdaptable workingSetElement) {
IResource workingSetResource = null;
if (workingSetElement.equals(element))
return true;
if (workingSetElement instanceof IResource) {
workingSetResource = (IResource) workingSetElement;
} else {
workingSetResource = (IResource) workingSetElement
.getAdapter(IResource.class);
}
if (workingSetResource != null) {
IPath resourcePath = workingSetResource.getFullPath();
if (resourcePath.isPrefixOf(elementPath))
return true;
}
return false;
}
public void reset() {
types = ROOT_TYPES;
onResource = ON_ANY_RESOURCE;
filterOnDescription = false;
descriptionFilter = ""; //$NON-NLS-1$
filterOnSeverity = false;
severityFilter = 0;
filterOnPriority = false;
priorityFilter = 0;
filterOnCompletion = false;
completionFilter = 0;
filterOnMarkerLimit = true;
markerLimit = DEFAULT_MARKER_LIMIT;
}
/**
* @see IPersistable
*/
public void restoreState(IMemento memento) {
IMemento children[] = memento.getChildren(TAG_TYPE);
types = new String[children.length];
for (int i = 0; i < children.length; i++) {
types[i] = children[i].getString(TAG_ID);
}
Integer ival = memento.getInteger(TAG_ON_RESOURCE);
onResource = ival == null ? ON_ANY_RESOURCE : ival.intValue();
restoreWorkingSet(memento.getString(TAG_WORKING_SET));
ival = memento.getInteger(TAG_FILTER_ON_DESCRIPTION);
filterOnDescription = ival != null && ival.intValue() == 1;
ival = memento.getInteger(TAG_DESCRIPTION_FILTER_KIND);
descriptionFilterKind = ival == null ? FILTER_CONTAINS : ival
.intValue();
descriptionFilter = memento.getString(TAG_DESCRIPTION_FILTER);
if (descriptionFilter == null)
descriptionFilter = ""; //$NON-NLS-1$
ival = memento.getInteger(TAG_FILTER_ON_SEVERITY);
filterOnSeverity = ival != null && ival.intValue() == 1;
ival = memento.getInteger(TAG_SEVERITY_FILTER);
severityFilter = ival == null ? 0 : ival.intValue();
ival = memento.getInteger(TAG_FILTER_ON_PRIORITY);
filterOnPriority = ival != null && ival.intValue() == 1;
ival = memento.getInteger(TAG_PRIORITY_FILTER);
priorityFilter = ival == null ? 0 : ival.intValue();
ival = memento.getInteger(TAG_FILTER_ON_COMPLETION);
filterOnCompletion = ival != null && ival.intValue() == 1;
ival = memento.getInteger(TAG_COMPLETION_FILTER);
completionFilter = ival == null ? 0 : ival.intValue();
ival = memento.getInteger(TAG_FILTER_ON_MARKER_LIMIT);
filterOnMarkerLimit = ival == null || ival.intValue() == 1;
ival = memento.getInteger(TAG_MARKER_LIMIT);
markerLimit = ival == null ? DEFAULT_MARKER_LIMIT : ival.intValue();
}
/**
* Restores the saved working set, if any.
*
* @param the saved working set name or null
*/
private void restoreWorkingSet(String workingSetName) {
if (workingSetName != null) {
IWorkingSetManager workingSetManager = PlatformUI.getWorkbench()
.getWorkingSetManager();
IWorkingSet workingSet = workingSetManager
.getWorkingSet(workingSetName);
if (workingSet != null) {
this.workingSet = workingSet;
}
}
}
/**
* Saves the object state within a memento.
*
* @param memento a memento to receive the object state
*/
public void saveState(IMemento memento) {
for (int i = 0; i < types.length; i++) {
memento.createChild(TAG_TYPE).putString(TAG_ID, types[i]);
}
memento.putInteger(TAG_ON_RESOURCE, onResource);
if (workingSet != null) {
memento.putString(TAG_WORKING_SET, workingSet.getName());
}
memento.putInteger(TAG_FILTER_ON_DESCRIPTION, filterOnDescription ? 1
: 0);
memento.putInteger(TAG_DESCRIPTION_FILTER_KIND, descriptionFilterKind);
memento.putString(TAG_DESCRIPTION_FILTER, descriptionFilter);
memento.putInteger(TAG_FILTER_ON_SEVERITY, filterOnSeverity ? 1 : 0);
memento.putInteger(TAG_SEVERITY_FILTER, severityFilter);
memento.putInteger(TAG_FILTER_ON_PRIORITY, filterOnPriority ? 1 : 0);
memento.putInteger(TAG_PRIORITY_FILTER, priorityFilter);
memento
.putInteger(TAG_FILTER_ON_COMPLETION, filterOnCompletion ? 1
: 0);
memento.putInteger(TAG_COMPLETION_FILTER, completionFilter);
memento.putInteger(TAG_FILTER_ON_MARKER_LIMIT, filterOnMarkerLimit ? 1
: 0);
memento.putInteger(TAG_MARKER_LIMIT, markerLimit);
}
public boolean select(Viewer viewer, Object parentElement, Object element) {
return select((IMarker) element);
}
public boolean select(IMarker marker) {
// resource settings are handled by the content provider
return selectByType(marker) && selectByAttributes(marker)
&& selectByWorkingSet(marker);
}
public boolean select(IMarkerDelta markerDelta) {
// resource settings are handled by the content provider
return selectByType(markerDelta) && selectByAttributes(markerDelta)
&& selectByWorkingSet(markerDelta);
}
private boolean selectByType(IMarker marker) {
for (int i = 0; i < types.length; ++i) {
if (MarkerUtil.isMarkerType(marker, types[i]))
return true;
}
return false;
}
private boolean selectByType(IMarkerDelta markerDelta) {
for (int i = 0; i < types.length; ++i) {
if (markerDelta.isSubtypeOf(types[i]))
return true;
}
return false;
}
/**
* Returns whether the specified marker should be filter out or not.
*
* @param marker the marker to test
* @return
* true=the marker should not be filtered out
* false=the marker should be filtered out
*/
private boolean selectByWorkingSet(IMarker marker) {
if (workingSet == null || onResource != ON_WORKING_SET) {
return true;
}
IResource resource = marker.getResource();
if (resource != null) {
return isEnclosed(resource);
}
return false;
}
/**
* Returns whether the specified marker delta should be filter out
* or not.
*
* @param markerDelta the marker delta to test
* @return
* true=the marker delta should not be filtered out
* false=the marker delta should be filtered out
*/
private boolean selectByWorkingSet(IMarkerDelta markerDelta) {
if (workingSet == null || onResource != ON_WORKING_SET) {
return true;
}
IResource resource = markerDelta.getResource();
if (resource != null) {
return isEnclosed(resource);
}
return false;
}
/*
* WARNING: selectByAttributes(IMarker) and selectByAttributes(IMarkerDelta) must correspond.
*/
private boolean selectByAttributes(IMarker marker) {
// severity filter applies only to problems
if (filterOnSeverity
&& MarkerUtil.isMarkerType(marker, IMarker.PROBLEM)) {
int sev = MarkerUtil.getSeverity(marker);
if ((severityFilter & (1 << sev)) == 0)
return false;
}
// priority and completion filters apply only to tasks
// avoid doing type check more than once
if ((filterOnPriority || filterOnCompletion)
&& MarkerUtil.isMarkerType(marker, IMarker.TASK)) {
if (filterOnPriority) {
int pri = MarkerUtil.getPriority(marker);
if ((priorityFilter & (1 << pri)) == 0)
return false;
}
if (filterOnCompletion) {
boolean complete = MarkerUtil.isComplete(marker);
if ((completionFilter & (complete ? 2 : 1)) == 0)
return false;
}
}
// description applies to all markers
if (filterOnDescription) {
String desc = MarkerUtil.getMessage(marker);
if (!checkDescription(desc))
return false;
}
return true;
}
private boolean selectByAttributes(IMarkerDelta markerDelta) {
// severity filter applies only to problems
if (filterOnSeverity && markerDelta.isSubtypeOf(IMarker.PROBLEM)) {
int sev = markerDelta.getAttribute(IMarker.SEVERITY,
IMarker.SEVERITY_WARNING);
if ((severityFilter & (1 << sev)) == 0)
return false;
}
// priority and completion filters apply only to tasks
// avoid doing type check more than once
if ((filterOnPriority || filterOnCompletion)
&& markerDelta.isSubtypeOf(IMarker.TASK)) {
if (filterOnPriority) {
int pri = markerDelta.getAttribute(IMarker.PRIORITY,
IMarker.PRIORITY_NORMAL);
if ((priorityFilter & (1 << pri)) == 0)
return false;
}
if (filterOnCompletion) {
boolean complete = markerDelta
.getAttribute(IMarker.DONE, false);
if ((completionFilter & (complete ? 2 : 1)) == 0)
return false;
}
}
// description applies to all markers
if (filterOnDescription) {
String desc = markerDelta.getAttribute(IMarker.MESSAGE, ""); //$NON-NLS-1$
if (!checkDescription(desc))
return false;
}
return true;
}
/**
* Returns whether the filter is including all markers.
*
* @return <code>true</code> if the filter includes all markers, <code>false</code> if not
*/
public boolean isShowingAll() {
if (filterOnDescription || filterOnSeverity || filterOnPriority
|| filterOnCompletion) {
return false;
}
if (onResource != ON_ANY_RESOURCE) {
return false;
}
HashSet set = new HashSet(Arrays.asList(types));
if (set.size() != ROOT_TYPES.length) {
return false;
}
for (int i = 0; i < ROOT_TYPES.length; ++i) {
if (!set.contains(ROOT_TYPES[i])) {
return false;
}
}
return true;
}
}