Version 1.2
Copyright © 2010 - 2011 Lars Vogel
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 | ||
Table of Contents
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.
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; } }
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; } }
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
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.

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.

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; } }
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.
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
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