|
|
Line 1: |
Line 1: |
| === 1. Create project and data model === | | === 1. Create project and data model === |
− |
| |
− | === 2. Show Data in Application ===
| |
− | 2.1 Columns data in a JFace table can be hold in <code>ModelProvider</code> and it is defined via instances of <code>TableViewerColumn</code> object:<br/>
| |
− | <code>viewer.setInput(ModelProvider.INSTANCE.getStudents());</code><br/>
| |
− | and
| |
− | <code>TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0);</code>
| |
− | 2.2 Add the following lines to <code>StudentsView.java</code> class:<br/>
| |
− | Private variable: <br/>
| |
− | <code>private TableViewer viewer;</code><br/>
| |
− | Change the <code>createColumns()method:<br/>
| |
− | <pre>
| |
− | 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();
| |
− | }
| |
− | });
| |
− | </pre><br/>
| |
− | Add the same functionality for other three columns
| |
− | 2.3 Run your application:<br/>
| |
− | [[Image: Create1.png | 400px]]<br/>
| |
− |
| |
− | === 3. Add Edit Cell Data Option ===
| |
− | 3.1 To make the column editable you need to define an object of type <code>EditingSupport/<code> on your TableColumnViewer.
| |
− | 3.2 Create new class for each column that extends <code>EditingSupport</code> class:
| |
− | <pre>
| |
− | 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();
| |
− | }
| |
− | }
| |
− | </pre><br/>
| |
− | 3.3 Assign <code>EditorSupport</code> objects to your <code>TableColumnViewers </code>in your <code>StudentView</code> class.<br/>
| |
− | Add the following line at the end of the <code>LabelProvider</code> is set:<br/>
| |
− | <code>col.setEditingSupport(new IdEditingSupport(viewer));</code><br/>
| |
− | 3.4 Run your application. You should now be able to modify the content of the table:<br/>
| |
− | [[Image: Create2.png | 400px]]<br/>
| |
− |
| |
− | === 4. Add Sorting Option ===
| |
− | 4.1 Create a new Class <code>StudentViewerComparator.java</code> put it in package <code>sorter</code>:<br/>
| |
− | <pre>
| |
− | 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;
| |
− | }
| |
− | }
| |
− | </pre><br/>
| |
− | 4.2 Add new private variable to <code>StudentsView</code> class:<br/>
| |
− | <code>private StudentViewerComparator comparator;</code><br/>
| |
− | 4.3 Add the following lines to the end of <code>createPartControl()</code> method:<br/>
| |
− | <pre>
| |
− | comparator = new StudentViewerComparator();
| |
− | viewer.setComparator(comparator);
| |
− | </pre><br/>
| |
− | 4.4 Add <code>SelectionListener</code> the to the <code>createTableViewerColumn()</code> method:
| |
− | <code>column.addSelectionListener(getSelectionAdapter(column, colNumber));</code><br/>
| |
− | 4.5 Add new method:<br/>
| |
− | <pre>
| |
− | 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;
| |
− | }
| |
− | </pre><br/>
| |
− | 4.6 Run the application. Click on a column header, the table should be sorted according to the content of this column.<br/>
| |
− | There will also appear a sort-direction in the top of the column:<br/>
| |
− | [[Image: Create3.png | 400px]]<br/>
| |
− |
| |
− | === 5. Add Filter(Search) Option ===
| |
− | 5.1 Create new class that extends <code>ViewerFilter</code>. This class uses case-insensitive filtering:<br/>
| |
− | <pre>
| |
− | 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;
| |
− | }
| |
− | }
| |
− | </pre><br/>
| |
− | 5.2 Create a new private variable in the <code>StudentView</code> class:
| |
− | <code>private StudentFilter filter;</code><br/>
| |
− | 5.3 Add the filter to <code>createPartControl()</code> method:<br/>
| |
− | <pre>
| |
− | filter = new StudentFilter();
| |
− | viewer.addFilter(filter);
| |
− | </pre><br/>
| |
− | 5.4 Run the application. Search for the student:<br/>
| |
− | [[Image: Create4.png | 400px]]<br/>
| |
− |
| |
− | === 6. Add Highlights to Search ===
| |
− | 6.1 Create a new helper class and put it in <code>util</code> package. <br/>
| |
− | Method in this class use logic that is case-insensitive, because filter is case-insensitive:<br/>
| |
− | <pre>
| |
− | 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;
| |
− | }
| |
− | }
| |
− | </pre><br/>
| |
− | 6.2 Change the way columns are created in the <code>createColumns()</code> method.<br/>
| |
− | Following is the code for the first column, other columns need to be changed in similar way:<br/>
| |
− | <pre>
| |
− | // 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));
| |
− | </pre><br/>
| |
− | 6.3 Run the application. Now your search matches are highlighted:<br/>
| |
− | [[Image: Create5.png | 400px]]
| |