Sunday, August 24, 2008

Writing a CTreeCombo-Widget

I was working on my example RCP/EMF/Databinding application

I'm going to use to present various parts of those technologies to my co-workers and getting familiar with new technologies like CDO, Teneo, Spring and others when I hit the problem that standard CCombo didn't suited my needs.

What I wanted to have was a CCombo which presents a Tree like structure like this

for my Login-Screen and as you all know there's no such widget available currently. As you might guess from the above Screenshot I somehow managed to get such a widget.

Before we dive into it another requirement I had was that the implementation plugs itself into the existing viewer and databinding concepts of Eclipse.

So what did I do and how did it work? Well 95% of the work I had to do is C&P. I copied the CCombo-Code replaced List against Tree and solved compilation errors. To make a CTreeCombo widget I would have been done almost if this would have been the only requirement.

The real problem is that widgets are reparentable and that this can happen across Shells which makes it necessary to recreate the Tree and its popup shell from time to time so directly attaching a TreeViewer on the underlying Tree-Widget is not possible. So the only possibility was to create Proxy objects around TreeItem/TreeColumn who proxy the real implemementation so that they could be recreated whenever needed.

So if one wants to use the widget he/she has to write code like this:

CTreeCombo combo = new CTreeCombo(shell,style);

CTreeComboItem item = new CTreeComboItem(combo,SWT.NONE);
item.setText("Parent 1");

CTreeComboItem childItem = new CTreeComboItem(item,SWT.NONE);
childItem.setText("Child 1.1");

childItem = new CTreeComboItem(item,SWT.NONE);
childItem.setText("Child 1.2");

item = new CTreeComboItem(combo,SWT.NONE);
item.setText("Parent 2");

childItem = new CTreeComboItem(item,SWT.NONE);
childItem.setText("Child 2.1");

childItem = new CTreeComboItem(item,SWT.NONE);
childItem.setText("Child 2.2");

CTreeCombo now works like an ordinary SWT-Tree providing the same API as SWT-Tree (at least currently the one which is necessary to write a JFace-Viewer) so that I could subclass AbstractTreeViewer and providing an implementation for it. So if one uses JFace-Viewers in his/her code they simply need to write:

CTreeCombo combo = new CTreeCombo(parent,style);

CTreeComboViewer viewer = new CTreeComboViewer(combo);
viewer.setLabelProvider(new LabelProviderImpl());
viewer.setContentProvider(new ContentProviderImpl());

In the end it took me longer than I first thought but after 4 hours I had a working CTreeComboViewer (although it is not thoroughly tested yet) which behaves appropiately (at least in the way I currently use it).

If you are interested in the code of the widget or in the application to learn about:

  • Writing a modular RCP-Application

  • Using SWT, JFace and Databinding

  • Using EMF and EMF-Databinding

  • Using and creating your own Extension Points

  • Using and extending the Commands, Handlers and the Expression Framework

You can fetch the code from my companies svn-repository but the application is still in flux. If you are only interested in the widget and viewer code you can find it here for the widget and here for the viewer.