Hi,
I used to apply similar pattern as Thomas bt with some remarkable
difference.
here is the example to illustrate the differences and the concept
itself - it's quite simple and not show all possible combinations but
i think it's just enough for "getting started communication" - if you
were interested in it and need some hepl feel free to ask
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.ButtonElement;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.FormElement;
import com.google.gwt.user.client.Element;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Widget;
public class ExampleUiBinderWidget extends Widget {
public static interface UI {
Element root();
Element someButton();
Element someLabel();
}
public static class DefaultUI implements UI {
//different from thomas - I used to inject UiBinder interface
definition
//inside "the layout inner class" - why look below
@UiTemplate("com.tomaszgawel.example.client.ExampleUiBinderWidget.ui.xml")
static interface DefaultUIBinder extends UiBinder<DivElement,
DefaultUI> {}
final static DefaultUIBinder uiBinder =
GWT.create(DefaultUIBinder.class);
//i could have declared this fields the same as return types from
//coresponding UI methods - so avoid necessity to cast later -
//but it is to show the flexibility of this approach
DivElement _root;
@UiField ButtonElement _someButton;
@UiField SpanElement _someLabel;
public DefaultUI(){
_root = uiBinder.createAndBindUi(this);
}
@Override public Element root() {
return _root.cast();
}
@Override public Element someButton() {
return _someButton.cast();
}
@Override public Element someLabel() {
return _someLabel.cast();
}
}
UI ui;
int counter;
public ExampleUiBinderWidget(){
this(new DefaultUI());
}
public ExampleUiBinderWidget(UI ui){
assert ui != null : "Provide ui - widgets do not like to show
naked :P";
//move initailisation from constructor
//in case you want call setElement on something else than ui.root()
this.ui = ui;
init();
}
protected void init() {
setElement(ui.root());
someInitActions();
}
protected void someInitActions() {
DOM.sinkEvents(ui.someButton(), Event.ONCLICK);
DOM.setEventListener(ui.someButton(), new EventListener() {
@Override public void onBrowserEvent(Event event) {
counter++;
ui.someLabel().setInnerText("Button has been clicked " + counter +
" times.");
}
});
}
}
class SomeSubClass extends ExampleUiBinderWidget {
public static interface UI extends ExampleUiBinderWidget.UI {
//wrappingFormElement
FormElement form();
}
//could just implenet the UI - but we also inherit superclass
DefaultUI
//to save some lines of duplicate code
static class DefaultUI extends ExampleUiBinderWidget.DefaultUI
implements UI {
@UiTemplate("com.tomaszgawel.example.client.SomeSubClass.ui.xml")
static interface DefaultUIBinder extends UiBinder<DivElement,
DefaultUI> {}
final static DefaultUIBinder uiBinder =
GWT.create(DefaultUIBinder.class);
@UiField FormElement _form;
public DefaultUI(){
_root = uiBinder.createAndBindUi(this);
}
@Override public FormElement form() {
return _form;
}
}
public SomeSubClass(){
super(new DefaultUI());
}
public SomeSubClass(UI ui){
super(ui);
}
@Override
protected void init() {
//you must cast to subclasses UI to get to additional fields
//as member field ui is of type ExampleUiBinderWidget.UI
((UI) ui).form().setAction("
http://someserver.com");
//and you could do this before call to super.init
//as it is not a constructor
super.init();
//if you wuld prefer to set ELement on form not root
//instead of calling super.init just insert lines like this:
//setElement(((UI) ui).form());
//someInitActions();
}
}
class Test {
public static void test(){
//as we have constructor with UI as argument
//you can provide any UI defined outside the class
//only if it implements UI interface
//it can even not have anything to do with uibinder
//consider the UI that looks for ELement in html page
//(yes - that was why I extended Widget not Composite in that
example)
SomeSubClass ssc = new SomeSubClass(new SomeSubClass.UI() {
FormElement _form;
Element _root;
Element _button;
Element _label;
//initialisation block as anonymous class does not
//have a constructor
{
_root = Document.get().getBody().cast();
_form = _root.getElementsByTagName("form").getItem(0).cast();
_label = DOM.getElementById("someLabelOnThePage");
_button = _form.getElementsByTagName("button").getItem(0).cast();
assert _form != null && _root != null && _button != null &&
_label != null;
}
@Override public Element someLabel() {
return _label;
}
@Override public Element someButton() {
return _button;
}
@Override public Element root() {
return _root;
}
@Override public FormElement form() {
return _form;
}
});
}
}