Wednesday, July 8, 2009

When you use the FilteredTree with a PatternFilter, the visible nodes include the leaves as well as their parents in the tree that match the filter text. However if your usecase requires that a matched node's children also be shown then you need to use a custom PatternFilter which will select an element if any of its ancestors are a match.

Here is how I did it:


public class ShowChildrenPatternFilter extends PatternFilter {

protected boolean isChildMatch(Viewer viewer, Object element) {
System.out.println("inchildmatch");
Object parent = ((ITreeContentProvider) ((AbstractTreeViewer) viewer)
.getContentProvider()).getParent(element);

if(parent!=null){
return (isLeafMatch(viewer, parent)?true:isChildMatch(viewer,parent));
}
return false;

}


@Override
protected boolean isLeafMatch(Viewer viewer, Object element) {
String labelText = ((ILabelProvider) ((StructuredViewer) viewer)
.getLabelProvider()).getText(element);

if(labelText == null) {
return false;
}

return (wordMatches(labelText)?true:isChildMatch(viewer, element));
}
}
Now from a good UI design perspective we should also show the actual pattern matches in a bold font similar to how the default Preferences Dialog filtered tree works.

For that we need our ILabelProvider to implement IFontProvider and in the getFont method we need to call the FilteredTree.getBoldFont method. This method takes a PatternFilter as an argument. This is the filter that is used to select which elements are shown in bold. Since we just want our true matches ( and not their children) to be bolded, we cannot use our modified ShowChildrenPatterFilter. Instead we can just use the regular PatternFilter here. Here is how your LabelProvider class will look:

public class MyFilteredTreeLabelProvider implements ILabelProvider,IFontProvider {

private FilteredTree filterTree;
private PatternFilter filterForBoldElements = new PatternFilter();

public TypeSystemTreeLabelProvider(FilteredTree filterTree) {
super();
this.filterTree = filterTree;
}


@Override
public String getText(Object element) {
//your code to get the display text for the element
}

@Override
public void addListener(ILabelProviderListener listener) {}

@Override
public void dispose() {}

@Override
public boolean isLabelProperty(Object element, String property) {
return false;
}

@Override
public void removeListener(ILabelProviderListener listener) {}

public Font getFont(Object element) {
return FilteredTree.getBoldFont(element, filterTree,
filterForBoldElements);
}
}

2 comments:

Subash said...

The solution did work for me. But I have to collapse all the child nodes if it does not match the filtered text. Do you have any solution for that?

Subash said...
This comment has been removed by the author.

Post a Comment