by Lars Vogel

Follow me on twitter

Lars Vogel on Google+

Eclipse JFace Tree - Tutorial

Lars Vogel

Version 1.2

24.08.2011

Revision History
Revision 0.1 22.08.2010 Lars
Vogel
Created
Revision 0.2 - 1.2 12.09.2010 - 24.08.2011 Lars
Vogel
bug fixes and enhancements

Eclipse JFace Tree

This article explains the usage of Eclipse JFace TreeViewer. It is is based on Eclipse 3.7 (Indigo).


Table of Contents

1. Overview
2. Example
3. Content and LabelProvider
3.1. Build your ContentProvider
3.2. Build your LabelProvider
4. View
5. StyledLabelProvider
6. File Browser
7. Thank you
8. Questions and Discussion
9. Links and Literature
9.1. Source Code
9.2. JFace Resources
9.3. vogella Resources

1. Overview

JFace provides functionality to build tables. The following provides an example how to build a tree with the JFace Viewer framework. Please see Introduction to JFace for an introduction to the concepts behind this example.

For an example on how to build JFace Tables please see JFace Table Tutorial.

2. Example

In this tutorial we will build a Eclipse RCP which will display a domain model in a JFace tree. The domain model represents the data of todo items, grouped by categories.

Create a new RCP Project "de.vogella.jface.treeviewer" (see Create your first Eclipse RCP application for details). Use the "RCP application with a view" as a template.

We will now create the model which will hold our application data. Create a package "de.vogella.jface.treeviewer" and create the following classes.

			
package de.vogella.jface.treeviewer.model;

public class Todo {
	private String summary="";
	private String description="";
	
	public Todo(String summary) {
		this.summary = summary;
	}
	
	public Todo(String summary, String description){
		this.summary = summary;
		this.description = description;
		
	}
	
	public String getSummary() {
		return summary;
	}
	public void setSummary(String summary) {
		this.summary = summary;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	
	
}

		

			
package de.vogella.jface.treeviewer.model;

import java.util.ArrayList;
import java.util.List;

public class Category {
	private String name;
	private int sort;
	private List<Todo> todos = new ArrayList<Todo>();
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getSort() {
		return sort;
	}
	public void setSort(int sort) {
		this.sort = sort;
	}
	
	public List<Todo> getTodos (){
		return todos;
	}
	
	
}

		

The following class will provide example data for the tree.

			
package de.vogella.jface.treeviewer.model;

import java.util.ArrayList;
import java.util.List;

public class TodoMockModel  {

	public List<Category> getCategories() {
		List<Category> categories = new ArrayList<Category>();
		Category category = new Category();
		category.setName("Programming");
		categories.add(category);
		Todo todo = new Todo("Write more about e4");
		category.getTodos().add(todo);
		todo = new Todo("Android", "Write a widget.");
		category.getTodos().add(todo);
		
		category = new Category();
		category.setName("Leasure");
		categories.add(category);
		todo = new Todo("Skiing");
		category.getTodos().add(todo);
		
		return categories;
	}

}

		

3. Content and LabelProvider

3.1. Build your ContentProvider

Create the following class "TodoContentProvider" which implement the Interface "org.eclipse.jface.viewers.ITreeContentProvider".

				
package de.vogella.jface.treeviewer.provider;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;

import de.vogella.jface.treeviewer.model.Category;
import de.vogella.jface.treeviewer.model.TodoMockModel;

public class TodoContentProvider implements ITreeContentProvider {

	private TodoMockModel model;

	@Override
	public void dispose() {
	}

	@Override
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		this.model = (TodoMockModel) newInput;
	}

	@Override
	public Object[] getElements(Object inputElement) {
		return model.getCategories().toArray();
	}

	@Override
	public Object[] getChildren(Object parentElement) {
		if (parentElement instanceof Category) {
			Category category = (Category) parentElement;
			return category.getTodos().toArray();
		}
		return null;
	}

	@Override
	public Object getParent(Object element) {
		return null;
	}

	@Override
	public boolean hasChildren(Object element) {
		if (element instanceof Category) {
			return true;
		}
		return false;
	}

}

			

3.2. Build your LabelProvider

Create the following class "TodoLabelProvider".

				
package de.vogella.jface.treeviewer.provider;

import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;

import de.vogella.jface.treeviewer.model.Category;
import de.vogella.jface.treeviewer.model.Todo;

public class TodoLabelProvider extends LabelProvider {
	@Override
	public String getText(Object element) {
		if (element instanceof Category) {
			Category category = (Category) element;
			return category.getName();
		}
		return ((Todo) element).getSummary();
	}

	@Override
	public Image getImage(Object element) {
		if (element instanceof Category) {
			return PlatformUI.getWorkbench().getSharedImages()
					.getImage(ISharedImages.IMG_OBJ_FOLDER);
		}
		return PlatformUI.getWorkbench().getSharedImages()
		.getImage(ISharedImages.IMG_OBJ_FILE);
	}

}
			

Important thing to note:

  • getColumnText: will return the value for a certain element, e.g. in our example row and column. May not be null.

  • getColumnImage: will return the image for a certain element and a certain column. May be null

4. View

Change the View.java to the following. We will use some shared images from the workbench.

			
package de.vogella.jface.treeviewer;

import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

import de.vogella.jface.treeviewer.model.TodoMockModel;
import de.vogella.jface.treeviewer.provider.TodoContentProvider;
import de.vogella.jface.treeviewer.provider.TodoLabelProvider;

public class View extends ViewPart {
	public static final String ID = "de.vogella.jface.treeviewer.view";
	private TreeViewer viewer;
	public void createPartControl(Composite parent) {
		viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL);
		viewer.setContentProvider(new TodoContentProvider());
		viewer.setLabelProvider(new TodoLabelProvider());
		// Expand the tree 
		viewer.setAutoExpandLevel(2);
		// Provide the input to the ContentProvider
		viewer.setInput(new TodoMockModel());
	}

	
/** * Passing the focus request to the viewer's control. */
public void setFocus() { viewer.getControl().setFocus(); } }

If you run your application the result should look like the following.

5. StyledLabelProvider

The class "StyledLabelProvider" allows to influence the appearance of the label. If you use this as the basis for your LabelProvider you have to override the update(ViewerCell) method. Here is an example which will add the number of the entries in a counter style format.

			
package de.vogella.jface.treeviewer.provider;

import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;

import de.vogella.jface.treeviewer.model.Category;
import de.vogella.jface.treeviewer.model.Todo;

public class TodoLabelProvider extends StyledCellLabelProvider {
	@Override
	public void update(ViewerCell cell) {
		Object element = cell.getElement();
		StyledString text = new StyledString();

		if (element instanceof Category) {
			Category category = (Category) element;
			text.append(category.getName());
			cell.setImage(PlatformUI.getWorkbench().getSharedImages()
					.getImage(ISharedImages.IMG_OBJ_FOLDER));
			text.append(" ( " +category.getTodos().size() + " ) ", StyledString.COUNTER_STYLER);
		} else {
			Todo todo = (Todo) element;
			text.append(todo.getSummary());
			cell.setImage(PlatformUI.getWorkbench().getSharedImages()
					.getImage(ISharedImages.IMG_OBJ_FILE));
		}
		cell.setText(text.toString());
		cell.setStyleRanges(text.getStyleRanges());
		super.update(cell);
	}
}
		

If you run your application the result should look like the following.

6. File Browser

Here is the Composite implementation for the File browser in an Eclipse application.

			
import java.io.File;
import java.net.URL;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;

public class MyComposite extends Composite {

	public MyComposite(Composite parent, int style) {
		super(parent, style);
		viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
		viewer.setContentProvider(new ViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		viewer.setInput(File.listRoots());
	}

	private TreeViewer viewer;

	class ViewContentProvider implements ITreeContentProvider {
		public void inputChanged(Viewer v, Object oldInput, Object newInput) {
		}

		@Override
		public void dispose() {
		}

		@Override
		public Object[] getElements(Object inputElement) {
			return (File[]) inputElement;
		}

		@Override
		public Object[] getChildren(Object parentElement) {
			File file = (File) parentElement;
			return file.listFiles();
		}

		@Override
		public Object getParent(Object element) {
			return ((File) element).getParentFile();
		}

		@Override
		public boolean hasChildren(Object element) {
			File file = (File) element;
			if (file.isDirectory()) {
				return true;
			}
			return false;
		}

	}

	class ViewLabelProvider extends LabelProvider {
		@Override
		public String getText(Object element) {
			File file = (File) element;
			String name = file.getName();
			if (name.length() > 0) {
				return name;
			}
			return file.getPath();
		}

		public Image getImage(Object obj) {
			Bundle bundle = FrameworkUtil.getBundle(this.getClass());
			URL url = FileLocator.find(bundle, new Path(
					"icons/alt_window_32.gif"), null);
			ImageDescriptor image = ImageDescriptor.createFromURL(url);
			return image.createImage();
		}
	}

	@Override
	public boolean setFocus() {
		viewer.getControl().setFocus();
		return true;
	}

}
		

7. Thank you

Please help me to support this article:

Flattr this

8. Questions and Discussion

Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.de Google Group. I have created a short list how to create good questions which might also help you.

9. Links and Literature

9.1. Source Code

Source Code of Examples

9.2. JFace Resources

http://www.eclipse.org/articles/Article-Table-viewer/table_viewer.html Building and delivering a table editor with SWT/JFace

http://wiki.eclipse.org/index.php/JFaceSnippets JFace snippets, e.g. small code examples

9.3. vogella Resources

Eclipse RCP Training (German) Eclipse RCP Training with Lars Vogel

Android Tutorial Introduction to Android Programming

GWT Tutorial Program in Java and compile to JavaScript and HTML

Eclipse RCP Tutorial Create native applications in Java

JUnit Tutorial Test your application

Git Tutorial Put everything you have under distributed version control system