I don't want to learn new things if the one I'm familiar with would make my life much easier. JFace-Viewers is one of my main working areas in Eclipse-land. So I sat down and took a closer look and after 1 hour of work my GWT-code looks like this:
package at.bestsolution.eclipse.jface.example.client;
import java.util.ArrayList;
import org.gwtwidgets.client.util.SimpleDateParser;
import at.bestsolution.eclipse.jface.client.viewers.TreeViewer;
import at.bestsolution.eclipse.jface.example.client.model.Family;
import at.bestsolution.eclipse.jface.example.client.model.Person;
import at.bestsolution.eclipse.jface.example.client.ui.MyContentProvider;
import at.bestsolution.eclipse.jface.example.client.ui.MyLabelProvider;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Tree;
/**
* Entry point classes defineonModuleLoad()
.
*/
public class JFaceExampleApp implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
Tree tree = new Tree();
TreeViewer viewer = new TreeViewer(tree);
viewer.setLabelProvider(new MyLabelProvider());
viewer.setContentProvider(new MyContentProvider());
viewer.setInput(createInput());
RootPanel.get().add(tree);
}
private ArrayList createInput() {
SimpleDateParser parser = new SimpleDateParser("yyyy-MM-dd");
ArrayList list = new ArrayList();
Family fam = new Family("Schindl");
Person p = new Person("Tom",parser.parse("1979-05-01"),fam);
p = new Person("Tina",parser.parse("1980-10-14"),fam);
p = new Person("Laura",parser.parse("1991-08-07"),fam);
list.add(fam);
fam = new Family("Hoppichler");
p = new Person("Andreas",parser.parse("1977-11-06"),fam);
p = new Person("Franzi",parser.parse("1978-11-02"),fam);
list.add(fam);
return list;
}
}
And the respective Viewer-classes like this:
package at.bestsolution.eclipse.jface.example.client.ui;
import java.util.ArrayList;
import at.bestsolution.eclipse.jface.client.viewers.ITreeContentProvider;
import at.bestsolution.eclipse.jface.client.viewers.Viewer;
import at.bestsolution.eclipse.jface.example.client.model.Family;
import at.bestsolution.eclipse.jface.example.client.model.Person;
public class MyContentProvider implements ITreeContentProvider {
public Object[] getChildren(Object parentElement) {
if( parentElement instanceof Family ) {
return ((Family)parentElement).getList().toArray();
}
return new Object[0];
}
public Object getParent(Object element) {
if( element instanceof Person ) {
return ((Person)element).getFamily();
}
return null;
}
public boolean hasChildren(Object element) {
return getChildren(element).length > 0;
}
public Object[] getElements(Object inputElement) {
return ((ArrayList)inputElement).toArray();
}
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
package at.bestsolution.eclipse.jface.example.client.ui;
import org.gwtwidgets.client.util.SimpleDateFormat;
import at.bestsolution.eclipse.jface.client.viewers.ILabelProvider;
import at.bestsolution.eclipse.jface.example.client.model.Family;
import at.bestsolution.eclipse.jface.example.client.model.Person;
public class MyLabelProvider implements ILabelProvider {
private SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
public String getText(Object element) {
if( element instanceof Family ) {
return ((Family)element).getName();
} else if( element instanceof Person ) {
return ((Person)element).getName() + " ("+format.format(((Person)element).getBirthday())+")";
}
return "";
}
}
Now you think this is cool? Because this was to trivial I thought I'll have to go further and after ~ 6h I had ported the the core-parts from the JFace-Databinding-Framework to GWT! So my UI-Binding-Code looks like this now:
// ....
TextBox box = new TextBox();
TextBoxObservableValue targetValue = new TextBoxObservableValue(box,TextBoxObservableValue.Change);
IObservableValue modelValue = PEMFObservablesFactory.observeDetailValue(Realm.getDefault(), value, "id", String.class);
DataBindingContext ctx = new DataBindingContext();
UpdateValueStrategy targetToModel = new UpdateValueStrategy();
targetToModel.setConverter(new IConverter() {
public Object convert(Object fromObject) {
return fromObject.toString();
}
public Object getFromType() {
return null;
}
public Object getToType() {
return null;
}
});
UpdateValueStrategy modelToTarget = new UpdateValueStrategy();
modelToTarget.setConverter(new IConverter() {
public Object convert(Object fromObject) {
return fromObject.toString();
}
public Object getFromType() {
return null;
}
public Object getToType() {
return null;
}
});
ctx.bindValue(targetValue, modelValue, targetToModel, modelToTarget);
The GWT-Compiler translates all into JS-Code and because there's no Reflection-API available in this space I had to invent my own concept which I lend from EMF hence the name PEMF (for PoorEMF). Without question much of the Databinding-Framework is not working but at this stage I don't mind. The good thing is that all those low-level modules use fairly only classes already available from GWT so porting the whole framework is only a matter of time.
9 comments:
That is awesome. Would there be a way to make plug compatible?
Excellent. So next time when someone asks why we restrict ourselves to CDC/Foundation 1.0, I can point to this!
Well I don't know but when all those things are broken down to the Java-classes implemented by GWT or you reimplement those things it seems to be do able. Things that won't work are the one like OSGi because there's no class-loader, ... in JavaScript.
After thinking a bit more about this - how much would we have to change in the core data binding classes to make it (or a subset) work with GWT? Any chance we can do this with just one codebase, and in an API-compatible way?
having MVC + Databinding available through GWT would be cool and as discussed on IRC, I'm going to have a look at EMF 3.2 to see how this can also be compiled with GWT. This would make writing GWT applications a piece of cake :-)
Hi Boris, I think an API compatible way is possible but would mean that all current classes have to be moved into a package called "org.eclipse.core.databinding.client.*"
and the current classes are delegating to these classes and casting converting the internal types to the one externally visible which might have a big performance impact.
I think the better way is that we make the current databinding (and classes it depends on in core and icu) compileable with GWT and then setup a automatic conversion tool which only has to replaces package names. This way we would have one code base to maintain because the GWT implementation is created with a set of automatic scripts.
The other possibility would be to findout how one could work-around the client-package limitation in GWT, but I think we can do this at any given point later on when the proof-of-concept implementation is ready.
Just have a look on this article :
"GWT Databinding"
http://www.zenika.com/blog/2007/08/03/gwt-data-binding-english-version/
Thanks for the Pointer, looks interesting and to some extent the same I'm doing with Databinding but the scope of Databinding is a bit wider than the framework describe there. The most interesting thing is the how the automatic wrapper generation works.
This is a very nice article, I try to follow up for my example. OK, and I want to sugguest new best artical about GWT and Eclipse, That is Extjs-GWT on Eclipse which reduce development time.
I like this example and try to use extjs-gwt in eclipse project.
See more about Extjs-GWT on Eclipse by using Eclipse's plugin.
I think this Extjs-GWT article can help beginner to learn faster.
Post a Comment