July 31, 2012

Custom Containers with GWT UiBinder

I just wasted a whole day at work trying to figure out how to create my own container widget that will work with in GWT's UiBinder. In the end, I was forced to dig through the source to find the solution. If you take a look at the UIBinderClass.registerParsers(), you'll see that it has a list of hard coded ElementParsers. If you take a close look, you'll notice that google has registered 4 generic parsers: HasText,HasHTML,HasTreeItems,HasWidgets. So if you're Composite class implements any one of these interfaces then it will you're widget will support having some child element's within it's XML. In my case, I just wanted to create a custom decorated panel. So I simple created a class that extended the HasWidget interface.
public class Decorated extends Composite implements HasWidgets {
 private static DecoratedUiBinder uiBinder = GWT.create(DecoratedUiBinder.class);

 interface DecoratedUiBinder extends UiBinder {
 }

 public Decorated() {
  initWidget(uiBinder.createAndBindUi(this));
 }

 @UiField SimplePanel placeholder;
 
 @Override
 protected Widget getWidget() {
  return placeholder.getWidget();
 }

 @Override
 protected void setWidget(Widget widget) {
  placeholder.setWidget(widget);
 }

 @Override
 public void add(Widget w) {
  setWidget(w);
 }

 @Override
 public void clear() {
  setWidget(null);
 }

 @Override
 public Iterator iterator() {
  return Arrays.asList( getWidget() ).iterator();
 }

 @Override
 public boolean remove(Widget w) {
  if ( getWidget() == w ) {
   clear();
   return true;
  }
  return false;
 } 
}


<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui">
  <g:HTMLPanel>
    <div>
      <div>
         <g:SimplePanel ui:field="placeholder" />
      </div>
    </div>
  </g:HTMLPanel>
</ui:UiBinder>

1 comment:

Anonymous said...

Thanks, exactly what I was looking for :)