Archive for July, 2008

Jul 26 2008

Help in Eclipse RCP application

Published by under Eclipse,IT,Java

Until you are working at Google or Apple your applications probably requires some sort of help system (UX). Eclipse help system can be easily reused in your custom application based on Eclipse RCP.

Let assume that you already have RCP application (if not you can use one of the wizards provided in Eclipse to get one).  In order to enable help there you need to add three dependencies explicitly in plugin.xml:

  • org.eclipse.help.ui
  • org.eclipse.help.ui.webapp
  • org.eclipse.equinox.http.jetty

After adding those make sure to update *.product configuration and add all new required dependencies.

The next step is adding an extension which will provide the help content in plug-ins that will contribute it. The extension point that provides this feature is: org.eclipse.help.toc (there is one template with dummy help content available to choose in Extension Point Selection form).

Now some menu item that will launch help needs to be added. It can be done in plugin.xml:

  • Add an extension (if you don’t have it already) : org.eclipse.ui.menus
  • Add new element: menuContribution with locationURI menu:file
  • Add new command with id: org.eclipse.ui.help.helpContents

Last step is registering an action that will be binded to previously created menu item. It can be done in a class that extends ActionBarAdvisor (if you created your RCP application using default wizard it will be called ApplicationActionBarAdvisor. You need to override one method:

protected void makeActions(IWorkbenchWindow window) {
	this.contentsHelpAction = ActionFactory.HELP_CONTENTS.create(window);
	register(this.contentsHelpAction);
}

Now help system with sample content should be available in Help menu. It will launch separate window and display content there. A help content can be provided by any plug-in extending org.eclipse.help.toc extension point. It is set of HTML documents which are displayed together in one common place, framework provides built-in search, index, table of contents etc (Eclipse uses Jetty as a web server, try this in a browser).

2 responses so far

Jul 22 2008

JFace Binding

Published by under Eclipse,IT,Java

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<Category> 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<Category> getCategories() {
return categories;
}
 
/**
* @param categories the categories to set
*/
public void setCategories(List<Category> 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);
}
}

4 responses so far