Teams Winter 2011/team1/RCP/Define and use JFace
Contents
Define and view JFace Viewers
1. Show Data in Application
1.1 Columns data in a JFace table can be hold in ModelProvider
and it is defined via instances of TableViewerColumn
object:
viewer.setInput(ModelProvider.INSTANCE.getStudents());
and
TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0);
1.2 Add the following lines to StudentsView.java
class:
Private variable:
private TableViewer viewer;
Change the createColumns()method:
String[] titles = { "Id", "First name", "Last name", "Program" }; int[] bounds = { 100, 100, 100, 100 }; // First column is for the student id TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0); col.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { Student s = (Student) element; return s.getId(); } });
Add the same functionality for other three columns
1.3 Run your application:
2. Add Edit Cell Data Option
2.1 To make the column editable you need to define an object of type <code>EditingSupport/<code> on your TableColumnViewer. 2.2 Create new class for each column that extends <code>EditingSupport class:
package cs.ecl.rcp.simplercp.edit; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TextCellEditor; import cs.ecl.rcp.simplercp.model.Student; public class IdEditingSupport extends EditingSupport { private final TableViewer viewer; public IdEditingSupport(TableViewer viewer) { super(viewer); this.viewer = viewer; } @Override protected CellEditor getCellEditor(Object element) { return new TextCellEditor(viewer.getTable()); } @Override protected boolean canEdit(Object element) { return true; } @Override protected Object getValue(Object element) { return ((Student) element).getId(); } @Override protected void setValue(Object element, Object value) { ((Student) element).setId(String.valueOf(value)); viewer.refresh(); } }
2.3 Assign EditorSupport
objects to your TableColumnViewers
in your StudentView
class.
Add the following line at the end of the LabelProvider
is set:
col.setEditingSupport(new IdEditingSupport(viewer));
2.4 Run your application. You should now be able to modify the content of the table:
3. Add Sorting Option
3.1 Create a new Class StudentViewerComparator.java
put it in package sorter
:
package cs.ecl.rcp.simplercp.sorter; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import cs.ecl.rcp.simplercp.model.*; public class StudentViewerComparator extends ViewerComparator { private int propertyIndex; private static final int DESCENDING = 1; private int direction = DESCENDING; public StudentViewerComparator() { 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) { Student s1 = (Student) e1; Student s2 = (Student) e2; int rc = 0; switch (propertyIndex) { case 0: rc = s1.getId().compareTo(s2.getId()); break; case 1: rc = s1.getFirstName().compareTo(s2.getFirstName()); break; case 2: rc = s1.getLastName().compareTo(s2.getLastName()); break; case 3: rc = s1.getProgram().compareTo(s2.getProgram()); break; default: rc = 0; } // If descending order, flip the direction if (direction == DESCENDING) { rc = -rc; } return rc; } }
3.2 Add new private variable to StudentsView
class:
private StudentViewerComparator comparator;
3.3 Add the following lines to the end of createPartControl()
method:
comparator = new StudentViewerComparator(); viewer.setComparator(comparator);
3.4 Add SelectionListener
the to the createTableViewerColumn()
method:
column.addSelectionListener(getSelectionAdapter(column, colNumber));
3.5 Add new method:
private SelectionAdapter getSelectionAdapter(final TableColumn column, final int index) { SelectionAdapter selectionAdapter = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { comparator.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(); } }; return selectionAdapter; }
3.6 Run the application. Click on a column header, the table should be sorted according to the content of this column.
There will also appear a sort-direction in the top of the column:
4. Add Filter(Search) Option
4.1 Create new class that extends ViewerFilter
. This class uses case-insensitive filtering:
package cs.ecl.rcp.simplercp.filter; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import cs.ecl.rcp.simplercp.model.*; public class StudentFilter 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; } Student s = (Student) element; if (s.getFirstName().toLowerCase().matches(searchString.toLowerCase())) { return true; } if (s.getLastName().toLowerCase().matches(searchString.toLowerCase())) { return true; } if (s.getProgram().toLowerCase().matches(searchString.toLowerCase())) { return true; } if (s.getId().matches(searchString)) { return true; } return false; } }
4.2 Create a new private variable in the StudentView
class:
private StudentFilter filter;
4.3 Add the filter to createPartControl()
method:
filter = new StudentFilter(); viewer.addFilter(filter);
4.4 Run the application. Search for the student:
5. Add Highlights to Search
5.1 Create a new helper class and put it in util
package.
Method in this class use logic that is case-insensitive, because filter is case-insensitive:
package cs.ecl.rcp.simplercp.util; import java.util.ArrayList; import java.util.List; public class SearchUtil { public static int[] getSearchTermOccurrences(final String searchTerm, final String content) { if (searchTerm == null || searchTerm.length() == 0) { return new int[0]; } if (content == null) { throw new IllegalArgumentException("content is null"); } final List<Integer> list = new ArrayList<Integer>(); int searchTermLength = searchTerm.length(); int index; int fromIndex = 0; int lastIndex = -1; int lastLength = 0; while (true) { index = content.toLowerCase().indexOf(searchTerm.toLowerCase(), fromIndex); if (index == -1) { // no occurrence of "searchTerm" in "content" starting from // index "fromIndex" if (lastIndex != -1) { // but there was a previous occurrence list.add(Integer.valueOf(lastIndex)); list.add(Integer.valueOf(lastLength)); } break; } if (lastIndex == -1) { // the first occurrence of "searchTerm" in "content" lastIndex = index; lastLength = searchTermLength; } else { if (lastIndex + lastLength == index) { // the current occurrence is right after the previous // occurrence lastLength += searchTermLength; } else { // there is at least one character between the current // occurrence and the previous one list.add(Integer.valueOf(lastIndex)); list.add(Integer.valueOf(lastLength)); lastIndex = index; lastLength = searchTermLength; } } fromIndex = index + searchTermLength; } final int n = list.size(); final int[] result = new int[n]; for (int i = 0; i != n; i++) { result[i] = list.get(i); } return result; } }
5.2 Change the way columns are created in the createColumns()
method.
Following is the code for the first column, other columns need to be changed in similar way:
// First column is for the id TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0); col.setLabelProvider(new StyledCellLabelProvider() { @Override public void update(ViewerCell cell) { String search = searchText.getText(); Student student = (Student) cell.getElement(); String cellText = student.getId(); cell.setText(cellText); if (search != null && search.length() > 0) { int intRangesCorrectSize[] = SearchUtil .getSearchTermOccurrences(search, cellText); List<StyleRange> styleRange = new ArrayList<StyleRange>(); for (int i = 0; i < intRangesCorrectSize.length / 2; i++) { int start = intRangesCorrectSize[i]; int length = intRangesCorrectSize[++i]; StyleRange myStyledRange = new StyleRange(start, length, null, colorYellow); styleRange.add(myStyledRange); } cell.setStyleRanges(styleRange .toArray(new StyleRange[styleRange.size()])); } else { cell.setStyleRanges(null); } super.update(cell); setStatusLine("Student search has been updated"); } }); col.setEditingSupport(new IdEditingSupport(viewer));
5.3 Run the application. Now your search matches are highlighted:
6. Adding status line
6.1 Open ApplicationWorkbenchWindowAdvisor.java
file in your project and add the following line at the end of preWindowOpen()
method:
configurer.setShowStatusLine(true);
6.2 Add a new method to this class to set text in status line from different parts of application:
@Override public void postWindowOpen() { IStatusLineManager statusline = getWindowConfigurer().getActionBarConfigurer().getStatusLineManager(); statusline.setMessage(null, "Status line is ready"); }
6.3 Run the application you should see the following:
6.4 Change the status line from StudentsView.java
. Add the following method to this class:
private void setStatusLine(String message) { // Get the status line and set the text IActionBars bars = getViewSite().getActionBars(); bars.getStatusLineManager().setMessage(message); }
Use this method to change text in status line. In the createColumn()
method insert the following line at the end of column's update()
method:</br>
setStatusLine("Student search has been updated");
6.5 Run the application and try to use Search to find a student. You should get the following:
6.6 To access status line from the editor use the following line:
IEditorPart.getEditorSite().getActionBars();
7. Adding a perspective
7.1 Add necessary extensions to the plugin.xml
:
7.2 Specify the id cs.ecl.simpleRCP.perspective, name RCP Perspective and class cs.ecl.rcp.simplercp.Perspective:
7.3 Click on the class*
link to create a class. The method createInitialLayout()
in this class is responsible for creating the new perspective.
7.4 The perspective is defined but not yet reachable via the application. To activate the switch between perspectives add the following line to the
ApplicationWorkbenchWindowAdvisor.java
in method preWindowOpen():
configurer.setShowPerspectiveBar(true);
7.5 Run the application. You should be able to select your perspective interactively: