vogella.de

Follow me on twitter
About Lars Vogel
Flattr this

Eclipse JFace Table - Tutorial

Clemens Muessener, Lars Vogel

Version 2.0

22.08.2010

Revision History
Revision 0.101.07.2007Clemens Muessener, Lars Vogel
Created Article
Revision 0.2 - 2.0 12.09.2007 - 22.08.2010Lars Vogel
bug fixes and enhancements

Eclipse JFace Table

This article explains the usage of Eclipse JFace TableViewer including label and contentprovider, filtering, sorting, and model / view interaction.

This article is based on Eclipse 3.6 (Helios).


Table of Contents

1. Eclipse JFace viewers
1.1. Overview
1.2. Elements of a JFace Viewer
2. Overview of the example
3. Create a project
4. Create the model
5. Content and LabelProvider
5.1. Build your ContentProvider
5.2. Build your LabelProvider
5.3. Use the providers
5.4. Run
6. Cell Editors
7. Sort Columns
8. Filter
9. Highlighting elements - StyledCellLabelProvider
10. Show/Hide Columns
11. Commands
11.1. Print the model content
11.2. Add and delete a person to and from the model
11.3. Copy data to the system clipboard
12. Thank you
13. Questions and Discussion
14. Download
15. Links and Literature
15.1. Source Code
15.2. JFace Resources
15.3. vogella Resources

1. Eclipse JFace viewers

1.1. Overview

Eclipse JFace viewers allow to display a domain model in a list, tree or table without converting the domain model beforehand. These viewers are based on content providers which provide the model to the viewer and label provider which define how the model data is displayed in the viewer. This separation allows to re-use components.

1.2. Elements of a JFace Viewer

The user interface is represented by the JFace viewer. For example JFace defines the following viewers:

Table 1. JFace Viewers

ClassDescription
org.eclipse.jface.viewers.ListViewerDisplay a simple list
org.eclipse.jface.viewers.TreeViewerDisplays a tree
org.eclipse.jface.viewers.TableViewerDisplays a table

The content provider is responsible for providing objects to the view. It can simply return objects without performing any conversion. The content provider makes no assumption how the data model is displayed by the view. This is the responsibility of the label provider. Typical content provider are:

Table 2. Content Provider

ClassDescription
IStructuredContentProviderUsed for lists and tables
ITreeContentProviderUsed for trees, has addional methods to determine the children and the parents of elements

Label providers define how objects are displayed, e.g. which part of the object is used to return the text which is displayed. Label provider follow usually the template approach; you have an interface which describes and contact and a class which the programmer can use which delivers already reasonable implementations for the interface and the programmer can then choose to override only the relevant methods.

Typical label providers are

Table 3. Label providers

InterfaceTemplate classDescription
ILabelProviderLabelProviderUsed for lists and trees, displays per element a icons and / or a text element.
ITableLabelProviderLabelProviderUsed for tables, displays per element and column a icons and / or a text element

2. Overview of the example

In this tutorial we will build a Eclipse RCP which will display data of persons in a JFace table. The domain model represents the data of persons (first name, last name, gender and if he/she is married). Each person is displayed in one row in the table.

Different editors and label provider will be used for different data types. The article demonstrate how to sort based on different table columns and how to use filters to display only selected content of the viewer. We will then learn how to use StyledCellLabelProvider to influence the display of data in the table. The usage of commands and how to hide and sort table columns is demonstrated.

The application will also be able to change the first name and last name like a text editor, the gender by a drop down list and the married status by a checkbox. You can edit the objects on two ways: an inline editor in the table and within a editor.

Via the menu it will be possible to add new persons to the table and to remove persons from the table. You will also be able to show/hide columns.

The final application will look like this.

3. Create a project

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

4. Create the model

Create a package "de.vogella.jface.tableviewer.model".

Create the following class "Person". This class contains the first name, last name, gender and married status for a person and represents the data model for this example.

			
package de.vogella.jface.tableviewer.model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class Person {
	private String firstName;
	private String lastName;
	private boolean married;
	private String gender;
	private Integer age;
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
			this);

	public Person() {
	}

	public Person(String firstName, String lastName, String gender,
			boolean married) {
		super();
		this.firstName = firstName;
		this.lastName = lastName;
		this.gender = gender;
		this.married = married;
	}

	public void addPropertyChangeListener(String propertyName,
			PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
	}

	public void removePropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(listener);
	}

	public String getFirstName() {
		return firstName;
	}

	public String getGender() {
		return gender;
	}

	public String getLastName() {
		return lastName;
	}

	public boolean isMarried() {
		return married;
	}

	public void setFirstName(String firstName) {
		propertyChangeSupport.firePropertyChange("firstName", this.firstName,
				this.firstName = firstName);
	}

	public void setGender(String gender) {
		propertyChangeSupport.firePropertyChange("gender", this.gender,
				this.gender = gender);
	}

	public void setLastName(String lastName) {
		propertyChangeSupport.firePropertyChange("lastName", this.lastName,
				this.lastName = lastName);
	}

	public void setMarried(boolean isMarried) {
		propertyChangeSupport.firePropertyChange("married", this.married,
				this.married = isMarried);
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		propertyChangeSupport.firePropertyChange("age", this.age,
				this.age = age);
	}

	@Override
	public String toString() {
		return firstName + " " + lastName;
	}

}
		

Tip

This class has also propertyChange support, which is not necessary for this example. Feel free to ignore this and implement your own POJO's with only the getter and setters.

Now create a class, called "ModelProvider". This class will be providing the collection of persons. This class is defined as a Singleton .

			
package de.vogella.jface.tableviewer.model;

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

public class ModelProvider {

	private static ModelProvider content;
	private List<Person> persons;

	private ModelProvider() {
		persons = new ArrayList<Person>();
		// Image here some fancy database access to read the persons and to
		// put them into the model
		Person person;
		person = new Person("Rainer", "Zufall", "male", true);
		persons.add(person);
		person = new Person("Rainer", "Babbel", "male", true);
		persons.add(person);
		person = new Person("Marie", "Darms", "female", false);
		persons.add(person);
		person = new Person("Holger", "Adams", "male", true);
		persons.add(person);
		person = new Person("Juliane", "Adams", "female", true);
		persons.add(person);

	}

	public static synchronized ModelProvider getInstance() {
		if (content != null) {
			return content;
		}
		content = new ModelProvider();
		return content;
	}

	public List<Person> getPersons() {
		return persons;
	}

}

		

5. Content and LabelProvider

5.1. Build your ContentProvider

Create the package "de.vogella.jface.tableviewer.providers". Create the class "PersonContentProvider" which implement the Interface "org.eclipse.jface.viewers.IStructuredContentProvider". This class reads the data model and returns the data as an array.

				
package de.vogella.jface.tableviewer.providers;

import java.util.List;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.Viewer;

import de.vogella.jface.tableviewer.model.Person;

public class PersonContentProvider implements IStructuredContentProvider {

	@Override
	public Object[] getElements(Object inputElement) {
		@SuppressWarnings("unchecked")
		List<Person> persons = (List<Person>) inputElement;
		return persons.toArray();
	}

	@Override
	public void dispose() {
	}

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

}

			

The method getElements() will be called by the viewer. The viewer has method setInput(). This input will be provided to the contentProvider as the parameter in method getElements().

5.2. Build your LabelProvider

We will use icons for the married Status. If the folder "icons" does not exists in your project create it. Download the icons from the link provided at the end of this article and place the two icons in the folder icons. You can also return null in the method getColumnImage() of the label provider in case you don't want to use the icons.

Create class "PersonLabelProvider" implementing the interface org.eclipse.jface.viewers.ITableLabelProvider.

				
package de.vogella.jface.tableviewer.providers;

import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import de.vogella.jface.tableviewer.Activator;

import de.vogella.jface.tableviewer.model.Person;

public class PersonLabelProvider extends LabelProvider implements
		ITableLabelProvider {
	// We use icons
	// We use icons
	private static final Image CHECKED = Activator.getImageDescriptor(
			"icons/checked.gif").createImage();
	private static final Image UNCHECKED = Activator.getImageDescriptor(
					"icons/unchecked.gif").createImage();

	@Override
	public Image getColumnImage(Object element, int columnIndex) {
		// In case you don't like image just return null here
		if (columnIndex == 3) {
			if (((Person) element).isMarried()) {
				return CHECKED;
			} else {
				return UNCHECKED;
			}
		}
		return null;
	}

	@Override
	public String getColumnText(Object element, int columnIndex) {
		Person person = (Person) element;
		switch (columnIndex) {
		case 0:
			return person.getFirstName();
		case 1:
			return person.getLastName();
		case 2:
			return person.getGender();
		case 3:
			return String.valueOf(person.isMarried());
		default:
			throw new RuntimeException("Should not happen");
		}

	}

}

			

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

5.3.  Use the providers

Change the class "View.java" to the following to use your content and label providers.

				
package de.vogella.jface.tableviewer;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.ui.part.ViewPart;

import de.vogella.jface.tableviewer.model.ModelProvider;
import de.vogella.jface.tableviewer.providers.PersonContentProvider;
import de.vogella.jface.tableviewer.providers.PersonLabelProvider;

public class View extends ViewPart {
	public static final String ID = "de.vogella.jface.tableviewer.view";

	private TableViewer viewer;

	public void createPartControl(Composite parent) {
		createViewer(parent);
		// Get the content for the viewer, setInput will call getElements in the
		// contentProvider
		viewer.setInput(ModelProvider.getInstance().getPersons());
	}

	private void createViewer(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION);
		createColumns(viewer);
		viewer.setContentProvider(new PersonContentProvider());
		viewer.setLabelProvider(new PersonLabelProvider());
	}

	// This will create the columns for the table
	private void createColumns(TableViewer viewer) {

		String[] titles = { "First name", "Last name", "Gender", "Married" };
		int[] bounds = { 100, 100, 100, 100 };

		for (int i = 0; i < titles.length; i++) {
			TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
			column.getColumn().setText(titles[i]);
			column.getColumn().setWidth(bounds[i]);
			column.getColumn().setResizable(true);
			column.getColumn().setMoveable(true);
		}
		Table table = viewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
	}

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

			

The method createColumns create the table columns, headers, sets the size of the columns, makes the columns resizable and show the lines in the table.

5.4. Run

Run the example. The application should look like this.

6. Cell Editors

A cell editor defines how the user can edit certain cells of a table.

We will define the editors for our table. The "First name" and "Last name" column will be editable by a textfield. The "Gende"’ column will be editable by a drop down list and the "Married" column will be editable by a checkbox.

Create a new class with the name "PersonEditingSupport" in package de.vogella.jface.tableviewer.providers.

			
package de.vogella.jface.tableviewer.providers;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckboxCellEditor;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;

import de.vogella.jface.tableviewer.model.Person;

public class PersonEditingSupport extends EditingSupport {
	private CellEditor editor;
	private int column;

	public PersonEditingSupport(ColumnViewer viewer, int column) {
		super(viewer);

		String[] gender = new String[2];
		gender[0] = "male";
		gender[1] = "female";

		// Create the correct editor based on the column index
		switch (column) {
		case 2:
			editor = new ComboBoxCellEditor(((TableViewer) viewer).getTable(),
					gender);
			break;
		case 3:
			editor = new CheckboxCellEditor(null, SWT.CHECK | SWT.READ_ONLY);
			break;
		default:
			editor = new TextCellEditor(((TableViewer) viewer).getTable());
		}
		this.column = column;
	}

	@Override
	protected boolean canEdit(Object element) {
		return true;
	}

	@Override
	protected CellEditor getCellEditor(Object element) {
		return editor;
	}

	@Override
	protected Object getValue(Object element) {
		Person person = (Person) element;

		switch (this.column) {
		case 0:
			return person.getFirstName();
		case 1:
			return person.getLastName();
		case 2:
			if (person.getGender().equals("male")) {
				return 0;
			}
			return 1;
		case 3:
			return person.isMarried();
		default:
			break;
		}
		return null;
	}

	@Override
	protected void setValue(Object element, Object value) {
		Person pers = (Person) element;

		switch (this.column) {
		case 0:
			pers.setFirstName(String.valueOf(value));
			break;
		case 1:
			pers.setLastName(String.valueOf(value));
			break;
		case 2:
			if (((Integer) value) == 0) {
				pers.setGender("male");
			} else {
				pers.setGender("female");
			}
			break;
		case 3:
			pers.setMarried((Boolean) value);
			break;
		default:
			break;
		}

		getViewer().update(element, null);
	}

}

		

Explanation of the the main methods of "PersonEditingSupport":

  • ‘getCellEditor’ : In this method you return the celleditor you want to use (e.g. Texteditor). I work with a ‘switch-case-command’ to split my columns and give every column its own celleditor.

  • ‘setValue’: Receives the new value the user gives. You have to set the new value to the object which is given, too.

  • ‘getValue’: Receives the object which was changed and returns the value for the table. You have to return the new value of the object.

Now assign the editors to your columns. We do this in View.java in the method createColumns().

			
// This will create the columns for the table
	private void createColumns(TableViewer viewer) {

		String[] titles = { "First name", "Last name", "Gender", "Married" };
		int[] bounds = { 100, 100, 100, 100 };

		for (int i = 0; i < titles.length; i++) {
			TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
			column.getColumn().setText(titles[i]);
			column.getColumn().setWidth(bounds[i]);
			column.getColumn().setResizable(true);
			column.getColumn().setMoveable(true);
			// enable editing support
			column.setEditingSupport(new PersonEditingSupport(viewer, i));
		}
		Table table = viewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
	}
		

Run now your application. You should now be able to modify the content of the JFace table.

7. Sort Columns

This chapter explains how to to sort the columns of the table ascending/descending.

Create a new Class "de.vogella.jface.tableviewer.sorter.TableSorter.java"

			
package de.vogella.jface.tableviewer.sorter;

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

import de.vogella.jface.tableviewer.model.Person;

public class TableSorter extends ViewerSorter {
	private int propertyIndex;
	// private static final int ASCENDING = 0;
	private static final int DESCENDING = 1;

	private int direction = DESCENDING;

	public TableSorter() {
		this.propertyIndex = 0;
		direction = DESCENDING;
	}

	public void setColumn(int column) {
		if (column == this.propertyIndex) {
			// Same column as last sort; toggle the direction
			direction = 1 - direction;
		} else {
			// New column; do an ascending sort
			this.propertyIndex = column;
			direction = DESCENDING;
		}
	}

	@Override
	public int compare(Viewer viewer, Object e1, Object e2) {
		Person p1 = (Person) e1;
		Person p2 = (Person) e2;
		int rc = 0;
		switch (propertyIndex) {
		case 0:
			rc = p1.getFirstName().compareTo(p2.getFirstName());
			break;
		case 1:
			rc = p1.getLastName().compareTo(p2.getLastName());
			break;
		case 2:
			rc = p1.getGender().compareTo(p2.getGender());
			break;
		case 3:
			if (p1.isMarried() == p2.isMarried()) {
				rc = 0;
			} else
				rc = (p1.isMarried() ? 1 : -1);
			break;
		default:
			rc = 0;
		}
		// If descending order, flip the direction
		if (direction == DESCENDING) {
			rc = -rc;
		}
		return rc;
	}
}
		

Add a listener to the view for setting the information which column should be sorted. Change View.java to the following-

			
package de.vogella.jface.tableviewer;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.part.ViewPart;

import de.vogella.jface.tableviewer.model.ModelProvider;
import de.vogella.jface.tableviewer.providers.PersonContentProvider;
import de.vogella.jface.tableviewer.providers.PersonEditingSupport;
import de.vogella.jface.tableviewer.providers.PersonLabelProvider;
import de.vogella.jface.tableviewer.sorter.TableSorter;

public class View extends ViewPart {
	public static final String ID = "de.vogella.jface.tableviewer.view";

	private TableViewer viewer;

	private TableSorter tableSorter;

	public void createPartControl(Composite parent) {
		createViewer(parent);
		// Get the content for the viewer, setInput will call getElements in the
		// contentProvider
		viewer.setInput(ModelProvider.getInstance().getPersons());
		// Make the selection available
		getSite().setSelectionProvider(viewer);
		// Set the sorter for the table
		tableSorter = new TableSorter();
		viewer.setSorter(tableSorter);

	}
	
	private void createViewer(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION);
		createColumns(viewer);
		viewer.setContentProvider(new PersonContentProvider());
		viewer.setLabelProvider(new PersonLabelProvider());
	}

	public TableViewer getViewer() {
		return viewer;
	}

	// This will create the columns for the table
	private void createColumns(final TableViewer viewer) {
		Table table = viewer.getTable();
		String[] titles = { "First name", "Last name", "Gender", "Married" };
		int[] bounds = { 100, 100, 100, 100 };

		for (int i = 0; i < titles.length; i++) {
			final int index = i;
			final TableViewerColumn viewerColumn = new TableViewerColumn(
					viewer, SWT.NONE);
			final TableColumn column = viewerColumn.getColumn();
			column.setText(titles[i]);
			column.setWidth(bounds[i]);
			column.setResizable(true);
			column.setMoveable(true);
			// Setting the right sorter
			column.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					tableSorter.setColumn(index);
					int dir = viewer.getTable().getSortDirection();
					if (viewer.getTable().getSortColumn() == column) {
						dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
					} else {

						dir = SWT.DOWN;
					}
					viewer.getTable().setSortDirection(dir);
					viewer.getTable().setSortColumn(column);
					viewer.refresh();
				}
			});
			viewerColumn.setEditingSupport(new PersonEditingSupport(viewer, i));
		}
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
	}

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

Run the example, click on a column, there will appear a sort-direction signifier and your items are ordered ascending or descending.

8. Filter

Now we would like to add a filter to the table. The user should have a text field in which we can enter a first- or lastname. Only the names which applies to this filter should get displayed.

Adding a filter to a view is simple, you use method addFilter() on the viewer, which expects a ViewFilter as argument. Each ViewFilter is checked the input on the viewer is changed of whenever the viewer.refresh();

Create a new Class "de.vogella.jface.tableviewer.filter.PersonFilter.java"

			
package de.vogella.jface.tableviewer.filter;

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

import de.vogella.jface.tableviewer.model.Person;

public class PersonFilter extends ViewerFilter {

	private String searchString;

	public void setSearchText(String s) {
		// Search must be a substring of the existing value
		this.searchString = ".*" + s + ".*";
	}

	@Override
	public boolean select(Viewer viewer, Object parentElement, Object element) {
		if (searchString == null || searchString.length() == 0) {
			return true;
		}
		Person p = (Person) element;
		if (p.getFirstName().matches(searchString)) {
			return true;
		}
		if (p.getLastName().matches(searchString)) {
			return true;
		}

		return false;
	}
}

		

We will create a new text field in which the user can search. This text field will have a keyListener which updates the filter and the viewer. Change the View.java to the following .

			
package de.vogella.jface.tableviewer;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

import de.vogella.jface.tableviewer.filter.PersonFilter;
import de.vogella.jface.tableviewer.model.ModelProvider;
import de.vogella.jface.tableviewer.providers.PersonContentProvider;
import de.vogella.jface.tableviewer.providers.PersonEditingSupport;
import de.vogella.jface.tableviewer.providers.PersonLabelProvider;
import de.vogella.jface.tableviewer.sorter.TableSorter;

public class View extends ViewPart {
	public static final String ID = "de.vogella.jface.tableviewer.view";

	private TableViewer viewer;

	private TableSorter tableSorter;

	private PersonFilter filter;

	public void createPartControl(Composite parent) {
		GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		Label searchLabel = new Label(parent, SWT.NONE);
		searchLabel.setText("Search: ");
		final Text searchText = new Text(parent, SWT.BORDER | SWT.SEARCH);
		searchText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
				| GridData.HORIZONTAL_ALIGN_FILL));
		searchText.addKeyListener(new KeyAdapter() {
			public void keyReleased(KeyEvent ke) {
				filter.setSearchText(searchText.getText());
				viewer.refresh();
			}

		});
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
		createColumns(viewer);
		viewer.setContentProvider(new PersonContentProvider());
		viewer.setLabelProvider(new PersonLabelProvider());
		// Get the content for the viewer, setInput will call getElements in the
		// contentProvider
		viewer.setInput(ModelProvider.getInstance().getPersons());
		// Make the selection available
		getSite().setSelectionProvider(viewer);
		// Set the sorter for the table
		tableSorter = new TableSorter();
		viewer.setSorter(tableSorter);
		filter = new PersonFilter();
		viewer.addFilter(filter);

		// Layout the viewer
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		viewer.getControl().setLayoutData(gridData);
	}

	public TableViewer getViewer() {
		return viewer;
	}

	// This will create the columns for the table
	private void createColumns(final TableViewer viewer) {
		Table table = viewer.getTable();
		String[] titles = { "First name", "Last name", "Gender", "Married" };
		int[] bounds = { 100, 100, 100, 100 };

		for (int i = 0; i < titles.length; i++) {
			final int index = i;
			final TableViewerColumn viewerColumn = new TableViewerColumn(
					viewer, SWT.NONE);
			final TableColumn column = viewerColumn.getColumn();
			column.setText(titles[i]);
			column.setWidth(bounds[i]);
			column.setResizable(true);
			column.setMoveable(true);
			// Setting the right sorter
			column.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					tableSorter.setColumn(index);
					int dir = viewer.getTable().getSortDirection();
					if (viewer.getTable().getSortColumn() == column) {
						dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
					} else {

						dir = SWT.DOWN;
					}
					viewer.getTable().setSortDirection(dir);
					viewer.getTable().setSortColumn(column);
					viewer.refresh();
				}
			});
			viewerColumn.setEditingSupport(new PersonEditingSupport(viewer, i));
		}
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
	}

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

Run the example, filtering should work.

9. Highlighting elements - StyledCellLabelProvider

It is also possible to use a StyleCellLabelProvider to highlight the search result. StyleCellLabelProvider can do much more but we will look at the simple case.

First create the following helper class which will determine which occurrence of the search string is in the column.

			
package de.vogella.jface.tableviewer.util;

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

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.widgets.Display;

public class SearchUtil {
	public static int[] getSearchTermOccurrences(String searchTerm,
			String content) {
		List<StyleRange> styleRange;
		List<Integer> ranges;
		Display disp = Display.getCurrent();
		StyleRange myStyleRange = new StyleRange(0, 0, null, disp
				.getSystemColor(SWT.COLOR_YELLOW));

		styleRange = new ArrayList<StyleRange>(); // reset the StyleRange-Array
		// for each new field
		ranges = new ArrayList<Integer>(); // reset the ranges-array
		// empty search term ==> return an empty StyleRange array
		if (searchTerm.equals("")) {
			return new int[] {};
		}

		// determine all occurrences of the searchText and write the beginning
		// and length of each occurrence into an array
		for (int i = 0; i < content.length(); i++) {
			if (i + searchTerm.length() <= content.length()
					&& content.substring(i, i + searchTerm.length())
							.equalsIgnoreCase(searchTerm)) {
				// ranges format: n->start of the range, n+1->length of the
				// range
				ranges.add(i);
				ranges.add(searchTerm.length());
			}
		}
		// convert the list into an int[] and make sure that overlapping
		// search term occurrences are are merged
		int[] intRanges = new int[ranges.size()];
		int arrayIndexCounter = 0;
		for (int listIndexCounter = 0; listIndexCounter < ranges.size(); listIndexCounter++) {
			if (listIndexCounter % 2 == 0) {
				if (searchTerm.length() > 1
						&& listIndexCounter != 0
						&& ranges.get(listIndexCounter - 2)
								+ ranges.get(listIndexCounter - 1) >= ranges
								.get(listIndexCounter)) {
					intRanges[arrayIndexCounter - 1] = 0
							- ranges.get(listIndexCounter - 2)
							+ ranges.get(listIndexCounter)
							+ ranges.get(++listIndexCounter);
				} else {
					intRanges[arrayIndexCounter++] = ranges
							.get(listIndexCounter);
				}
			} else {
				intRanges[arrayIndexCounter++] = ranges.get(listIndexCounter);
				styleRange.add(myStyleRange);
			}
		}
		// if there have been any overlappings we need to reduce the size of
		// the array to avoid conflicts in the setStyleRanges method
		int[] intRangesCorrectSize = new int[arrayIndexCounter];
		System.arraycopy(intRanges, 0, intRangesCorrectSize, 0,
				arrayIndexCounter);

		return intRangesCorrectSize;
	}
}

		

Change your PersonLabelProvider to the following.

			
package de.vogella.jface.tableviewer.providers;

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

import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import de.vogella.jface.tableviewer.Activator;

import de.vogella.jface.tableviewer.model.Person;
import de.vogella.jface.tableviewer.util.SearchUtil;

public class PersonLabelProvider extends StyledCellLabelProvider {
	// We use icons
	private static final Image CHECKED = Activator.getImageDescriptor(
			"icons/checked.gif").createImage();
	private static final Image UNCHECKED = Activator.getImageDescriptor(
					"icons/unchecked.gif").createImage();
	private String searchText;
	private Color systemColor;

	public PersonLabelProvider() {
		systemColor = Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);
	}

	public void setSearchText(String searchText) {
		this.searchText = searchText;

	}

	@Override
	public void update(ViewerCell cell) {
		Person element = (Person) cell.getElement();
		int index = cell.getColumnIndex();
		String columnText = getColumnText(element, index);
		cell.setText(columnText);
		cell.setImage(getColumnImage(element, index));
		if (searchText != null && searchText.length() > 0) {
			int intRangesCorrectSize[] = SearchUtil.getSearchTermOccurrences(
					searchText, columnText);
			List<StyleRange> styleRange = new ArrayList<StyleRange>();
			for (int i = 0; i < intRangesCorrectSize.length / 2; i++) {
				StyleRange myStyleRange = new StyleRange(0, 0, null,
						systemColor);
				myStyleRange.start = intRangesCorrectSize[i];
				myStyleRange.length = intRangesCorrectSize[++i];
				styleRange.add(myStyleRange);
			}
			cell.setStyleRanges(styleRange.toArray(new StyleRange[styleRange
					.size()]));
		} else {
			cell.setStyleRanges(null);
		}
	
		super.update(cell);

	}

	private String getColumnText(Object element, int columnIndex) {
		Person person = (Person) element;
		switch (columnIndex) {
		case 0:
			return person.getFirstName();
		case 1:
			return person.getLastName();
		case 2:
			return person.getGender();
		case 3:
			return String.valueOf(person.isMarried());
		default:
			throw new RuntimeException("Should not happen");
		}
	}

	private Image getColumnImage(Object element, int columnIndex) {
		// In case you don't like image just return null here
		if (columnIndex == 3) {
			if (((Person) element).isMarried()) {
				return CHECKED;
			}
			return UNCHECKED;
		}
		return null;
	}

}

		

Make the following changes to the View. .

			
package de.vogella.jface.tableviewer;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

import de.vogella.jface.tableviewer.filter.PersonFilter;
import de.vogella.jface.tableviewer.model.ModelProvider;
import de.vogella.jface.tableviewer.providers.PersonContentProvider;
import de.vogella.jface.tableviewer.providers.PersonEditingSupport;
import de.vogella.jface.tableviewer.providers.PersonLabelProvider;
import de.vogella.jface.tableviewer.sorter.TableSorter;

public class View extends ViewPart {
	public static final String ID = "de.vogella.jface.tableviewer.view";

	private TableViewer viewer;

	private TableSorter tableSorter;

	private PersonFilter filter;

	private PersonLabelProvider labelProvider;

	public void createPartControl(Composite parent) {
		GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		Label searchLabel = new Label(parent, SWT.NONE);
		searchLabel.setText("Search: ");
		final Text searchText = new Text(parent, SWT.BORDER | SWT.SEARCH);
		searchText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
				| GridData.HORIZONTAL_ALIGN_FILL));
		searchText.addKeyListener(new KeyAdapter() {
			public void keyReleased(KeyEvent ke) {
				filter.setSearchText(searchText.getText());
				labelProvider.setSearchText(searchText.getText());
				viewer.refresh();
			}
		});
		
		createViewer(parent);
		
		
		// Get the content for the viewer, setInput will call getElements in the
		// contentProvider
		viewer.setInput(ModelProvider.getInstance().getPersons());
		// Make the selection available
		getSite().setSelectionProvider(viewer);
		// Set the sorter for the table
		tableSorter = new TableSorter();
		viewer.setSorter(tableSorter);
		filter = new PersonFilter();
		viewer.addFilter(filter);

		// Layout the viewer
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		viewer.getControl().setLayoutData(gridData);
	}
	private void createViewer(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
		createColumns(viewer);
		viewer.setContentProvider(new PersonContentProvider());
		labelProvider = new PersonLabelProvider();
		viewer.setLabelProvider(labelProvider);
	}

	public TableViewer getViewer() {
		return viewer;
	}

	// This will create the columns for the table
	private void createColumns(final TableViewer viewer) {
		Table table = viewer.getTable();
		String[] titles = { "First name", "Last name", "Gender", "Married" };
		int[] bounds = { 100, 100, 100, 100 };

		for (int i = 0; i < titles.length; i++) {
			final int index = i;
			final TableViewerColumn viewerColumn = new TableViewerColumn(
					viewer, SWT.NONE);
			final TableColumn column = viewerColumn.getColumn();
			column.setText(titles[i]);
			column.setWidth(bounds[i]);
			column.setResizable(true);
			column.setMoveable(true);
			// Setting the right sorter
			column.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					tableSorter.setColumn(index);
					int dir = viewer.getTable().getSortDirection();
					if (viewer.getTable().getSortColumn() == column) {
						dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
					} else {

						dir = SWT.DOWN;
					}
					viewer.getTable().setSortDirection(dir);
					viewer.getTable().setSortColumn(column);
					viewer.refresh();
				}
			});
			viewerColumn.setEditingSupport(new PersonEditingSupport(viewer, i));
		}
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
	}

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

Run the example, if you search now the selected content should get highlighted should work.

10. Show/Hide Columns

This chapter shows how to implement a menu on the table which allows to show and hide columns of the table. Please note that Eclipse 3.5 introduced the possibility to add menus to columns headers.

Tip

This example is based on SWT Snippet 311

Change your coding in View.java to the following.

			
package de.vogella.jface.tableviewer;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

import de.vogella.jface.tableviewer.filter.PersonFilter;
import de.vogella.jface.tableviewer.model.ModelProvider;
import de.vogella.jface.tableviewer.providers.PersonContentProvider;
import de.vogella.jface.tableviewer.providers.PersonEditingSupport;
import de.vogella.jface.tableviewer.providers.PersonLabelProvider;
import de.vogella.jface.tableviewer.sorter.TableSorter;

public class View extends ViewPart {
	public static final String ID = "de.vogella.jface.tableviewer.view";

	private TableViewer viewer;

	private TableSorter tableSorter;

	private PersonFilter filter;

	private PersonLabelProvider labelProvider;

	public void createPartControl(Composite parent) {
		GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		Label searchLabel = new Label(parent, SWT.NONE);
		searchLabel.setText("Search: ");
		final Text searchText = new Text(parent, SWT.BORDER | SWT.SEARCH);
		searchText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
				| GridData.HORIZONTAL_ALIGN_FILL));
		searchText.addKeyListener(new KeyAdapter() {
			public void keyReleased(KeyEvent ke) {
				filter.setSearchText(searchText.getText());
				labelProvider.setSearchText(searchText.getText());
				viewer.refresh();
			}
		});
		createViewer(parent);
	}

	private void createViewer(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);

		createColumns(parent, viewer);
		viewer.setContentProvider(new PersonContentProvider());
		labelProvider = new PersonLabelProvider();
		viewer.setLabelProvider(labelProvider);
		// Get the content for the viewer, setInput will call getElements in the
		// contentProvider
		viewer.setInput(ModelProvider.getInstance().getPersons());
		// Make the selection available
		getSite().setSelectionProvider(viewer);
		// Set the sorter for the table
		tableSorter = new TableSorter();
		viewer.setSorter(tableSorter);
		filter = new PersonFilter();
		viewer.addFilter(filter);

		// Layout the viewer
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		viewer.getControl().setLayoutData(gridData);
	}

	public TableViewer getViewer() {
		return viewer;
	}

	// This will create the columns for the table
	private void createColumns(final Composite parent, final TableViewer viewer) {
		final Menu headerMenu = new Menu(parent);
		String[] titles = { "First name", "Last name", "Gender", "Married" };
		int[] bounds = { 100, 100, 100, 100 };

		for (int i = 0; i < titles.length; i++) {
			final int index = i;
			final TableViewerColumn viewerColumn = new TableViewerColumn(
					viewer, SWT.NONE);
			final TableColumn column = viewerColumn.getColumn();
			column.setText(titles[i]);
			column.setWidth(bounds[i]);
			column.setResizable(true);
			createMenuItem(headerMenu, column); // Create the menu item for this
												// column
			column.setMoveable(true);

			// Setting the right sorter
			column.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					tableSorter.setColumn(index);
					int dir = viewer.getTable().getSortDirection();
					if (viewer.getTable().getSortColumn() == column) {
						dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
					} else {

						dir = SWT.DOWN;
					}
					viewer.getTable().setSortDirection(dir);
					viewer.getTable().setSortColumn(column);
					viewer.refresh();
				}
			});
			viewerColumn.setEditingSupport(new PersonEditingSupport(viewer, i));
		}
		final Table table = viewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		table.addListener(SWT.MenuDetect, new Listener() {
			public void handleEvent(Event event) {
				table.setMenu(headerMenu);
			}
		});

	}

	private void createMenuItem(Menu parent, final TableColumn column) {
		final MenuItem itemName = new MenuItem(parent, SWT.CHECK);
		itemName.setText(column.getText());
		itemName.setSelection(column.getResizable());
		itemName.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event event) {
				if (itemName.getSelection()) {
					column.setWidth(150);
					column.setResizable(true);
				} else {
					column.setWidth(0);
					column.setResizable(false);
				}
			}
		});

	}

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

If you run your application you are able to hide and show columns using the right mouse click on your table.

11. Commands

The following will demonstrate the usage of commands. Feel free to skip with chapter.

11.1. Print the model content

This chapter add the functionality to print the content of the domain model to the console. This way it is possible to verify that the changes on the JFace table are updating the model.

Create the command "de.vogella.jface.tableviewer.commands.Print" with the default handler "de.vogella.jface.tableviewer.commands.Print" (see Defining commands for details).

Implement the following coding:

				
package de.vogella.jface.tableviewer.commands;

import java.util.List;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;

import de.vogella.jface.tableviewer.model.ModelProvider;
import de.vogella.jface.tableviewer.model.Person;

public class Print extends AbstractHandler {
	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
		List<Person> personList = ModelProvider.getInstance().getPersons();
		for (Person p : personList) {
			System.out.println(p);
		}
		return null;
	}
}

			

Add your command to the menu.(see Defining commands for details).

After finishing this you will be able to print the current state of your domain model to the console via the menu. Validate that the changes you are doing in the UI are reflected the model.

11.2. Add and delete a person to and from the model

This chapter shows how to add and delete Persons to and from the table.

You have to make the selection of the viewer available and will also provide an access method to the viewer of the view.

				
	public void createPartControl(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION);
		createColumns(viewer);
		viewer.setContentProvider(new PersonContentProvider());
		viewer.setLabelProvider(new PersonLabelProvider());
		// Get the content for the viewer, setInput will call getElements in the
		// contentProvider
		viewer.setInput(ModelProvider.getInstance().getPersons());
		// Make the selection available
		getSite().setSelectionProvider(viewer);

	}

	public TableViewer getViewer() {
		return viewer;
	}

			

Create the command "de.vogella.jface.tableviewer.commands.AddPerson" with the default handler "de.vogella.jface.tableviewer.commands.AddPerson". Add the command to your menu. Again see Defining commands for details.

Create a dialog to maintain the data for the additional person. Create package "de.vogella.jface.tableviewer.dialogs" and the following class "AddPersonDialog".

				
package de.vogella.jface.tableviewer.dialogs;

import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import de.vogella.jface.tableviewer.model.Person;

public class AddPersonDialog extends TitleAreaDialog {

	private Text text1;
	private Text text2;
	private Person person;
	private Button button1;
	private Combo combo1;

	public Person getPerson() {
		return person;
	}

	public AddPersonDialog(Shell parentShell) {
		super(parentShell);
	}

	@Override
	protected Control createContents(Composite parent) {
		Control contents = super.createContents(parent);
		setTitle("Add a new Person");
		setMessage("Please enter the data of the new person",
				IMessageProvider.INFORMATION);
		return contents;
	}

	@Override
	protected Control createDialogArea(Composite parent) {
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		parent.setLayout(layout);
		Label label1 = new Label(parent, SWT.NONE);
		label1.setText("First Name");
		text1 = new Text(parent, SWT.BORDER);
		Label label2 = new Label(parent, SWT.NONE);
		label2.setText("Last Name");
		text2 = new Text(parent, SWT.BORDER);
		Label label3 = new Label(parent, SWT.NONE);
		label3.setText("Gender");
		GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
		gd.horizontalSpan = 2;
		combo1 = new Combo(parent, SWT.READ_ONLY);
		combo1.add("male");
		combo1.add("female");
		button1 = new Button(parent, SWT.CHECK);
		button1.setText("Is married?");
		button1.setLayoutData(gd);
		return parent;

	}

	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		((GridLayout) parent.getLayout()).numColumns++;

		Button button = new Button(parent, SWT.PUSH);
		button.setText("OK");
		button.setFont(JFaceResources.getDialogFont());
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				if (text1.getText().length() != 0
						&& text2.getText().length() != 0
						&& combo1.getItem(combo1.getSelectionIndex()).length() != 0) {
					person = new Person(text1.getText(), text2.getText(),
							combo1.getItem(combo1.getSelectionIndex()), button1
									.getSelection());
					close();

				} else {
					setErrorMessage("Please enter all data");
				}
			}
		});
	}
}

			

Implement the following code for the class "de.vogella.jface.tableviewer.commands.AddPerson":

				
package de.vogella.jface.tableviewer.commands;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.handlers.HandlerUtil;

import de.vogella.jface.tableviewer.View;
import de.vogella.jface.tableviewer.dialogs.AddPersonDialog;
import de.vogella.jface.tableviewer.model.ModelProvider;

public class AddPerson extends AbstractHandler {

	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
		IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event);
		ModelProvider persons = ModelProvider.getInstance();
		AddPersonDialog dialog = new AddPersonDialog(window.getShell());
		dialog.open();
		if (dialog.getPerson() != null) {
			persons.getPersons().add(dialog.getPerson());
			// Updating the display in the view
			IWorkbenchPage page = window.getActivePage();
			View view = (View) page.findView(View.ID);
			view.getViewer().refresh();
		}
		return null;
	}
}
			

When you finished this successful you are able to add new persons in your application.

We will implement that a person can be deleted from the list after someone selected a person in the table, e.g. via a double click.

Create the command "de.vogella.jface.tableviewer.commands.DeletePerson" with the default handler "de.vogella.jface.tableviewer.commands.DeletePerson". Add the command to your menu.

Implement class "de.vogella.jface.tableviewer.commands.DeletePerson".

				
package de.vogella.jface.tableviewer.commands;

import java.util.Iterator;
import java.util.List;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.handlers.HandlerUtil;

import de.vogella.jface.tableviewer.View;
import de.vogella.jface.tableviewer.model.ModelProvider;
import de.vogella.jface.tableviewer.model.Person;

public class DeletePerson extends AbstractHandler {
	@SuppressWarnings("unchecked")
	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
		IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event);
		IWorkbenchPage page = window.getActivePage();
		View view = (View) page.findView(View.ID);
		ISelection selection = view.getSite().getSelectionProvider()
				.getSelection();

		if (selection != null && selection instanceof IStructuredSelection) {
			List<Person> persons = ModelProvider.getInstance().getPersons();
			IStructuredSelection sel = (IStructuredSelection) selection;

			for (Iterator<Person> iterator = sel.iterator(); iterator.hasNext();) {
				Person person = iterator.next();
				persons.remove(person);
			}
			view.getViewer().refresh();
		}
		return null;
	}
}

			

Please try to delete entries of the table by selection entries and executing "Delete Action".

11.3. Copy data to the system clipboard

This chapter shows how to copy the table data to the system clipboard via a command.

Create the command "de.vogella.jface.tableviewer.commands.CopyPersonClipboard" with the default handler "de.vogella.jface.tableviewer.commands.CopyPersonClipboard". Add the command to the menu.

				
package de.vogella.jface.tableviewer.commands;

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

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

import de.vogella.jface.tableviewer.View;
import de.vogella.jface.tableviewer.model.Person;

public class CopyPersonClipboard extends AbstractHandler {

	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {

		IWorkbenchWindow window = PlatformUI.getWorkbench()
				.getActiveWorkbenchWindow();
		IWorkbenchPage page = window.getActivePage();
		IViewPart view = page.findView(View.ID);
		Clipboard cb = new Clipboard(Display.getDefault());
		ISelection selection = view.getSite().getSelectionProvider()
				.getSelection();
		List<Person> personList = new ArrayList<Person>();
		if (selection != null && selection instanceof IStructuredSelection) {
			IStructuredSelection sel = (IStructuredSelection) selection;
			for (Iterator<Person> iterator = sel.iterator(); iterator.hasNext();) {
				Person person = iterator.next();
				personList.add(person);
			}
		}
		StringBuilder sb = new StringBuilder();
		for (Person person : personList) {
			sb.append(personToString(person));
		}
		TextTransfer textTransfer = TextTransfer.getInstance();
		cb.setContents(new Object[] { sb.toString() },
				new Transfer[] { textTransfer });

		return null;
	}

	private String personToString(Person person) {
		return person.getFirstName() + "\t" + person.getLastName() + "\t"
				+ person.getGender() + "\t" + person.isMarried()
				+ System.getProperty("line.separator");
	}

}

			

Run your application, select a few persons, run your command and paste the result in a text editor, e.g. notepad.

12. Thank you

Thank you for practicing with this tutorial.

I maintain this tutorial in my private time. If you like the information please help me by using flattr or donating or by recommending this tutorial to other people.

Flattr this

13. 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. .

14. Download

http://www.vogella.de/articles/EclipseJFaceTable/download/checkedpics.zip The checkbox pictures for the JFace Labelprovider

15. Links and Literature

15.1. Source Code

Source Code of Examples

15.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