Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we need ContentProviders for JFace Viewers (TableViewers specifically)?

I have always wondered why we exactly need ContentProviders for JFace TableViewers? I know that getElements() method of a ContentProvider class will return an Array or Collection of Objects which corresponds to rows on the table and getElements will be called when we setInput(input) on a table. But my questions would be more specific..

getElements returns an Array or Collection of objects, instead I could write my own method to return an Array of objects and then do a setInput on the table viewer's instance right?

Can someone give me a not-too-technical but a brief and satisfying answer on why exactly we need ContentProviders? Without ContentProviders if I try to set input on a table then nothing shows up.. so when it comes to JFace a ContentProvider and a LabelProvider is a must..

like image 769
Sangli Avatar asked Dec 29 '15 11:12

Sangli


1 Answers

For a JFace (table) viewer to work, a ContentProvider and a LabelProvider is essential.

When creating a viewer, a default LabelProvider (an instance of LabelProvider) is already set. This implementation uses toString() to obtain a textual representation of the element.

A ContentProvider needs to be explicitly set. It is used to translate from the applications domain model to the viewers model. In case of the TableViewer, the viewer expects a flat array of the elements that should be displayed. Each element represents one row of the TableViewer.

If your domain model already uses an array or collection, you can use the predefined ArrayContentProvider.

To show a list of Persons for example you would configure the viewer like this:

Person[] persons = ...
viewer.setContentProvider( ArrayContentProvider.getInstance() );
viewer.setInput( persons );

Suppose that persons are held in a PersonRegistry you would rather configure the viewer with a custom ContentProvider that is able to extract persons from the registry:

PersonRegistry registry = ...
viewer.setContentProvider( new PersonContentProvider() );
viewer.setInput( registry );

class PersonContentProvider implements IStructuredContentProvider {
  PersonRegistry registry;
  public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
    this.registry = ( PersonRegistry )newInput;
  }

  public Object[] getElements(Object inputElement) {
    return registry.getPersons();
  }

  ...
}

Finally, setInput() is meant to supply the application model. The inputChanged() method of the ContentProvider must be able to cope with what was passed to setInput(). Also note, that setInput() must only be called after a content provider was set, otherwise an exception will be thrown.

like image 75
Rüdiger Herrmann Avatar answered Nov 03 '22 20:11

Rüdiger Herrmann