eclipse-dev

Friday, June 13, 2008

Ganymede - What's in JFace and Databinding

The History


JFace-Viewers/ToolTips


In 3.3 the whole Viewer-Infrastructur has been reworked to make it easier to add new features in upcoming releases. Some new features where part of 3.3 (e.g. LabelProvider/Column, CellNavigation, Customizable-Editor). Additionally JFace opened up its viewers for subclassers by wrapping Widget-Specific API (ViewerRow/ViewerCell).

Databinding


3.3 saw the first public release of the Eclipse-Databinding-Framework which removes the need for myiards of listeners to keep your model and UI in sync. Anbody who ever had write a Master-Detail-UI knows how hard it is to get it right.

Today


JFace-Viewers


We saw great adoption of our new API and new features added ontop of it. The most significat one is a LabelProvider which understands StyledText-Instructions named StyledCellLabelProvider. You'll see this LabelProvider in action if you open the Java-ProjectExplorer.

On the other hand we also saw great adoption of our API-Opening-Up effort which allows widget vendors to provide a JFace-Viewer-API for their structured widgets. There are 2 Nebula-Components (Nebula-Gallery and Nebula-Grid) who already adopted the concept and provide a viewer.

Thanks for the great feedback and bug reports from the community we fixed some [92] problems and feature request some of them dating back to 2003!

In comparison to Europa-Release we didn't introduced much new API. From my point of the main focus was to evolve the new API we provided in 3.3 and fix problems which have been introduced. If you saw how much code has been rewritten in 3.3 I think this was thr right thing (although we fairly broke no backward code anyways in 3.3).

Databinding


Thanks to the community and Ed Merks and his team there's now a 2nd possibility to back up your UI with a model beside JavaBeans.

Naturally they provide integration for their EMF-Objects with 2 brand new plugins named org.eclipse.emf.databinding and org.eclipse.emf.databinding.edit. Those plugins are marked as provisional but I'm using them since day 1 in my projects and for the standard cases they just work fine and whenever a bug occurs it's fixed immediately. Give it a try and see how fast you can develop powerful SWT-UIs.

At the very moment you bring EMF into your project it opens up the door for fairly everything you and your customers ever dreamed of (take a look at the teneo to presist your model in a SQL-Database using hibernate, working with distributed objects using CDO, validating your model using OCL and much more).

On UI-Side of Databinding also many new features have been added. You have support for Inline-Editing in Table/TreeViewers (every control inheriting from it e.g. GridViewer), there's new support for Observable-TreeViewers and naturally many many bugfixes [75].

The future


JFace-Viewers/ToolTips


Naturally we are going to fix bugs and problems. I have already some bugs in my queue I can address after the Ganymede-Release is out of the doors. Looking at this back log of viewer bugs [228] I'm going to try to bring this bug count down a bit (say 200 is a good number).

Databinding


I see a bright future for databinding and I'll restart my work on bringing all this (databinding+emf) to the web using it in my GWT-Enabled applications inside my UFace-project if time permits.

Summary


I think all people worked on the projects above have done an amazing job. We fixed many bugs added many great new features, many with the help from the community whether they filed sensetational bug reports or even provided patches. A big thank goes out to you, the community.

One more note in the end. In time of 3.4 we saw the creation of a new project called E4. It was discussed controversial in the blog space and on mailling list as you all known.

After EclipseCon I decided as a community member to take part in this effort for the next generation of an UI-Framework provided by the Eclipse Organisation and had a lot of fun until then. If you are interested in learning new things and exploring new areas in space of ui, resource-managment, model-driven development I can only advice you to take part and learn how to organize, design and implement one of the tools that will have infulence on the next generation of thousands of commercial and none-commercial products.

Thursday, June 05, 2008

E4 is more about bringing it to the web

Since the E4-Presentation at EclipseCon and the SWT-Talk most people think that E4 is only about bringing Eclipse to the web. THAT'S NOT TRUE.

E4 is much more and that SWT gets a web-port is only a small part. Here's my top list of things for E4:

  • Modeldriven:
    One extensible model backing up the whole workbench

  • DOM: At the moment the Workbench is backed up by ONE model you automatically have a DOM and you can do with this DOM the same you do in Web-Applications (See my prototype)

  • New Resource Framework:
    Making handling resources much more Flexible

  • New Listener Concept:
    The current listener concept in eclipse sucks and makes eclipse slower than it could be

  • NO SINGLETONS AND STATIC FIELDS

  • Plugins in NONE-Java: Make it possible to write an Eclipse-Plugin in other languages (JavaScript, ...)

  • Declarative UI, Easier Styling .... and much more

Tuesday, May 20, 2008

A radical approach to explore new paths for e4

After EclipseCon 2008 and the E4 noise I started to rewrite the prototype shown there to use an EMF-Model (I'm going to refer to this prototype in the rest of this posting as PROTOTYPE_1).

It was quite cool to get insights into the platform code and with the code already created for EclipseCon it was not really an achievement to get something running within a fairly short time but finally I wasn't really happy because of multiple things:

  • I had to work around problems from the beginning to get a workbench up and running

  • It was hard to add new features because I was limited to things I could find a work-around for or going to learn the complete platform code which would have driven me mad

  • There was lack of feedback on the real code and we talked more about EMF pros and cons than concentrating on how we want to solve things (I'm still an EMF believer :-)


I asked myself how to solve the following problems:

  • How can I get up an Workbench-Window without any of the legacy code

  • How can I easily add features

  • How can I encourage people to work on E4 without having a deep understanding what's going on inside the current platform. In fact how can I get people outside the Platform-UI-Team to look at the code and understand in an affordable amount of time the concepts behind the workbench and bring up interesting ideas or outline how they think a feature can be implemented
Approximately 1 month ago I sat down and started to define a project which had the following targets:

  • A workbench with dependency on org.eclipse.jface, org.eclipse.equinox.common, org.eclipse.osgi, org.eclipse.emf

  • Built around an extensible EMF-Model

  • NO plugin.xml and NO .exsd (you'll see later how I extend the platform - it's a radical approach I know and looking back it got even more radical then I first thought it's going to be)

  • Similar but slightly improved EMF-Model compared the original one used to straight port the EclipseCon-Example

  • Allow multiple instances of the workbench inside one OSGi-Env - no singletons, no static variables!

  • As few API-Methods as possible (=suppress all the EMF-Methods and adding API-Methods e.g. to attach listeners or traverse the DOM generically) but still strongly typed

  • provide support for Scripting

Step 1: Redesign The Model From PROTOTYPE_1


I started to redesign the original model and removed some things I didn't like or found they are not needed yet. For example styles/styleclasses now work like they do in a Browser:
.myActiveView {
color: #FF0000;
background-color: #0000FF;
}

<span class="myActiveView" >Green on Blue</span>
where the style-properties and the class-properties are merged. I also moved all UI-Data (Font,Color,Gradient,...) from the UI-Element to the "css"-style definition whether an UI-Element reacts on a style property is the choice of the UI-Element and its implementor.

Step 2: Implementing the Workbench-UI-Core From Scratch

With the .ecore-Definition from Step 1 I created a static workbench.xmi file which defines a model of a static workbench.(Yes I started from a static model you'll see how dynamic such a model gets later). The final source code is ~ 88KB and the resulting .jar 36KB (the model, emf-dependencies are not part of this figures of course). But I think the target is reached I think there's no class having more than 500 Lines of Code (including the comments).
Creating .xmi-Files is a fairly trivial task because EMF comes with a generic editor and I guess people who know GMF could have written a graphical one with in a minute (any GMF-volunteers around?). When this step was finished my XMI-File looked like this

Step 3: Making the model dynamic


When starting Step 3 I first headed of and created .exsd-Files (you can see them here) to contribute the information to my model (views/perspectives). But while doing this I recognized that I'm redefining my .ecore-Model-Elements using .exsd so why the hell do I not provide plugin.xmi-artefacts instead of those plugin.xml files and at runtime create a complete workbench.xmi from all those artefacts. The hard part was to reimplement the loading of xmi-File (or rather to identify the source-code where the plugin.xml is processed to copy the logic). This left me with 3 files
  • workbench.xmi in org.eclipse.e4.workbench.ui

  • plugin.xmi in org.eclipse.e4.workbench.ui.ide contributing to workbench.xmi

  • plugin.xmi in org.eclipse.e4.workbench.ui.rhino contributing to plugin.xmi from org.eclipse.e4.workbench.ui.ide

Step 4: Implementing a Scritable-DOM


So now I had a workbench-model constructed at runtime using XMI-Artefacts. Doing some cool UI-Stuff was the next on my list. Wraping up an EObject as an Object-Scritable for Rhino was something I had already written for PROTOTYPE_1 so I "stole" the code from myself. The top feature on my list was to move a View (in 3.3 a ViewPart) in the model and automatically update the UI. So I wrote a view which presented the current workbench model inside a TreeViewer and allowed me to drag a view from stack to stack. It wasn't really is to distinguish a move from a remove but with help from Ed I managed to get it working. See the screen cast at the end of this posting.

Step 5: Persisting the current workbench state


So I was able to drag around the views but everytime I shut down the workbench and restarted model was recreated from the artifacts and started in the initial state. So adding persistance was next the next "big" issue. Well there's nothing more to say than these lines of code:

if (!restore) {
uri = URI.createPlatformPluginURI(
"/org.eclipse.e4.workbench.ui/META-INF/EWorkbench.xmi",true);
} else {
uri = URI.createFileURI(restoreFile);
}

// Save
try {
((EObject)workbench).eResource().save(null);
} catch (IOException e) {
e.printStackTrace();
}

Step 6: Extending the extension


Haven't you ever dreamed of extending an extension. I decided that my WorkbenchStructureViewPart should restore the current selection when coming up from a restored state but my generic model-element I contribute didn't had a slot to restore the information. So I digged into and searched how EMF allows me to extend an existing element (in fact once more Ed pointed me in the right direction). Now the plugin.xmi contributed by org.eclipse.e4.workbench.ui.rhino looks like this.

Step 7: Multiple Instances of the workbench


Not using org.eclipse.ui, no singletons and static variables automatically allows to have multiple workbench instances running. So in theory making this workbench run on top of the RAP framework should be possible without patching any code parts.

Acknowledgement / A Screencast / How to get it run


Before I forget about it two other guys (Boris and Ed) provided ideas, code and input to those freaking lines of code available from Eclipse-CVS using this ProjectSet.

Finally I created a Screencast for you to look at (it's a bit big (15MB) because I have no idea how to do Screencasting with OSS-Software on OS-X).

video

You'll see that I radically stripped down everything and made some strange decisions (e.g. no plugin.xml), backwards compatibility is not addressed at all, ... . Whether you like the idea of contributing XMI-Artefacts instead of .exsd & plugin.xml is not the question. The interesting thing IMHO is that it takes so few lines of code to show a nice workbench backed up by a model and reacting on (structural-)changes inside of it.

Thursday, March 20, 2008

Eclipse E4 and UFacekit

E4 and my impression

Haveing attended the E4 Talk, A Future of SWT and the E4 BOF. I'm looking forward for a lot of innovation and discussion about new architectures at various levels of the Eclipse-Platform.

The most important thing to notice is that E4 is much more than simply bringing RCP to the webspace. Still I'm going to concentrate on the UI-Aspect of E4 in the rest of the post.

There's never been a better time to start getting involved because I myself (or you yourself) can to some extend define how the future looks like.

From the discussion I had with all the guys from the Platform/SWT/...-team I feel fairly comfortable infact I'm glad the Platform/SWT-Team recognized that RAP is not the only solution to get RCP-Applications run inside the browsers. The current SWT-prototype code uses established technologies like GWT, Dojo. In fact with the current prototype design SWT is going to be for DOJO what GWT-Ext/MyGWT are for Ext-Js nowadays.

UFacekit and E4

Do we still have to put effort into UFacekit?

When I first saw what's been done by the E4-Prototypers my first reaction was: Do we still need to work UFacekit? My answer is definately YES because UFacekite is more than providing a possibility to run your Desktop-UI inside a Browser. UFacekit has more to offer than a uniform Widget-API. UFacekit provides other values:

  • Eclipse-Core-Databinding compatible to GWT

  • Eclipse-EMF-Ecore compatible to GWT

  • Highlevel-Abstraction for Eclipse-Databinding

  • Easy support for Decoration, ...

  • ... and much more

If SWT for Browser is getting reality (and it will trust me) people will want to use all this stuff in their application and then UFace provides them with all they need.

How can UFacekit profit


Well we get a first class Browser-Widget implementation for free or even better we can take part to make this happen (I'm willing get part of this effort) and use it in UFacekit.

UFacekit News

  • I added an Example how to use EMF + UFacekit inside GWT.
    You can take a look at the code here.

  • Angelo started to add CSS-Support for SWT-Widget in his own project and offered to donate it to UFacekit but I didn't had time to take look how to use it in UFacekit until now

  • Work on GWT-Ext port continues but getting the layout stuff right is a real pain

Thursday, March 06, 2008

UFace - Update

I recognized today that I haven't blogged about one of my favorite OSS-project (UFace/UFacekit) lately.

For those of you who have never heard of this project let me introduce it in a few sentences.

UFace or UFacekit has the following targets:

  • Add a highlevel API above Eclipse-Databinding

  • Helping Eclipse-Databinding to gain momentum outside Eclipse/SWT/JFace world by providing Observable-Implementation for various UI-Toolkits like Swing, GWT, ...

  • Helping OSGi to be used in UI-Applications outside Eclipse-RCP e.g. in Swing Applications

  • Providing a uniform UI-API for all those widget-systems including builders for common form layouts (e.g. 2 column label/field list)


We have been fairly busy lately and added the following things into UFace:

  • Validation and Decoration Support (contributed by Kenneth Westelinck) for Swing and SWT

  • Worked heavily on the MyGWT integration

  • Maven-Build-System


Validation and Decoration


Adding decorations to a UIForms (our abstraction above the databindingContext providing a uniform API for different Databinding-Implementations JavaBean/EMF/UBean/...) is not more than adding these 2 lines to your sources:

StatusDecoratingInterceptor interceptor = 
new StatusDecoratingInterceptor(detailComposite);
detailForm_1.setAfterBindInterceptor(interceptor);


Darn cool, isn't it?

The resulting UI with validation error looks like this:

SWT on Win32:



Swing on Win32:


UFacekit implementation for MyGWT



Beside providing a higherlevel API above Eclipse-Databinding the other idea of UFace is to provide a uniform API to deploy your applications in different ways (Desktop, Web, Mobile-Devices, ...). In Web-Space we decided to go the GWT way which means your application is running completely in the browser and only business data is fetched from the server.

This concept is different from the one of RAP who, as far as I have understood the framework, does most of the work on the server-side and uses the browser "only" for rendering purposes (RAP devs please correct if I'm wrong here).

The hardest thing to bring to browsers are SWT-Layouts and that's where I'm currently progressing slowly but steadily at the moment. This is how the the same form looks like in the browser rendered with MyGWT:



It's not 100% right and Combo and List aren't working either but it was quite an achievement to get that far.

Current status / Release plans


My first draft plan was to have an M1-Milestone for JFace, Swing and MyGWT implementation ready for EclipseCon but I had to delay this because my current work load hasn't give me enough time to work on UFacekit too many hours. Today JFace and Swing are complete (as complete a first Milestone can be) and only MyGWT is missing so I hope we could have a first Milestone by April.

What's in the queue


We already have a queue for features we'd like to integrate (an incomplete list is this):

  • Support for more Widgets Tree/TreeTable, TabFolders, ...

  • Implementation ontop of Eclipse-Forms

  • Better looking decorations on Swing

  • Support for CSS to style your widgets

  • Extensible converts

Wednesday, January 23, 2008

EMF + Databinding - I'm adicted to this stuff

Ed blogged somedays ago about the progress he made makeing EMF available to RAP and J2ME and there are more and more people requesting a simple example project where some EMF-Databinding-Features are shown.

I've already send some code to the EMF-newsgroup and today I've added some more bits showing how to bind a Detail-List.



I'm going to add some more interesting stuff (e.g. field-dependencies, validation, ...) when I have time and will restart working on my article on EMF+Databinding+RCP+iBatis.

If you want to take a look at source code you can grab it from here.

There are some issues you need to be aware of when it comes to
e.g. Master-Detail + Field-Dependencies.

This is where UFace comes into play which handles this kind of thing for you (and even more).

Because I'm talking about UFace. We are making progress since the last blog entry the following things have happend:

  • refactored Factory-API to get extensible and not cluttered with overloaded methods

  • started to think how UForm can be used by native implementators (UForm is an abstraction level above Databinding and your Model-Implementation-Technology)

  • we added a new committer just today (Angelo Zerr) who develops some cool XML-UI things (See Akrogen) and is enhancing our Swing-Binding and SWT-Bindings. Welcome Angelo.

  • Set up a Committer and Contributor policy. I hate this legal stuff and we want to keep it at minimum but this has to be the foundation of every project

  • Received a code donation (SWT GridLayout for Swing) from Daniel Spiewak (See Daniels Code contribution)

Thursday, January 10, 2008

One month of UFacekit-Development

A month ago James Strachan and I started hacking on a project we named UFacekit.

We both faced the need to write datacentric applications for different deployment environments (Desktop (Swing/SWT), GWT (MyGWT/GWT-Ext), ...) and we thought there must be an easy and fast way to come up with something that makes our day job easier. At this very moment UFacekit was born.

There are different things we are targeting with the project.

  1. Provide a uniform Facade above widget implementations (SWT,Swing,GWT,...)

  2. Promote the use of Eclipse-Databinding (and other related technologies e.g. EMF) outside Eclipse-World (Swing,GWT, ...) and provide a highlevel API above the low-level databinding API

  3. Provide reuseable Bundles which can be used independently
    • you are only interested in Swing-Databinding but still want to use the native Swing-API? - UFacekit provides an indepented Swing-Observable bundle for you
    • you want to use an alternative Bean-like implementation not relying on reflection and EMF is too heavy for you? - UFacekit provides an independent implementation for you named UBean



Instead of writing an SWT-Port for GWT/Swing (I know for Swing there's already an SWT port) we decided to go the Facade/Factory way and started hacking and the progress we made in this very short period of time (we are only working on it in the evening) is more than amazing.

Take a look at the following Screenshots they show what's already possible with the current sources.





They look fairly identical (the only reason they not look completely the same is that I haven't ported the GridLayout from SWT to Swing but relying on Mig-Layout).

They are full of features you need many lines code without a framework doing the nifity bits for you (e.g. MasterDetail + Field-Dependencies):

  • Master-Detail support

  • Model-UI-Binding

  • Field-Dependencies (Country/Federalstate)



Setting up this UI needs:

  • ~ 80 Lines of Widget-Toolkit-Independent code

  • ~ 20 Lines of Widget-Dependent code (= the start of the application which is currently not abstracted)



The amazing thing is that both UIs are made up by the same source code:


public void createFormUI(UIComposite root) {
UIFactory ui = root.getFactory();

UBeanForm listForm = new UBeanForm();
final UBeanForm detailForm_1 = new UBeanForm();

UIComposite containerComposite = ui.newComposite(root, null, ui.newGridLayout(2));

TableColumn[] columns = {
new TableColumn("People", new NameLabelProvider())
};

UITable table = ui.newTable(listForm, containerComposite, new GridLayoutData(200, GridLayoutData.DEFAULT, GridLayoutData.ALIGN_BEGINNING, GridLayoutData.ALIGN_FILL, false, true), listForm.detailList(AddressBook.PEOPLE, Collection.class), columns);

// ---------------------

UIComposite detailComposite = ui.newComposite(containerComposite, new GridLayoutData(GridLayoutData.ALIGN_FILL, GridLayoutData.ALIGN_FILL, true, true), ui.newGridLayout(2));
ui.newLabel(detailComposite, new GridLayoutData(GridLayoutData.ALIGN_END, GridLayoutData.ALIGN_CENTER), "ID");
ui.newTextField(detailForm_1, detailComposite, new GridLayoutData(GridLayoutData.ALIGN_FILL, GridLayoutData.ALIGN_FILL, true, false), detailForm_1.detailValue(Person.ID, int.class));

ui.newLabel(detailComposite, new GridLayoutData(GridLayoutData.ALIGN_END, GridLayoutData.ALIGN_CENTER), "Name");
ui.newTextField(detailForm_1, detailComposite, new GridLayoutData(GridLayoutData.ALIGN_FILL, GridLayoutData.ALIGN_FILL, true, false), detailForm_1.detailValue(Person.NAME, String.class));

ui.newLabel(detailComposite, new GridLayoutData(GridLayoutData.ALIGN_END, GridLayoutData.ALIGN_CENTER), "Location");
ui.newTextArea(detailForm_1, detailComposite, new GridLayoutData(GridLayoutData.ALIGN_FILL, GridLayoutData.ALIGN_FILL, true, false), detailForm_1.detailValue(Person.LOCATION, String.class));

ui.newLabel(detailComposite, new GridLayoutData(GridLayoutData.ALIGN_END, GridLayoutData.ALIGN_CENTER), "Country");
UICombo combo = ui.newCombo(detailForm_1, detailComposite, new GridLayoutData(GridLayoutData.ALIGN_FILL, GridLayoutData.ALIGN_FILL, true, false), detailForm_1.detailValue(Person.COUNTRY, Country.class), ModelHelper.createWritableList(getModel().getCountries(), Country.class), new CountryLabelProvider());

ui.newLabel(detailComposite, new GridLayoutData(GridLayoutData.ALIGN_END, GridLayoutData.ALIGN_BEGINNING), "Federalstate");
ui.newDependentListBox(detailForm_1, detailComposite, new GridLayoutData(GridLayoutData.DEFAULT,120,GridLayoutData.ALIGN_FILL, GridLayoutData.ALIGN_FILL, true, false), detailForm_1.detailValue(Person.FEDERAL_STATE, FederalState.class), (IObservableList) detailForm_1.detailList(Country.FEDERAL_STATES, Collection.class).createObservable(combo.getSelectionObservable()), new FederalStateLabelProvider());

WritableValue value = ModelHelper.createWritableValue(getModel());
listForm.bind(value);

IObservableValue detailObservable = table.getSelectionObservable();
detailForm_1.bind(detailObservable);

UBeanForm detailForm_2 = new UBeanForm();

columns = new TableColumn[] {
new TableColumn("ID", new IDLabelProvider()),
new TableColumn("Name", new NameLabelProvider()),
new TableColumn("Location", new LocationLabelProvider())
};

ui.newLabel(detailComposite, new GridLayoutData(GridLayoutData.ALIGN_END, GridLayoutData.ALIGN_CENTER), "");
ui.newTable(detailForm_2, detailComposite, new GridLayoutData(GridLayoutData.ALIGN_FILL,GridLayoutData.ALIGN_FILL,true,true), detailForm_2.detailList(Person.FRIENDS, Collection.class), columns);
detailForm_2.bind(detailObservable);
}


  public void run(final String uiMethod) {
Display display = new Display();

Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
public void run() {
Shell shell = createUI(uiMethod);
shell.setSize(650, 500);
shell.setText("UFacekit - JFace-Demo ");
Display display = Display.getCurrent();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
});
}

private Shell createUI(String uiMethod) {
final Shell shell = new Shell();
SWTComposite composite = new SWTComposite(shell,new JFaceFactory().newFillLayout());
// generic code as shown above


You can even more reduce the size and complexity of the source by using FormBuilder-classes we are going to provide to make creating standard-forms like this as simple as possible.

Before we are publishing a first cut we need to finish the GWT-implementation (GWT/MyGWT/GWT-Ext) but we (in this case James) are on a good way and we should have a release fairly soon. Naturally there are some gaps (e.g. missing widgets, API inconsistencies) but hey the project just got 1 month so I hope you don't mind.

Did this spot your interest? Come and join our google group and share your ideas with us.