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.

Saturday, January 05, 2008

EclipseCon: I'll be there

News 1:

Just booked my flight and my room at the Hyatt. I'm excited to meet you all.

There are so many interesting talks like Steve's talk about the future of SWT which I'm very interested in because recently the Web-2.0 movement hit me hard and I've started to make Eclipse-Core-Technologies available in Web-Env.

News 2:

The other news I'd like to share with we you is that together with James Strachan I started a fairly interesting "experiment" called UFaceKit.

In short the project aims to provide a facade above widget implementations to use a uniform API above various Java-Widget implementations to create Datacentric-Applications.

Beside providing this generic API the project is split into many individual plugins/bundles which can be used out of the uface-scope:

  • A light weight JavaBean like implementation useable without any reflection-API the implementation is called UBean

  • Observables for UBean like Eclipse provides an implementation for JavaBeans

  • UI-Observables for GWT/MyGWT/GWT-EXT

  • UI-Observables for Swing



As you see one of the "waste products" of this project is that Eclipse-Databinding is can be used by Swing/GWT/... developers.

If you are interested in the project take a look at our project page and join the google-group. We are in pre-alpha stage and code changes a lot but we appreciate your help e.g. to provide an implementation for other Java-UI toolkits (QT-Jambi, Android, ...), help us with the Swing, GWT implementations of course all code is released under EPL.

Primary targets currently are:

  • SWT/JFace

  • GWT-implementations