swt

JFace Binding

Recently I have started using JFace Binding. Unfortunately there are not many resources available on the web with non-trivial examples.

Let present example of master-detail view: a drop-down list and two text fields which display some details regarding option chosen from the list.

POJO Category. It contains two fields: name and description which will be displayed as details of the object chosen from the drop-down list:

import java.beans.PropertyChangeListener;
import java.io.Serializable;

/**
* Domain object representing category
*
*/
public class Category implements Serializable {

private static final long serialVersionUID = -5542167952605551865L;

private String name;
private String description;

/**
* Default constructor
*/
public Category() {
// Do nothing
}

/**
* Constructor
*
* @param name
*            name of a category
* @param description
*            description of a category
*/
public Category(String name, String description) {
this.name = name;
this.description = description;
}

/**
* @return the name
*/
public String getName() {
return name;
}

/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}

/**
* @return the description
*/
public String getDescription() {
return description;
}

/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
}

Class of model that will be used to bind the data to the view:

import java.util.List;

/**
* Model for displaying categories
*
*/
public class CategoriesModel extends AbstractModelObject {
private List categories;
private IDataManager dataManager;
private Category category;

/**
* The constructor
*/
public CategoriesModel() {
this.dataManager = Activator.getDataManager();
this.categories = this.dataManager.getAllCategories();
}

/**
* @return the category
*/
public Category getCategory() {
return this.category;
}

/**
* @param category
*            the category to set
*/
public void setCategory(Category category) {
this.category = category;
}

/**
* @return the categories
*/
public List getCategories() {
return categories;
}

/**
* @param categories the categories to set
*/
public void setCategories(List categories) {
this.categories = categories;
}
}

Class of view (in this case it is Eclipse View containing managed form):

import java.util.logging.Logger;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.ManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.part.ViewPart;

/**
* Allows to view list of categories and their details
*
*/
public class CategoryView extends ViewPart {

private Logger logger = Logger.getLogger(CategoryView.class.getName());

private static final String FORM_TITLE = Messages
.getString("category.view.form.title");

private FormToolkit formToolkit;

private CategoriesModel model;
private Text nameText;
private Text descriptionText;
private ComboViewer categoriesComboViewer;
private DataBindingContext dbc;

/**
* {@inheritDoc}
*/
@Override
public void createPartControl(Composite parent) {
model = new CategoriesModel();

ManagedForm mForm = new ManagedForm(parent);
ScrolledForm scrolledForm = mForm.getForm();
FormToolkit formToolkit = mForm.getToolkit();
Composite formBody = scrolledForm.getBody();
formToolkit.decorateFormHeading(scrolledForm.getForm());
scrolledForm.setText(FORM_TITLE);
formBody.setLayout(new GridLayout(2, true));

categoriesComboViewer = new ComboViewer(formBody, SWT.DROP_DOWN
| SWT.READ_ONLY);
GridData comboGridData = new GridData();
comboGridData.horizontalSpan = 2;
comboGridData.horizontalAlignment = GridData.FILL;
categoriesComboViewer.getCombo().setLayoutData(comboGridData);

nameText = formToolkit.createText(formBody, "", SWT.NONE);
GridData nameGridData = new GridData();
nameGridData.horizontalSpan = 2;
nameGridData.horizontalAlignment = GridData.FILL;
nameText.setLayoutData(nameGridData);

descriptionText = formToolkit.createText(formBody, "", SWT.MULTI);
GridData textGridData = new GridData();
textGridData.horizontalSpan = 2;
textGridData.horizontalAlignment = GridData.FILL;
textGridData.heightHint = 100;
descriptionText.setLayoutData(textGridData);

formToolkit.paintBordersFor(formBody);
bindData();
}

/**
* {@inheritDoc}
*/
@Override
public void setFocus() {
// Do nothing
}

/**
* This method binds the value from UI layer to the model object
*/
protected void bindData() {
dbc = new DataBindingContext();

// Seting content provider for combo viewer
ObservableListContentProvider categoryViewerContentProvider = new ObservableListContentProvider();
categoriesComboViewer.setContentProvider(categoryViewerContentProvider);
IObservableMap[] attributeMaps = BeansObservables.observeMaps(
categoryViewerContentProvider.getKnownElements(),
Category.class, new String[] { "name" });
categoriesComboViewer.setLabelProvider(new ObservableMapLabelProvider(
attributeMaps));
categoriesComboViewer.setInput(new WritableList(model.getCategories(),
Category.class));

// Observing changes in selection in combo viewer
IObservableValue selection = ViewersObservables
.observeSingleSelection(categoriesComboViewer);

// Observing the properties of the current selection
IObservableValue detailNameObservable = BeansObservables
.observeDetailValue(Realm.getDefault(), selection, "name",
String.class);

IObservableValue detailDescriptionObservable = BeansObservables
.observeDetailValue(Realm.getDefault(), selection,
"description", String.class);

// Binding the Text widgets to the name and description details
// (selection's properties).
dbc.bindValue(SWTObservables.observeText(nameText, SWT.None),
detailNameObservable, new UpdateValueStrategy(false,
UpdateValueStrategy.POLICY_NEVER), null);

dbc.bindValue(SWTObservables.observeText(descriptionText, SWT.None),
detailDescriptionObservable, new UpdateValueStrategy(false,
UpdateValueStrategy.POLICY_NEVER), null);
}

/**
* {@inheritDoc}
*/
public void dispose() {
if (formToolkit != null) {
formToolkit.dispose();
}
super.dispose();
}
}

AbstractModelObject which provides methods required by JFace Binding (it’s not checked on compilation level):

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

/**
* Provides minimal JavaBeans support for model objects
*
*/
public abstract class AbstractModelObject {
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
this);

/**
* @param listener
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}

/**
* @param propertyName
* @param listener
*/
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}

/**
* @param listener
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}

/**
* @param propertyName
* @param listener
*/
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(propertyName,
listener);
}

/**
*
* @param propertyName
* @param oldValue
* @param newValue
*/
protected void firePropertyChange(String propertyName, Object oldValue,
Object newValue) {
propertyChangeSupport.firePropertyChange(propertyName, oldValue,
newValue);
}
}