문제

I'm currently using a FilteredTree with a PatternFilter to display data in a Tree.
My problem is that it only shows the elements matching the pattern and hides their children (except they also match the pattern).

Example:
Tree:

A
-B
--1
--2
-C
--1
--2

Pattern "B" gives me:

A
-B

But I need:

A
-B
--1
--2

I tried a few things but didn't find a nice/easy way to do this. Any ideas?

도움이 되었습니까?

해결책

Thats the default behaviour. Override the PatternFilter.isParentMatch() and PatternFilter.isLeafMatch() to get the right results.

다른 팁

I had the same problem: The element was filtered correctly but no children of the tree node were displayed. The user had to select the found node (in hope it was only one result) then reset the filter and look where the selection appeared along with the children.

Solving this requires overwriting of PatternFilter#isLeafMatch() and retrieving of the (private) field cache from PatternFilter with JavaReflection:

public class MyPatternFilter extends PatternFilter {

    private final Map<Object, Object> patternFilterCache;

    public MyPatternFilter () {
        this.patternFilterCache = getCache();
    }

    @Override
    protected boolean isLeafMatch(final Viewer viewer, final Object element) {
        boolean result = super.isLeafMatch(viewer, element);
        if (result) { // element matches, now add all its children
            traverseChildren(((MyTreeNode) element).getChildren());
        }
        return result;
    }

    // this is to traverse the children of the element found before
    // these children need to be added to the Map 'cache' to be displayed
    void traverseChildren(List<MyTreeNode> children) {  
        // assuming that child.getChildren() is never null!
        for(MyTreeNode child : children) {
            this.patternFilterCache.put(child, child.getChildren().stream().toArray(MyTreeNode[]::new));
            traverseChildren(child.getChildren());
        }
    }

    private Map<Object, Object> getCache() {
        try {
            Field cacheField = this.getClass().getSuperclass().getDeclaredField("cache"); //$NON-NLS-1$
            cacheField.setAccessible(true);
            @SuppressWarnings("unchecked")
            Map<Object, Object> cache = (Map<Object, Object>) cacheField.get(this);
            cacheField.setAccessible(false);
            return cache;
        } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }

}

The obvious drawback is that the Map 'cache' is not API, so - in theory - if the name changes this solution will fail.

It feels so good to post my first answer!

Override isElementVisible() and add return condition.

public class FilePatternFilter extends PatternFilter {
    @Override
    public boolean isElementVisible(Viewer viewer, Object element) {
        File file = (File) element;
        return isParentMatch(viewer, element) || isLeafMatch(viewer, element) || isLeafMatch(viewer, file.getParent());
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top