Time for action – syncing selection

The TimeZoneTableView and the TimeZoneTreeView can propagate their selection to the Properties view. Responding to selection changes gives a unified feel despite the fact that the views are independent entities.

They can be further linked so that when a TimeZone is selected in either of these views, it automatically reveals in the other. To do this, a selection listener will need to be registered, and if the selected object is a type of TimeZone, display it in the view (with the reveal() and setSelection() methods).

  1. Create a class TimeZoneSelectionListener (in the com.packtpub.e4.clock.ui.internal package), which implements the ISelectionListener interface. This will take a viewer, and an associated part, to implement the selectionChanged() method.
    public class TimeZoneSelectionListener implements
     ISelectionListener {
      private Viewer viewer;
      private IWorkbenchPart part;
      public TimeZoneSelectionListener(Viewer v, IWorkbenchPart p) {
        this.viewer = v;
        this.part = p;
      }
      public void selectionChanged(IWorkbenchPart p, ISelection sel) {
      }
    }
  2. The selectionChanged() method needs to:
    • Ignore the event if it was fired by the same part
    • Get the selected object from the event and compare it with the current one
    • If different, and the selected object is a TimeZone, update the viewer
  3. Implement it as follows:
    public void selectionChanged(IWorkbenchPart p, ISelection sel) {
      if (p != this.part) {
        IStructuredSelection selected = ((IStructuredSelection)sel)
         .getFirstElement();
        Object current = ((IStructuredSelection)viewer.getSelection())
         .getFirstElement();
        if(selected != current && selected instanceof TimeZone) {
          viewer.setSelection(sel);
          if(viewer instanceof StructuredViewer) {
            ((StructuredViewer) viewer).reveal(selected);
          }
        }
      }
    }
  4. The selection listeners need to be registered with the views. Open up the TimeZoneTableView class, and at the bottom of the createPartControl() method, add the following:
    selectionListener = new TimeZoneSelectionListener(
      tableViewer, getSite().getPart());
    getSite().getWorkbenchWindow().getSelectionService()
      .addSelectionListener(selectionListener);
  5. The selectionListener needs to be added as a field, because it will be necessary to remove the listener when the view is disposed:
    private TimeZoneSelectionListener selectionListener;
    public void dispose() {
      if (selectionListener != null) {
        getSite().getWorkbenchWindow().getSelectionService()
         .removeSelectionListener(selectionListener);
        selectionListener = null;
      }
      super.dispose();
    }
  6. A very similar change (only the viewer's variable name is different) needs to be added to the TimeZoneTreeView class:
    selectionListener = new TimeZoneSelectionListener(
      tableViewer, getSite().getPart());
    getSite().getWorkbenchWindow().getSelectionService()
      .addSelectionListener(selectionListener);
  7. The dispose method is the same for the TimeZoneTreeView class as the TimeZoneTableView.
  8. Now run the Eclipse instance, select a time zone in the Time Zone Table View, and the Time Zone Tree View should show the same one. Change the selection of the Time Zone Tree View and the Time Zone Table View should show the same one.

What just happened?

Selection events occur a lot in the Eclipse workspace, so it is important that the selection listeners be performant. By filtering events fired from the same part, or filtering uninteresting types, the event delivery will be more efficient. In this case, the selection is checked to ensure that the selection contains (at least) one element, which is a TimeZone, before performing any UI updates.

The selection of the viewer can be synchronized with the setSelection() call; this saves having to instantiate a new selection object and set the data appropriately. However, setting the selection alone is not enough; the reveal() method needs to be called to ensure that it is appropriately highlighted. If multiple objects are selected, this will only reveal the first element.

The reveal() method is only available to StructuredViewers, so the selection stamps the selection as it is, and explicitly sets the IStructuredSelection for those that are StructuredViewers.

Finally, the listeners are registered when the view is created, and removed when the view is disposed. To do this, get hold of the ISelectionService via the part and then invoke the addSelectionListener() method to add it, and invoke the removeSelectionListener() method to remove it.

Note

What just happened? E4: If using E4, instead of using the ISelectionService, the ESelectionService is used. This provides a similar, but not identical, interface in that the WorkbenchPart is no longer present. Typically, the ESelectionService is injected into the view and the listener is wired in the @PostConstruct and removed in the @PreDestroy call.

Pop quiz – understanding tables

Q1. How are a columns' headers enabled in a TableViewer?

Q2. What is a TableViewerColumn for?

Q3. How is selection synchronized between two views?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset