|
|
There is a more up to date set of use cases at UiBinder
Declarative UI Construction in GWT
Joel Webber
Motivation & Use Cases
Writing imperative Java code to construct a user-interface hierarchy is awkward, and it makes working with UI designers difficult and/or impossible. What we want is to provide designers (and developers) with a simple way to define the static structure of applications and widgets, without having to write code.
It seems natural to define UI structure at the granularity of Composites. This will make it easy to define either entire applications declaratively, as well as simple widgets. It also provides a natural model for composing large structures from small ones, and for refactoring complex UI structures.
Imagine the following use pattern:
1. Designer creates a mock in Photoshop, Dreamweaver, ...
mymock.html
<html><body> <!-- A tree of buttons --> <div><div><button>Do something</button>... </body></html>
2. Developer and/or designer massages this into a GWT template for a page-like Widget
App.ui.xml
<g:HTML xmlns:g='http://code.google.com/webtoolkit/com.google.gwt.user.client.ui'> <!-- A tree of buttons --> <div><div><button>Do something</button>... </g:HTML>
App.java
class App extends Composite implements EntryPoint, Template {
public void onModuleLoad() {
// ...
}
}3. The template XML file can now run in the GWT hosted browser (a few clicks and/or command-line exec)
4. Developer and/or designer identifies Widget-like structures (including Panel-like structures, etc.) and factors them out into other templates
App.ui.xml
<!-- Note how we add a new namespace for the application's package --> <app:ButtonTree xmlns:g='http://code.google.com/webtoolkit/com.google.gwt.user.client.ui' xmlns:app='http://code.google.com/webtoolkit/com.example.myapp.client' />
ButtonTree.ui.xml
<g:Tree xmlns:g='http://code.google.com/webtoolkit/com.google.gwt.user.client.ui'>
<g:TreeItem>
<g:Button>Do something</g:Button>
</g:TreeItem>
</g:Tree>5. Still runnable!
- As always with GWT, styling is done with CSS.
- Designer and/or developer can tweak the template, and refresh the GWT hosted browser to see the working app.
- As developers add code to widgets identified above, the behavior is incorporated automatically.
- If either the designer or developer breaks anything (e.g. removing a necessary id attribute), the compiler can catch it and warn appropriately.
6. Goto 3
Goals and Non-goals
Goals:
- Simplicity.
- Designer-friendly (e.g. works with existing tools such as Dreamweaver).
- Small & fast generated code.
- Static type and identifier checking.
- Design/Implementation round-tripping.
- No runtime support required.
- Easy to use with 3rd-party widgets.
- No changes to widgets required.
Non-Goals:
- Runtime evaluation (i.e. client-side markup).
- Mixing code & markup.
- Generating static HTML.
A Simple Example
In this rather contrived example, we define a simple labeled text box using HTML and TextBox widgets embedded in a HorizontalPanel.
EditableTextBox.ui.xml:
<g:HorizontalPanel xmlns:g='http://code.google.com/webtoolkit/com.google.gwt.user.client.ui'> <g:HTML id='label'>This <em>text box</em> is editable:</g:HTML> <g:TextBox id='editor'/> <g:HorizontalPanel>
EditableTextBox.java:
public abstract class EditableTextBox extends Composite implements Template {
public static EditableTextBox create() {
return (EditableTextBox) GWT.create(EditableTextBox.class);
}
public EditableTextBox() {
getEditor().setText("default text");
}
public void setCaption(String captionHTML) {
getCaption().setHTML(captionHTML);
}
public String getValue() {
return getEditor().getText();
}
protected abstract HTML getCaption();
protected abstract TextBox getEditor();
}A More Complex Example
Here, we have an example of a composite that would define the outer superstructure of an application.
A couple of important things to notice here:
- Using the HTMLPanel allows us to build part of the structure using HTML instead of lots of nested panels. This can be very efficient for cases where we don't need to do much of anything to it dynamically.
- The TabPanel structure shown below gives an example of a panel that requires per-child arguments.
- The MenuItem shows that not all elements need to refer to full widgets.
- MainComposite and SettingsComposite are assumed to be other parts of the app, which could themselves be built using the declarative UI system. Doing so should make it easy to refactor your UI as the design evolves.
App.ui.xml:
<g:HTMLPanel xmlns:g='http://code.google.com/webtoolkit/com.google.gwt.user.client.ui'>
<div class='banner' style='width:100%'>
<img src='myLogo.gif'/>
Welcome to my application. It's really cool.
</div>
<g:MenuBar>
<g:MenuItem caption='file'>
<g:MenuBar>
<g:MenuItem caption='open'/ id='openMenu'>
<g:MenuItem caption='close' id='closeMenu'/>
<g:MenuItem caption='exit' id='exitMenu'/>
</g:MenuBar>
</g:MenuItem>
</g:MenuBar>
<div class='app' style='width:100%'>
<g:TabPanel id='tabs'>
<g:Tab>
<g:TabCaption><em>Main</em></g:TabCaption>
<g:MainComposite id='main'/>
</g:Tab>
<g:Tab>
<g:TabCaption><em>Settings</em></g:TabCaption>
<g:SettingsComposite id='settings'/>
</g:Tab>
</g:TabPanel>
</div>
</g:HTMLPanel>App.java:
public abstract class App extends Composite implements Template {
public static App create() {
return (App) GWT.create(App.class);
}
public App() {
getExitMenu().setCommand(new Command() {
public void execute() {
// Exit the app.
}
});
// etc...
}
protected abstract MenuItem getOpenMenu();
protected abstract MenuItem getCloseMenu();
protected abstract MenuItem getExitMenu();
protected abstract TabPanel getTabs();
protected abstract MainComposite getMain();
protected abstract SettingsComposite getSettings();
}Restrictions and Caveats
Because it uses a generator, composites defined this way must be created using GWT.create(). This also implies that they must have a no-argument constructor (because you cannot pass parameters to GWT.create(). A simple way to make this a little cleaner is to create a public static create() method, so that the site of instantiation just looks like MyWidget w = MyWidget.create().
public static MyWidget create() {
return (MyWidget)GWT.create(MyWidget.class);
}Widgets instantiated by a template composite must also have a no-argument constructor, because the code generator doesn't know what arguments to pass to them (This restriction can be worked around with a custom parser; see below).
Implementation Details
As shown above, the composite base class implements 'Template', which is simply a tag interface that triggers a generator. The generator will find the associated ui.xml and generate a concrete implementation that constructs the widget hierarchy and implements all of the widget getter methods().
(More to come on how the xml gets parsed, how xml structures are defined for widgets, and so forth)
Open Questions
- It would be nice to generate a Java interface skeleton from an xml file to boostrap the process.
- I18n (string replacement and the like).
- ImageBundle support.
Sign in to add a comment

How serious is this being proposed? Is there, say a 100% chance that it will happen in 5 years, or a random idea that isn't likely to ever move beyond this page?
It's not just a proposal -- Joel is working on it!
@joel - any news?
As for the img bundle support, here's a simple idea:
public interface MyImageBundle extends ImageBundle { AbstractImagePrototype myImg();The rest is already implemented.
Is the code available for us to use the DeclarativeUi?
Something like that I've been implemented in 'gwt-ui' project: http://code.google.com/p/gwt-ui/
But main idea of gwt-ui was not 'declarative ui', but 'declarative states'. But idea and code of 'gwt-ui' can be simply updated to implement idea of 'declarative ui'
Is this a project that will be implemented soon? I would have this need and it would be great if I could use GWT and declare UI in XML.
The proposal is so exciting to make GWT more friendly to developer. also, a IDE plugin to preview the declarativeUI would makes code more WYSIWYG.
Great feature!
This would be an awesome feature and probably the only reason I didn't jump into GWT from the beginning -- Declarative is by far a better way to define UIs. Let's hope this gets released soon!
Declarative UI or not.. anyone has experience with both? I have seen that Echo2 was working just by writing code in Java but then they moved to declare things in Javascript. Ext has been moved to Gwt, since they have kind of declarative Javascript. Backbase has declarative XML like format. For complex things does dreamweaver really works? I think at the very end web developers will have to totally separate the design thing just as a matter of creating a raw image output of how an application looks like and then hire a programmer to make that design a reality into the application and at the same time make it modifiable, which is a pain but for facebook-like applications I think it is worth the time
The ZK Ajax framework has adopted this concept since day 1 and it is really useful and convenient. However, what I want to say is that all these declarative UI tags should come out some sort of standards, (e.g. XUL) that users don't have to learn several tag set.
Agreed. Definitely need some standardization on the declarative ui markup languages already around.
http://en.wikipedia.org/wiki/List_of_user_interface_markup_languages
i was reading the Andriod site and they mentioned something about XML UI markup as well. It seems it's extremely simple right now with a few UI elements and controls. Is this project related to that one?
Here's a XulGuiBuilder? implementation that takes a xul file and a GWT panel and builds GWT widgets based on the xul file into the GWT panel. You then look up the xul ID of each widget to populate data, set listeners, etc... The designer can focus on layout without code and the developer connects things up. Like the old windows resource file for GUI days.
I wrote this idea up when GWT first came out 2 years ago for another project but decided to stay with my existing framework because GWT did not have enough widgets so the code stayed dormant.
Now that I see others are talking about similar ideas, I'm happy to contribute to share. The zip file belong contains the entire netbeans 6.1 project. You can also run it from the command line via "MainEntryPoint?-shell.cmd" (must have gwt installed of course). http://www.killaman.com/GwtUtils.zip
In the sample web app, click on the "XUL samples" link. Each button loads another xul file and builds the widgets in the content area. Also, the "XUL Preview" link has a LIVE preview area where you can type XUL and get an instant preview by pressing the Preview button (the preview will show up in a popup, this needs server support so you need to run via the .cmd and not just browse to the html pages unlike the xul samples which work without a server).
Here's some sample code:
Robert
Hmm... the sample code lines got run together by the wiki... Well, here are 2 screen captures:
Robert - I tried to download your sample (GwtUtils?.zip) - but it's telling me "page not found".
Wouldn't it be the sweetness if GWT declarative ui was (easily) mappable to Android declarative ui?
I'm involved in a project attempting to target both platforms from a single code base right now and having this sort of consistency could potentially reduce initial investment and maintenance overhead significantly.
For those unfamiliar with Android ui design an example (and links to more info) can be found at the following URL: http://code.google.com/android/devel/ui/xml.html
It's from January 2007 that I'm working with GWT and now I think that an XML approach for UI generation is a must if you want to develop a really big application with it.
Some months ago I've started to work on a Declarative XML UI approach for GWT. The result is a first library based on the ideas described in this page and some ideas that I've collected during this year. In my approach the XML that you can write have a lot of similarities with XSLT: there are templates, variables, parameters, actions and GWT components like Panels, TextBox???, CheckBox???, etc.
In my implementation you can decide if the XML is store with the compiled javascript or you can retrieve it from the server on runtime in order to generate dynamically user interfaces as GWT widgets accessible later like the Template approach described here.
The good think is that GWT code contains only the logic of your application and you can delegate a lot of part of the UI generation to the XML-GWT UI builder.
Now I've started to use it on a first real project.
It's difficult to explain all ideas behind my approach, but I hope to receive feedbacks about it.