Compiere: Switching from Swing to GWT
Relatd javascript Articles
A month ago James Strachanand 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.
- Provide a uniform Facade above widget implementations (SWT,Swing,GWT,...)
- 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
- 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 voidcreateFormUI(UIComposite root) {
UIFactory ui = root.getFactory();
UBeanForm listForm = newUBeanForm();
finalUBeanForm detailForm_1 = new UBeanForm();
UIComposite containerComposite = ui.newComposite(root, null, ui.newGridLayout(2));
TableColumn[] columns = {
newTableColumn("People", newNameLabelProvider())
};
UITable table = ui.newTable(listForm, containerComposite, newGridLayoutData(200, GridLayoutData.DEFAULT, GridLayoutData.ALIGN_BEGINNING, GridLayoutData.ALIGN_FILL, false, true), listForm.detailList(AddressBook.PEOPLE, Collection.class), columns);
// ---------------------
UIComposite detailComposite = ui.newComposite(containerComposite, newGridLayoutData(GridLayoutData.ALIGN_FILL, GridLayoutData.ALIGN_FILL, true, true), ui.newGridLayout(2));
ui.newLabel(detailComposite, newGridLayoutData(GridLayoutData.ALIGN_END, GridLayoutData.ALIGN_CENTER), "ID");
ui.newTextField(detailForm_1, detailComposite, newGridLayoutData(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, newGridLayoutData(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, newGridLayoutData(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, newGridLayoutData(GridLayoutData.ALIGN_FILL, GridLayoutData.ALIGN_FILL, true, false), detailForm_1.detailValue(Person.COUNTRY, Country.class), ModelHelper.createWritableList(getModel().getCountries(), Country.class), newCountryLabelProvider());
ui.newLabel(detailComposite, new GridLayoutData(GridLayoutData.ALIGN_END, GridLayoutData.ALIGN_BEGINNING), "Federalstate");
ui.newDependentListBox(detailForm_1, detailComposite, newGridLayoutData(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()), newFederalStateLabelProvider());
WritableValue value = ModelHelper.createWritableValue(getModel());
listForm.bind(value);
IObservableValue detailObservable = table.getSelectionObservable();
detailForm_1.bind(detailObservable);
UBeanForm detailForm_2 = newUBeanForm();
columns = new TableColumn[] {
newTableColumn("ID", newIDLabelProvider()),
newTableColumn("Name", newNameLabelProvider()),
newTableColumn("Location", newLocationLabelProvider())
};
ui.newLabel(detailComposite, new GridLayoutData(GridLayoutData.ALIGN_END, GridLayoutData.ALIGN_CENTER), "");
ui.newTable(detailForm_2, detailComposite, newGridLayoutData(GridLayoutData.ALIGN_FILL,GridLayoutData.ALIGN_FILL,true,true), detailForm_2.detailList(Person.FRIENDS, Collection. class), columns);
detailForm_2.bind(detailObservable);
}
public voidrun( finalString uiMethod) {
Display display = newDisplay();
Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
public voidrun() {
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();
}
}
}
});
}
privateShell createUI(String uiMethod) {
finalShell shell = newShell();
SWTComposite composite = newSWTComposite(shell, newJFaceFactory().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 groupand share your ideas with us.
Related javascript Projects
A simple command-line tool to create the folders and helper files for a new JavaScript project/library. As a bonus, you can quickly create a website to promote your project.
When you start a new JavaScript library, how do you layout the source files, the tests, the distribution files? Do you have support scripts to generate distributions from source files? Run your JavaScript unit tests? Generators to create new unit test HTMLfiles?
mapper.js 1.2 allows you to add automatic area highlighting to image maps on your webpages (inc. export to SVG). It works in all the major browsers - Mozilla Firefox 1.5+, Opera 9+, Safari and IE6+. On older browsers, it can use "jsgraphics" from Walter Zorn (if installed), else it'll degrade and your visitors won't notice a thing.
This JavaScript client library allows you to make Facebook API calls from any web site and makes it easy to create Ajax Facebook applications. Since the library does not require any server-side code on your server, you can now create a Facebook application that can be hosted on any web site that serves static HTML. An application that uses this client library should be registered as an iframe type. This applies to either iframe Facebook apps that users access through the Facebook web site or apps that users access directly on the app’s own web sites. Almost all Facebook APIs are supported.
Using Caja, web apps can safely allow scripts in third party content.
The computer industry has only one significant success enabling documents to carry active content safely: scripts in web pages. Normal users regularly browse untrusted sites with Javascript turned on. Modulo browser bugs and phishing, they mostly remain safe. But even though web apps build on this success, they fail to provide its power. Web apps generally remove scripts from third party content, reducing content to passive data. Examples include webmail, groups, blogs, chat, docs and spreadsheets, wikis, and more.
Were scripts in an object-capability language, web apps could provide active content safely, simply, and flexibly. Surprisingly, this is possible within existing web standards. Caja represents our discovery that a subset of Javascript is an object-capability language
What is XSTM?
XSTM is a n open sourcelibrary which enables high performance object replication between processes. It is an object oriented Distributed Shared Memory, or a Distributed Object Cache.
XSTMhas similarities with technologies like Adobe Flex Data Services , JBoss Cache, Terracotta, Tangosol Coherence , ScaleOut , or IBM's ObjectGrid .
Our model is based on object shares, which work like file shares. When an object is added to a share, it appears on the other machines which have the same share opened. Modifications done to the fields of the object are from this point replicated between machines.
Read more in the project overview.
XSTMis made of three projects. The Java implementation is called JSTMand is the base from which
the other versions are derived. An adapted version made with Luciano, the
author of GWM , is available for GWT . It allowsthis library to be used in a browser. NSTM is a .NET port based on IKVM.
All implementations are compatible with each other so object replication can take
place e.g. between a Java server and a .NET Smart Client.



