2009-06-23 5 views
9

Я применяю ViewerFilter к дереву из нескольких ветвей, но в основном уходит. Фильтр действительно применим к листьям, используя свойства внутри листа. Все ветви остаются нетронутыми, так что их листья могут появиться.Как лучше всего использовать ViewerFilter на TreeViewer?

Однако я бы хотел отфильтровать ветки, которые не содержат выбранных листьев, и я не вижу никакого механизма в пределах ViewerFilter, который позволяет это.

Возможно ли это вообще?

Например, с учетом условной дерево ниже (где b является ветвь, L является листом)

b0 
    b1 
    L2 
    L4 
    L8 
    b2 
    L1 
    L3 
    L5 

Я хотел бы применить ViewerFilter, что только выбирает даже листья и ветки, которые содержат даже листья , Полученное дерево будет ..

b0 
    b1 
    L2 
    L4 
    L8 

.. где филиал b2 не отображается, как она не содержит выбранные детей, но ветви b0 и b1 делать.

ответ

13
class MyFilter extends ViewerFilter{ 

    private boolean isLeaf(Object element){ 
    // implement this 
    } 

    private boolean isEvenLeaf(Object leaf){ 
    // implement this 
    } 

    @Override 
    public boolean select(Viewer viewer, Object parentElement, Object element){ 
    if (isLeaf(element)) 
     return isEventLeaf(element); 
    else { 
     StructuredViewer sviewer = (StructuredViewer) viewer; 
     ITreeContentProvider provider = (ITreeContentProvider) sviewer.getContentProvider(); 
     for (Object child: provider.getChildren(element)){ 
     if (select(viewer, element, child)) 
      return true; 
     } 
     return false; 
    } 
    } 
} 
+0

Я подозреваю, что время работы этого довольно плохо для больших коллекций элементов. Например, все ресурсы являются рабочей областью. Я думаю, что для каждого ресурса он будет посещать все свои ресурсы. Следовательно, * O (n^2) *. Должно быть решение * O (n) *. – Lii

+0

Это решение работает очень плохо, когда у зрителя есть другие фильтры. Например, в случае ресурсов рабочей области, когда другой фильтр отфильтровывает все ресурсы из папки, этот фильтр все равно будет сообщать папке как непустую, так как этот фильтр не знает о другом фильтре. – Lii

0

Я не уверен, что вы подразумеваете под выбранными листьями. Если вы имеете в виду выбранный в представлении, вы можете найти это, вызвав Viewer.getSelection(). Метод select, который вы реализуете в своем фильтре, проходит в средстве просмотра, родительском и листе. Вы должны иметь возможность использовать эту информацию, чтобы решить, выбран ли лист или нет, и отфильтровать их. Если вы можете дать дополнительную информацию, я могу ответить более подробно.

+0

Вместо листьев и ветвей, позволяет говорить о каталогах и файлах. Учитывая произвольное дерево каталогов, я хочу отображать только файлы, соответствующие * .foo. Кроме того, я хотел бы отображать только каталоги, содержащие * .foo-файлы, или рекурсивно содержать каталоги, которые делают. Каталоги, не содержащие таких файлов, не должны отображаться. Помогает ли это? M. –

+0

В этом случае в методе выбора вам нужно будет искать рекурсивно, начиная элемент, получая его дочерние элементы, пока не достигнете ровного листа (return true) или end (return false). – AdamC

1

Да, если вы не отфильтровываете узлы ветвления, они будут показаны, даже если в нем нет листьев. Если вы хотите, чтобы фильтр был постоянно включен, то вы можете рассмотреть, используя ITreeContentProvider в качестве фильтра.

Поскольку у поставщика контента есть методы getChildren() и hasChildren(), у вас есть немного больше контроля.

2

Также обратите внимание на org.eclipse.ui.dialogs.FilteredTree, который подходит для детей.