Teams Winter 2011/team1/RCP/Define and use JFace

From CDOT Wiki
Jump to: navigation, search

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:
Create1.png

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:
Create2.png

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:
Create3.png

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:
Create4.png

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:
Create5.png

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:
StatusLine.png
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:
StatusLine2.png
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:
PluginXml.png
7.2 Specify the id cs.ecl.simpleRCP.perspective, name RCP Perspective and class cs.ecl.rcp.simplercp.Perspective:
PluginXml2.png
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:
Perspective1.png


Index Page            Next>>