2010-11-26

UiBinder Support For ExtGWT (GXT)

I recently wrote about a new open source library I released that supports registering custom UiBinder ElementParser classes called gwt-customuibinder.  As mentioned in that blog post, I have also released an open source library that utilizes this approach to support the ExtGWT library from Sencha (GXT) in UiBinder XML files called gxt-uibinder.

The current version of GXT was created prior to GWT 2.0 UiBinder, so it does not implement the proper interfaces, such as HasWidgets, to behave properly in UiBinder.  This means that when a project needs to add GXT layouts and widgets, it all needs to be done programmatically in the "View" class rather than declaratively in XML.  This causes a huge burden on the developer.

With my recent work on adding custom UiBinder ElementParsers for GWT, I have been able to add new ElementParsers for the ExtGWT framework to make working with GXT widgets in UiBinder much more friendly.  This project has been released as gxt-uibinder.

Getting Started
First, you must inherit the module.  Since this library uses gwt-customuibinder to register custom ElementParser classes, this module must be inherited after all other <inherit> lines.

For example:
<module>

  <inherits name="com.google.gwt.user.User" />
  <inherits name="com.extjs.gxt.ui.GXT" />

  <inherits name="com.jhickman.web.gwt.gxtuibinder.GxtUiBinder" />

  <source path="client" />
  <source path="shared" />
</module>


Supported Components

As this is a fairly new project, not all components are supported.  The most important one, however, is the ContainerParser for subclasses of the Container component.

Container
Since most of the "panels" in GXT (such as LayoutContainer, ContentPanel, etc) extend Container, then all of these these will support nested children.

LayoutContainer
GXT LayoutContainer subclasses Container, so all of the above apply here as well.  The major difference, however, is the ability to apply different "Layouts".

Currently, there are 2 supported Layouts: FitLayout and BorderLayout.   Below shows examples of both.

FitLayout
<gxt:LayoutContainer layout="FitLayout">
  <Label text="Hi" />
</gxt:LayoutContainer>

BorderLayout
BorderLayout supports layout regions as child elements. This means that the children of a LayoutContainer using the BorderLayout must be one of <gxt:center>, <gxt:west>, <gxt:north>, <gxt:east>, and <gxt:south>. Each region can only appear once, but may appear in any order.

Also note that each region, except <gxt:center> must specify a size attribute, specified in pixels. These regions also support the folling attributes:
  • split
    • boolean value. true if resizable split panel is needed.
  • collapsible
    • boolean value. true if the panel should contain the collapse button.
  • margins
    • can be specified as a single integer (ie margins="5") to make all margins the same, or a comma separated list of 4 integers (ie margins="0,5,0,0"). The order is top, right, bottom, left

<gxt:LayoutContainer layout="BorderLayout">
  <gxt:north size="30">
    <gxt:ContentPanel>...</gxt:ContentPanel>
  </gxt:north>
  <gxt:center>
    <gxt:ContentPanel>...</gxt:ContentPanel>
  </gxt:center>
  <gxt:east size="50" split="true" collapsible="true">
    <gxt:ContentPanel>...</gxt:ContentPanel>
  </gxt:east>
</gxt:LayoutContainer>

ContentPanel
GXT ContentPanel subclasses LayoutContainer, so all of the above apply here as well.  The ContentPanel supports specifying top and bottom components.  This is typically used for status bars or toolbars.  This can be done by using the child elements: <gxt:topcomponent> and <gxt:bottomcomponent>.  These are optional children, and may appear only once each.

For example:
<gxt:ContentPanel heading="Admin Scripting Console">
  <gxt:topcomponent>
    <menu:MenuBar borders="true" /><!-- menu explained below -->
  </gxt:topcomponent>
</gxt:ContentPanel>

Menus


GXT menus are also supported.  Here is an example of its usage:

<gxt:ContentPanel heading="Some Panel">
  <gxt:topcomponent>
    <menu:MenuBar borders="true">
      <menu:MenuBarItem text="File">
        <menu:Menu>
          <menu:MenuItem text="New" ui:field="newMenuItem" />
          <menu:MenuItem text="Open" ui:field="openMenuItem" />
          <menu:MenuItem text="Save"  ui:field="saveMenuItem" />
          <menu:MenuItem text="Save As" ui:field="saveAsMenuItem" />
          <menu:CheckMenuItem checked="true" />
        </menu:Menu>
      </menu:MenuBarItem>
    </menu:MenuBar>
  </gxt:topcomponent>
  <gxt:LayoutContainer layout="BorderLayout">
    <gxt:center>
      <gxt:LayoutContainer layout="FitLayout">
        <gxt:Label>
      </gxt:LayoutContainer>
    </gxt:center>
  </gxt:LayoutContainer>
</gxt:ContentPanel>

Custom Event Handling

The GXT event model differs from GWT.  This means that the @UiHandler annotation cannot be directly used to apply widget event handlers back to the owning view class.

For this, I have created a new annotation that can be used for GXT widget event binding.   It's called @GxtUiHandler.

For example, let's say in the UiBinder XML, you have a GXT button that needs to execute.  In the XML, the ui:field is used as normal.

<gxt:Button text="submit" ui:field="submitButton" />

In the owning view Java class, a method to receive the event will have the @GxtUiHandler annotation applied as such:

@GxtUiHandler(uiField="submitButton", eventType=GxtEvent.Select)
public void submitForm(ButtonEvent event) {
  System.out.println("form Submitted");
}

Unlike the @UiHandler annotation, we have to tell the compiler what Event type it relates to.  This is the major difference between @GxtUiHandler and @UiHandler annotations.

Summary

This library is still in early development, so does not yet support all GXT widgets and properties, but it may have enough for any project to get started with using GXT in their UiBinder XML files.



11 comments:

Unknown said...

Could you attach the source code for this example? Which namespace I should use for 'gxt' in UiBinder.xml file? thanks

Justin Hickman said...

Sorry about that. I abbreviated the code snippets in this blog article. Check out the project site for more details. If I'm missing documentation on the project site, please let me know. I'll be happy to expand.

In short, the namespace you use will be the package that you're wanting to include in your UiBinder file. For example, if you want the GXT menus, you would use something like this:

<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:menu="urn:import:com.extjs.gxt.ui.client.widget.menu">

</ui:UiBinder>

The "menu" portion (prefix) can be changed to whatever you want, such as gxtmenu, or xmenu, etc. The important part is inside the quotes.

gwagener said...

Thanks for this project! We just started a GXT project and this is going to make things a lot nicer.

I found a couple of things lacking and lodged a couple of bugs. What's your policy on submitting patches?

Keep up the good work!

Justin Hickman said...

No policy yet on submission of patches. I am very open to any patches submitted. I'm not sure, at this point however, where the patches should be submitted. I just created a new issue template. You can submit there with the patch as an attachment.

Unknown said...

Hi,

Do Gxt-UiBinder work with GWT 2.2 ? Because i try to use it, and i have a binary incompatibility when i pass to the "design" view of my UiBinder XML file.

I installed as you said the gwt-customuibinder correctly.

Cordially,

Alexis

Justin Hickman said...

I'm not certain. I'll have to double check. If you're using the latest Eclipse plugin, are you using the UiBinder editor or the WindowBuilder editor? I haven't tested much with the GWT Designer. I've had reports that it doesn't work as GWT Designer assumes that the XML conforms to the standard GWT widgets.

Unknown said...

Hi,

In fact, i used Eclipse 3.6 (Helios) with GWT 2.2 (the SDK). And there is binary incompatibility when i put the inherit line: inherits name="com.jhickman.web.gwt.gxtuibinder.GxtUiBinder" /

But, i tried another way today:
I downgraded the GWT SDK to 2.1. There were problems with GWT Designer... So I tried the new GWT Designer in Beta version (http://dl.google.com/eclipse/inst/d2gwt/beta/3.6)
And now, it's work... a few. Now, all of my inherit lines work well, and when I pass to the "desgin" view, it's ok. And GXT code in my XML file is interpreted correctly.
But !!! I haven't got new Palette ! Just defaults palettes of UiBinder Design view are available. Without that, it's difficult to make GXT Interface, only with xml code ;D

Am I understandable ? ^^

Anyway, thank you very much for your work.

Cordially,

Alexis

Justin Hickman said...

There is currently an open issue (Issue 4) to add GWT-Designer support. I have yet to look into this as I do not use the GWT Designer. I manually write all my UiBinder XML.

If you want to leave comments on the issue or continue conversations, you can check out the discussion group: http://groups.google.com/group/gxt-uibinder

Vincent Lambert said...

Hello Justin,

Thanks for the library and the licensing. Would it be possible for you to re-upload the "true" version 1.2.0 of gwt-customuibinder please?

I am planning on using it on a project at the office but the download location might be an issue.
I came across the following link which fixes a bug for GWT-2.4.0: http://tjwebb.wordpress.com/2011/11/17/gwt-customuibinder-1-2-0-jar-download/

I'm not sure that I can easily get approval to include it in my project because of the published location.

Thanks

Justin Hickman said...

I have no affiliation with the blog link you posted. The official location for 1.2.0 is here: http://code.google.com/p/gwt-customuibinder/downloads/detail?name=gwt-customuibinder-1.2.0.jar. You can also get it through Maven.

Vincent Lambert said...

Thanks for the clarification about the 1.2.0 version, I'll re-download it and remove the one from that external site.