Java - Jface TreeViewer - Steps to create a Tree / TreeViewer





Steps to create a Tree Viewer

Step 1 - Identify the Parent Child Relationship and Objects required for that. Lets take an example of Directory and File Listing. So in that Case our Directory class is the parentClass and File is the childClass.

Step 2 - Identify the way by which child objects would be retrieved using parent objects. For example there could be a method in Directory class for getting files. Lets say - getFiles().

Step 3 - Identofy the way to find the parent using the child object. Lets say method in File Class - getDirectory().

Step 4 - Create a Tree Content Provider Class. This class will establish the relationship between parent and child object.

Tree Content Provider

public class MyTreeContentProvider implements ITreeContentProvider
{

    @Override
    public Object[] getChildren(Object parentElement)
    {
        if (parentElement instanceof Directory)
        {
            return ((Directory) parentElement).getFiles().toArray();
        } else if((parentElement instanceof List)) {
            return ((List) parentElement).toArray();
        }
        else
        {
            return null;
        }
    }

    @Override
    public Object getParent(Object element)
    {
        if (element instanceof childClass)
        {
            return ((parentClass) element.getParent()).
        }
        return null;
    }

    @Override
    public boolean hasChildren(Object element)
    {
        Object[] obj = getChildren(element);
        if (obj == null)
        {
            return false;
        }
        return (obj.length > 0);
    }

    @Override
    public Object[] getElements(Object inputElement)
    {
        if (inputElement instanceof List)
        {
            return ((List) inputElement).toArray();
        }
        else if (inputElement instanceof parentClass)
        {
            return ((parentClass) inputElement).getChildElements().toArray();
        }
        return null;
    }

    @Override
    public void dispose()
    {
    }

    @Override
    public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
    {
    }

}

Step 5 - Create a Tree Label Provider Class. This class will help identify the images and texts to be placed in table tree cells.

Tree Label Provider Class


public class MyTreeLabelProvider extends LabelProvider implements ITableLabelProvider
{
 
    @Override
    public Image getColumnImage(Object element, int columnIndex)
    {
        return null;
    }

    @Override
    public String getColumnText(Object element, int columnIndex)
    {
             
        if (element instanceof ParentClass)
        {
       
            ParentClass parentObj = (ParentClass)element;
   switch (columnIndex)
            {
            case 0:
                displayText = parentObj.getColumn1Value();
            break;
            case 1:
                displayText = parentObj.getColumn2Value();
                break;
            case 2:
            displayText = parentObj.getColumn3Value();
                 break;
   }
         
        } else if (element instanceof ChildClass) {
       
            ChildClass childObj = (ChildClass)element;
   switch (columnIndex)
            {
            case 0:
                displayText = childObj.getColumn1Value();
            break;
            case 1:
                displayText = childObj.getColumn2Value();
                break;
            case 2:
            displayText = childObj.getColumn3Value();
                 break;
   }
         
        }
        return displayText;
    }

}

Step 6 - Create Listener Classes for actions to be taken on events.

Listener Class for Delete Key event


class TestListener implements KeyListener
 {
        @Override
      public void keyPressed(KeyEvent e) {
      if (e.keyCode == SWT.DEL) {
      // Provide the implementation here.
      }
        }

@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub

}
 }
 


Step 7 -  Create the Tree Component

a. Create a composite.
b. new Tree
c. Set Column Header Text and Column Layout.
d. Set the Grid Layout
e. Create a Tree Viewer out of the created Tree
f. Set Content Provider Class for the Tree Viewer
g. Set Label Provider Class for the Tree Viewer
h. Set other Properties
i. Add Listeners to the tree


Code to create Tree


treeViewerComposite = new Composite(this, SWT.NONE);
     
Tree tree = new Tree(treeViewerComposite, SWT.BORDER | SWT.MULTI);
tree.setHeaderVisible(true);
TreeColumnLayout columnLayout = new TreeColumnLayout();
treeViewerComposite.setLayout(columnLayout);

TreeColumn column = new TreeColumn(tree, SWT.NONE);
column.setText(COLUMN1_NAME);
columnLayout.setColumnData(column, new ColumnWeightData(3,0));

column = new TreeColumn(tree, SWT.NONE);
column.setText(COLUMN2_NAME);
columnLayout.setColumnData(column, new ColumnWeightData(3,0));
     
column = new TreeColumn(tree, SWT.NONE);
column.setText(COLUMN7_NAME);
columnLayout.setColumnData(column, new ColumnWeightData(3,0));
             
     
GridDataFactory.fillDefaults().grab(true, true).hint(VIEWER_WIDTH, VIEWER_HEIGHT).applyTo(treeViewerComposite);

TreeViewer treeViewer = new TreeViewer(tree);
treeViewer .setContentProvider(new MyTreeContentProvider ());
treeViewer .setLabelProvider(MyTreeLabelProvider );
treeViewer .getTable().setHeaderVisible(true);
tree.addKeyListener(new TestListener());


Additional Code Snippets 

Code Snippet for implementing a Delete Key Listener to Delete a tree row.

class DeleteModifierKeyListener implements KeyListener
    {
        @Override
      public void keyPressed(KeyEvent e) {
      if (e.keyCode == SWT.DEL) {
      IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
      if (selection.isEmpty()) {
      return;
      } else {
                       TreeItem[] items = treeViewer.getTree().getSelection();
                            for (TreeItem treeItem : items)
                                       {
                                                list.remove(treeItem.getData());
                                       }
                                          treeViewer.refresh();
                        }
            }
       }

       @Override
public void keyReleased(KeyEvent e) {
 // TODO Auto-generated method stub
}
    }

Adding a Context Menu to Tree Viewer 

Menu menu1 = new Menu(treeViewer.getTree());
MenuItem item = new MenuItem(menu1, SWT.PUSH);
item.setText("Test 1");
item.addSelectionListener(new Test1Listener());
 MenuItem item = new MenuItem(menu1, SWT.PUSH);
item1.setText("Test2");
item1.addSelectionListener(new Test2Listener());
   
treeViewer.getTree().setMenu(menu1);

Different Context Menus for Parent and Child Rows

class TreeMenuDetectListener implements MenuDetectListener {

@Override
public void menuDetected(MenuDetectEvent e) {

// get the selected items
                                ISelection selection = (IStructuredSelection) treeViewer.getSelection();

            // define menus - menu 1 if right click on parent tree item
Menu menu1 = new Menu(treeViewer.getTree());
        MenuItem item = new MenuItem(menu1, SWT.PUSH);
        item.setText("Test 1");
        item.addSelectionListener(new Test1Listener());
   
           // menu 2 if right click on child tree item
        Menu menu2 = new Menu(TreeViewer.getTree());
        MenuItem item1 = new MenuItem(menu2, SWT.PUSH);
        item1.setText("Test2");
        item1.addSelectionListener(new Test2Listener());

           // menu 3 if right click on neither the parent tree item or child tree item. ex - menu for headers.
           Menu menu3 = new Menu(TreeViewer.getTree());
        MenuItem item1 = new MenuItem(menu3, SWT.PUSH);
        item1.setText("Test3");
        item1.addSelectionListener(new Test3Listener());
   
                           
                               // check if the tree item selected is parent or child and set the menu accordingly
       if (selection.getFirstElement() instanceof <ParentClass> ) {
 treeViewer.getControl().setMenu(menu1);
} else if (selection.getFirstElement() instanceof <ChildClass> )
          treeViewer.getControl().setMenu(menu2);
        } else {
               treeViewer.getControl().setMenu(menu3);
           }
           // clear the selection
           treeViewer.setSelection(null);
}
});

Changing the width of the Columns

treeViewer.setLayout(columnLayout);

TreeColumn column = new TreeColumn(tree, SWT.NONE);
column.setText(COLUMN1_NAME);
columnLayout.setColumnData(column, new ColumnWeightData(2,0));

column = new TreeColumn(tree, SWT.NONE);
column.setText(COLUMN2_NAME);
columnLayout.setColumnData(column, new ColumnWeightData(1,0));
     
column = new TreeColumn(tree, SWT.NONE);
column.setText(COLUMN7_NAME);
columnLayout.setColumnData(column, new ColumnWeightData(5,0));


So out of the three columns , the first column will take up 2/(2+1+5) = 1/4 of the width , second column will take 1/8 , and third will take rest 5/8.

Specifying the minimum width for the columns

treeViewer.setLayout(columnLayout);

TreeColumn column = new TreeColumn(tree, SWT.NONE);
column.setText(COLUMN1_NAME);
columnLayout.setColumnData(column, new ColumnWeightData(2,3));

column = new TreeColumn(tree, SWT.NONE);
column.setText(COLUMN2_NAME);
columnLayout.setColumnData(column, new ColumnWeightData(1,1));
     
column = new TreeColumn(tree, SWT.NONE);
column.setText(COLUMN3_NAME);
columnLayout.setColumnData(column, new ColumnWeightData(5,10));

Expand the tree by default

treeViewer.expandAll();

Setting / unsetting the tree row selection 

treeViewer.setSelection(null);
ISelection selection = (IStructuredSelection) treeViewer.getSelection();
treeViewer.setSelection(selection