Eclipse Plug-in Development:Beginner's Guide(Second Edition)
上QQ阅读APP看书,第一时间看更新

Time for action – sorting items in a viewer

The TreeViewer already shows data in a sorted list, but this is not a view-imposed sort. Because the data is stored in a TreeMap, the sort ordering is created by the TreeMap itself, which in turn is sorting on the value of the toString method. To use a different ordering (say, based on the timezone offset) the choices are either to modify the TreeMap to add a Comparator and sort the data at creation time, or add a sorter to the TreeViewer. The first choice is applicable if the data is only used by a single view, or if the data is coming from a large external data store which can perform the sorting more efficiently (such as a relational database). For smaller data sets, the sorting can be done in the viewer itself.

  1. JFace structured viewers allow view-specific sorting with the ViewerComparator. Create a new subclass called TimeZoneViewerComparator in the com.packtpub.e4.clock.ui.internal package, and implement the compare method as follows:
    public class TimeZoneViewerComparator extends ViewerComparator {
     public int compare(Viewer viewer, Object z1, Object z2) {
      int compare;
      if (z1 instanceof ZoneId && z2 instanceof ZoneId) {
        Instant now = Instant.now();
        ZonedDateTime zdt1 = ZonedDateTime.ofInstant(now,(ZoneId)z1);
        ZonedDateTime zdt2 = ZonedDateTime.ofInstant(now,(ZoneId)z2);
        compare = zdt1.compareTo(zdt2);
      } else {
        compare = o1.toString().compareTo(o2.toString());
      }
      return compare;
     }
    }
  2. Set the comparator on the treeViewer in the TimeZoneTreeView as follows:
    treeViewer.setComparator(new TimeZoneViewerComparator());
  3. Run the Eclipse instance, open the Time Zone Tree View, and the time zones should be sorted first by offset, then alphabetically:
  4. To add a viewer-specific sort, modify the compare method of the TimeZoneViewerComparator class to get a REVERSE key from the viewer's data. Use it to invert the results of the sort:
    // return compare;
    boolean reverse = Boolean.parseBoolean(String.valueOf(viewer.getData("REVERSE")));
    return reverse ? -compare : compare;
  5. To see the effect of this sort, set the REVERSE key just before the setComparator() call at the end of the create method of TimeZoneTreeView:
    treeViewer.setData("REVERSE", Boolean.TRUE);
    treeViewer.setComparator(new TimeZoneViewerComparator());
  6. Re-launch the Eclipse instance, and the view should be in the reverse order.

What just happened?

By adding the TimeZoneViewerComparator to the TimeZoneTreeViewer, data can be sorted in an appropriate manner for the viewer in question. Typically this will be done in conjunction with selecting an option in the view—for example, an option may be present to reverse the ordering, or to sort by name or offset.

Tip

When implementing a specific Comparator, check that the method can handle multiple object types (including ones that may not be expected). The data in the viewer may change, or be different at run-time than expected. Use instanceof to check that the items are of the expected type.

To store properties that are specific to a viewer, use the setData and getData calls on the viewer itself. This allows a generic comparator to be used across views while still respecting per view filtration/sorting operations.

The preceding example hard-codes the sort data, which requires an Eclipse re-launch to see the effect. Typically after modifying properties that may affect the view's sorting or filtering, refresh is invoked on the viewer to bring the display in line with the new settings.