Hello UiBinder

9 views
Skip to first unread message

rj...@google.com

unread,
Aug 4, 2009, 1:44:38 PM8/4/09
to j...@google.com, google-web-tool...@googlegroups.com
Reviewers: jgw,

Description:
Introduces UiBinder

http://code.google.com/p/google-web-toolkit-incubator/wiki/UiBinder

The actual source code has been through thorough code review over the
last year+ of use in various Google projects, including the new AdWords
UI and Wave. Feedback and criticism is of course solicited, but I'm
planning to submit this patch unmodified to serve as a base line.

The exception to the above is the eclipse .classpath. Does that look
right?

Please review this at http://gwt-code-reviews.appspot.com/51831

Affected files:
eclipse/user/.classpath
user/src/com/google/gwt/uibinder/UiBinder.gwt.xml
user/src/com/google/gwt/uibinder/client/AbstractUiBinder.java
user/src/com/google/gwt/uibinder/client/DomHolder.java
user/src/com/google/gwt/uibinder/client/UiBinder.java
user/src/com/google/gwt/uibinder/client/UiBinderUtil.java
user/src/com/google/gwt/uibinder/client/UiConstructor.java
user/src/com/google/gwt/uibinder/client/UiFactory.java
user/src/com/google/gwt/uibinder/client/UiField.java
user/src/com/google/gwt/uibinder/client/UiHandler.java
user/src/com/google/gwt/uibinder/client/UiTemplate.java
user/src/com/google/gwt/uibinder/parsers/AttributeMessageInterpreter.java
user/src/com/google/gwt/uibinder/parsers/AttributeMessageParser.java
user/src/com/google/gwt/uibinder/parsers/AttributeParser.java
user/src/com/google/gwt/uibinder/parsers/BeanParser.java
user/src/com/google/gwt/uibinder/parsers/BooleanAttributeParser.java
user/src/com/google/gwt/uibinder/parsers/BundleAttributeParser.java
user/src/com/google/gwt/uibinder/parsers/CellPanelParser.java
user/src/com/google/gwt/uibinder/parsers/ComputedAttributeInterpreter.java
user/src/com/google/gwt/uibinder/parsers/CustomButtonParser.java
user/src/com/google/gwt/uibinder/parsers/DisclosurePanelParser.java
user/src/com/google/gwt/uibinder/parsers/DockPanelParser.java
user/src/com/google/gwt/uibinder/parsers/DomElementParser.java
user/src/com/google/gwt/uibinder/parsers/ElementParser.java
user/src/com/google/gwt/uibinder/parsers/FieldInterpreter.java
user/src/com/google/gwt/uibinder/parsers/HTMLPanelParser.java
user/src/com/google/gwt/uibinder/parsers/HasHTMLParser.java
user/src/com/google/gwt/uibinder/parsers/HasTextParser.java
user/src/com/google/gwt/uibinder/parsers/HasWidgetsParser.java

user/src/com/google/gwt/uibinder/parsers/HorizontalAlignmentConstantParser.java
user/src/com/google/gwt/uibinder/parsers/HtmlInterpreter.java
user/src/com/google/gwt/uibinder/parsers/HtmlMessageInterpreter.java
user/src/com/google/gwt/uibinder/parsers/HtmlPlaceholderInterpreter.java
user/src/com/google/gwt/uibinder/parsers/IntPairParser.java
user/src/com/google/gwt/uibinder/parsers/IntParser.java
user/src/com/google/gwt/uibinder/parsers/InterpreterPipe.java
user/src/com/google/gwt/uibinder/parsers/MenuBarParser.java
user/src/com/google/gwt/uibinder/parsers/MenuItemParser.java
user/src/com/google/gwt/uibinder/parsers/NullInterpreter.java
user/src/com/google/gwt/uibinder/parsers/RadioButtonParser.java
user/src/com/google/gwt/uibinder/parsers/StackPanelParser.java
user/src/com/google/gwt/uibinder/parsers/StringAttributeParser.java
user/src/com/google/gwt/uibinder/parsers/TabPanelParser.java
user/src/com/google/gwt/uibinder/parsers/TextInterpreter.java
user/src/com/google/gwt/uibinder/parsers/TextPlaceholderInterpreter.java
user/src/com/google/gwt/uibinder/parsers/UIObjectParser.java

user/src/com/google/gwt/uibinder/parsers/VerticalAlignmentConstantParser.java
user/src/com/google/gwt/uibinder/parsers/WidgetInterpreter.java
user/src/com/google/gwt/uibinder/parsers/WidgetPlaceholderInterpreter.java
user/src/com/google/gwt/uibinder/rebind/ChildWalker.java
user/src/com/google/gwt/uibinder/rebind/FieldManager.java
user/src/com/google/gwt/uibinder/rebind/FieldWriter.java
user/src/com/google/gwt/uibinder/rebind/GetInnerHtmlVisitor.java
user/src/com/google/gwt/uibinder/rebind/GetInnerTextVisitor.java
user/src/com/google/gwt/uibinder/rebind/GwtResourceEntityResolver.java
user/src/com/google/gwt/uibinder/rebind/HandlerEvaluator.java
user/src/com/google/gwt/uibinder/rebind/IndentedWriter.java
user/src/com/google/gwt/uibinder/rebind/NodeVisitor.java
user/src/com/google/gwt/uibinder/rebind/Tokenator.java
user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
user/src/com/google/gwt/uibinder/rebind/XMLAttribute.java
user/src/com/google/gwt/uibinder/rebind/XMLElement.java
user/src/com/google/gwt/uibinder/rebind/messages/AttributeMessage.java

user/src/com/google/gwt/uibinder/rebind/messages/GenerateAnnotationWriter.java
user/src/com/google/gwt/uibinder/rebind/messages/MessageWriter.java
user/src/com/google/gwt/uibinder/rebind/messages/MessagesWriter.java

user/src/com/google/gwt/uibinder/rebind/messages/PlaceholderInterpreter.java
user/src/com/google/gwt/uibinder/rebind/messages/PlaceholderWriter.java
user/src/com/google/gwt/uibinder/rebind/model/OwnerClass.java
user/src/com/google/gwt/uibinder/rebind/model/OwnerField.java
user/src/com/google/gwt/uibinder/rebind/model/OwnerFieldClass.java
user/src/com/google/gwt/uibinder/resources/xhtml.ent
user/src/com/google/gwt/uibinder/sample/UiBinderDemo.gwt.xml
user/src/com/google/gwt/uibinder/sample/client/AnnotatedStrictLabel.java
user/src/com/google/gwt/uibinder/sample/client/ClickyLink.java
user/src/com/google/gwt/uibinder/sample/client/DomBasedUi.css
user/src/com/google/gwt/uibinder/sample/client/DomBasedUi.java
user/src/com/google/gwt/uibinder/sample/client/DomBasedUi.ui.xml
user/src/com/google/gwt/uibinder/sample/client/ExplicitElementPanel.java
user/src/com/google/gwt/uibinder/sample/client/ExplicitElementWidget.java
user/src/com/google/gwt/uibinder/sample/client/FakeBundle.java
user/src/com/google/gwt/uibinder/sample/client/Foo.java
user/src/com/google/gwt/uibinder/sample/client/FooLabel.java
user/src/com/google/gwt/uibinder/sample/client/HandlerDemo.java
user/src/com/google/gwt/uibinder/sample/client/HandlerDemo.ui.xml
user/src/com/google/gwt/uibinder/sample/client/MyDatePicker.java
user/src/com/google/gwt/uibinder/sample/client/MyEntities.ent

user/src/com/google/gwt/uibinder/sample/client/NeedlesslyAnnotatedLabel.java

user/src/com/google/gwt/uibinder/sample/client/PointlessRadioButtonSubclass.java
user/src/com/google/gwt/uibinder/sample/client/StrictLabel.java
user/src/com/google/gwt/uibinder/sample/client/UiBinderDemo.java
user/src/com/google/gwt/uibinder/sample/client/WidgetBasedUi.css
user/src/com/google/gwt/uibinder/sample/client/WidgetBasedUi.java
user/src/com/google/gwt/uibinder/sample/client/WidgetBasedUi.ui.xml
user/src/com/google/gwt/uibinder/sample/client/WidgetBasedUiResources.java
user/src/com/google/gwt/uibinder/sample/public/UiBinderDemo.html
user/src/com/google/gwt/uibinder/testing/BUILD
user/src/com/google/gwt/uibinder/testing/UiBinderTesting.java
user/test/com/google/gwt/uibinder/JClassTypeAdapter.java
user/test/com/google/gwt/uibinder/UiBinderGwtSuite.java
user/test/com/google/gwt/uibinder/UiBinderSmallSuite.java
user/test/com/google/gwt/uibinder/UiBinderTestModule.gwt.xml
user/test/com/google/gwt/uibinder/client/UiBinderTest.java

user/test/com/google/gwt/uibinder/rebind/GwtResourceEntityResolverTest.java
user/test/com/google/gwt/uibinder/rebind/HandlerEvaluatorTest.java
user/test/com/google/gwt/uibinder/rebind/TokenatorTest.java
user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java
user/test/com/google/gwt/uibinder/rebind/model/OwnerClassTest.java
user/test/com/google/gwt/uibinder/rebind/model/OwnerFieldClassTest.java
user/test/com/google/gwt/uibinder/rebind/model/OwnerFieldTest.java


Amir Kashani

unread,
Aug 4, 2009, 2:10:13 PM8/4/09
to Google-Web-Tool...@googlegroups.com
Hello, yourself. This looks absolutely awesome! Thank you!

- Amir

rj...@google.com

unread,
Aug 4, 2009, 2:50:55 PM8/4/09
to j...@google.com, google-web-tool...@googlegroups.com
On 2009/08/04 17:44:38, Ray Ryan wrote:


A question for the group: the stuff under rebind and parsers should not
be considered public API, it's just not ready for that. Is javadoc to
that effect enough of a deterrent? (Although I suppose the fact that you
can't actually make your own parsers and such *do* anything yet will
make the issue moot.)

http://gwt-code-reviews.appspot.com/51831

j...@google.com

unread,
Aug 4, 2009, 3:31:13 PM8/4/09
to rj...@google.com, google-web-tool...@googlegroups.com
On 2009/08/04 18:50:55, Ray Ryan wrote:
> On 2009/08/04 17:44:38, Ray Ryan wrote:
> >

> A question for the group: the stuff under rebind and parsers should
not be
> considered public API, it's just not ready for that. Is javadoc to
that effect
> enough of a deterrent? (Although I suppose the fact that you can't
actually make
> your own parsers and such *do* anything yet will make the issue moot.)

I would assume that if you can't usefully write your own yet, then it's
pretty safe to keep evolving the API. I assume that there's a
2.0-time-frame task to make a public API for parsers?

http://gwt-code-reviews.appspot.com/51831

Ray Ryan

unread,
Aug 4, 2009, 3:31:46 PM8/4/09
to rj...@google.com, j...@google.com, google-web-tool...@googlegroups.com
I was thinking 2.1, actually. 

j...@google.com

unread,
Aug 4, 2009, 3:32:59 PM8/4/09
to rj...@google.com, google-web-tool...@googlegroups.com
LGTM, based primarily on the fact that I know it works already, and with
the knowledge that there are some tasks left to be completed (like the
parser API).

I also assume that at some point we'll need to move the sample code out
into a proper sample, and that we'll want to come back and change our
existing samples to use UiBinder as well.


http://gwt-code-reviews.appspot.com/51831/diff/1/2
File eclipse/user/.classpath (right):

http://gwt-code-reviews.appspot.com/51831/diff/1/2#newcode19
Line 19: <classpathentry kind="var"
path="GWT_TOOLS/lib/easymock/easymockclassextension.jar"
sourcepath="/GWT_TOOLS/lib/easymock/easymockclassextension-src.zip"/>
I'll assume that all these libraries are necessary, and that you've
checked up on the licenses and made sure they're in the /tools repo.

http://gwt-code-reviews.appspot.com/51831/diff/1/6
File user/src/com/google/gwt/uibinder/client/UiBinder.java (right):

http://gwt-code-reviews.appspot.com/51831/diff/1/6#newcode36
Line 36:
There was talk at one point of re-unifying these methods. If that's
still in the cards, should we make a note to that effect as a warning?

http://gwt-code-reviews.appspot.com/51831/diff/1/17
File
user/src/com/google/gwt/uibinder/parsers/BooleanAttributeParser.java
(right):

http://gwt-code-reviews.appspot.com/51831/diff/1/17#newcode26
Line 26: // TODO(jgw): check validity.
Hey, that looks like my mistake :)

http://gwt-code-reviews.appspot.com/51831

Joel Webber

unread,
Aug 4, 2009, 3:35:14 PM8/4/09
to Ray Ryan, google-web-tool...@googlegroups.com
Ok, then we'll need to be pretty clear about that in the documentation, because it's a pretty serious landmine (i.e., in that existing projects could easily have some widgets that couldn't be directly used with UiBinder without hackery). As an example, I'm going to have to add some parsers for LayoutPanel, et al, because they have somewhat unusual construction semantics.

Amir Kashani

unread,
Aug 4, 2009, 3:42:10 PM8/4/09
to Google-Web-Tool...@googlegroups.com
What are the limitations for a Widget developer without a custom parser? I've only begun to look at the code, but it seems like it'll still be possible to use a custom widget albeit with cumbersome markup.

- Amir

Ray Ryan

unread,
Aug 4, 2009, 3:45:56 PM8/4/09
to Google-Web-Tool...@googlegroups.com
The need for a custom parser is actually pretty rare. Any widget with a zero args constructor and whose attributes are set via java bean style set*() methods will just work, no annotations required. If you really need constructor arguments, the @UiConstructor annotation will make it work.

rjrjr

Joel Webber

unread,
Aug 4, 2009, 3:47:24 PM8/4/09
to Google-Web-Tool...@googlegroups.com
There are three cases where custom parsers come up:
1. Widgets without a default constructor.
2. Non-widget UIObjects that need an XML representation.
3. Panels that need more than the default add() method to deal properly with child widgets.

The former is usually pretty easy to work around, and it seldom comes up much in practice (I think it came up for MenuBar, because it wants its 'direction' as an invariant -- that wasn't even a good design anyway).

The second case doesn't come up all that often, but it's important for menus and trees.

The third case is the most problematic. Take DockPanel, for example: It's really not going to be able to do anything useful if you just call add() on it, because it doesn't know where to put the child. These sorts of panels need extra attributes or elements to specify where to put children.

Amir Kashani

unread,
Aug 4, 2009, 4:36:03 PM8/4/09
to Google-Web-Tool...@googlegroups.com
As Ray mentioned, one has a pretty simple workaround and two is pretty uncommon. I'm a little more concerned about the third case. A few examples of issue with internally used widgets I've created:

- A StackPanel replacement that adds animation support. The only workaround I can think of is having the add() method take a StackPanelItem or similar that contains the header text or widget.
- TitledPanel, which supports a header, content and footer area. In this case, the widget could expect several calls to add, and determine the context based on number of previous calls. This would get a bit hairy if headers and footers were optional, though.

These scenarios are a bit inconvenient without a custom parser, but far from a deal breaker. The concern is that people develop a set of hackish workarounds that aren't easily fixed when custom parsers are supported.

- Amir

Ray Ryan

unread,
Aug 4, 2009, 4:49:49 PM8/4/09
to Google-Web-Tool...@googlegroups.com
I share your concern, Amir, but I'm even more afraid of a) providing an ill considered API for custom parsers and b) delaying 2.0. I'm pretty confident we can limp along without them for a dot release.

John Tamplin

unread,
Aug 4, 2009, 5:01:50 PM8/4/09
to Google-Web-Tool...@googlegroups.com
On Tue, Aug 4, 2009 at 4:49 PM, Ray Ryan <rj...@google.com> wrote:
I share your concern, Amir, but I'm even more afraid of a) providing an ill considered API for custom parsers and b) delaying 2.0. I'm pretty confident we can limp along without them for a dot release.

You could move it into an impl package which makes it even more clear that it isn't a public API.

--
John A. Tamplin
Software Engineer (GWT), Google

rj...@google.com

unread,
Aug 4, 2009, 5:37:46 PM8/4/09
to j...@google.com, google-web-tool...@googlegroups.com

http://gwt-code-reviews.appspot.com/51831/diff/1/2
File eclipse/user/.classpath (right):

http://gwt-code-reviews.appspot.com/51831/diff/1/2#newcode19
Line 19: <classpathentry kind="var"
path="GWT_TOOLS/lib/easymock/easymockclassextension.jar"
sourcepath="/GWT_TOOLS/lib/easymock/easymockclassextension-src.zip"/>

On 2009/08/04 19:32:59, jgw wrote:
> I'll assume that all these libraries are necessary, and that you've
checked up
> on the licenses and made sure they're in the /tools repo.

Yes, and done. Hope the gratuitous sort was okay, this joint was a mess.

http://gwt-code-reviews.appspot.com/51831/diff/1/6
File user/src/com/google/gwt/uibinder/client/UiBinder.java (right):

http://gwt-code-reviews.appspot.com/51831/diff/1/6#newcode36
Line 36:


On 2009/08/04 19:32:59, jgw wrote:
> There was talk at one point of re-unifying these methods. If that's
still in the
> cards, should we make a note to that effect as a warning?

Oops! Right, thanks. Deprecating them for this patch, will follow up.

http://gwt-code-reviews.appspot.com/51831

amitm...@google.com

unread,
Aug 4, 2009, 5:43:58 PM8/4/09
to rj...@google.com, j...@google.com, google-web-tool...@googlegroups.com
LGTM for changes to tools/api-checker/config/gwt16_20userApi.conf


http://gwt-code-reviews.appspot.com/51831/diff/1017/1019
File tools/api-checker/config/gwt16_20userApi.conf (right):

http://gwt-code-reviews.appspot.com/51831/diff/1017/1019#newcode82
Line 82: :com.google.gwt.uibinder.parsers\
Changes to this file looks good to me.

http://gwt-code-reviews.appspot.com/51831

amitm...@google.com

unread,
Aug 4, 2009, 6:13:48 PM8/4/09
to rj...@google.com, j...@google.com, google-web-tool...@googlegroups.com

http://gwt-code-reviews.appspot.com/51831/diff/1017/1019
File tools/api-checker/config/gwt16_20userApi.conf (right):

http://gwt-code-reviews.appspot.com/51831/diff/1017/1019#newcode68
Line 68:
:user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java\
add
:user/src/com/google/gwt/uibinder/parsers\

On 2009/08/04 21:43:58, amitmanjhi wrote:
> Changes to this file looks good to me.

My bad. I did not look at enough context. Remove these two lines from
here and make the change above.

http://gwt-code-reviews.appspot.com/51831

brett.wooldridge

unread,
Aug 5, 2009, 4:31:19 AM8/5/09
to Google Web Toolkit Contributors
Just a question, and a comment. First the comment. Thank you for
getting this up into the repo, in whatever state. Second, it was
commented that Adwords and a few other projects have vetted this over
the past year. How does this jibe with the deficiencies outlined?
For example, not being able to markup for DockPanel, etc? Did those
projects just have to go "off-roading" and create custom parsers based
on an API they knew they would eventually have to fix/rewrite?

-Brett

Ray Ryan

unread,
Aug 5, 2009, 9:32:44 AM8/5/09
to Google-Web-Tool...@googlegroups.com
The GWT standard widgets already have custom parsers built for them. DockPanel, DisclosurePanel, Menubar, etc. all work just fine despite their wonky api needs. The bug here is that you can't indulge in similar glue for your custom widgets yet. No Google team has found that to be a problem with their custom widgets, which is I why I felt like I could get away with ducking that issue a bit longer.

Andrés Testi

unread,
Aug 6, 2009, 10:39:52 AM8/6/09
to Google Web Toolkit Contributors
UiBinder is awesome!

An extra degree of decoupling, could be done by adding the next stuff
to the UiBinder interface:

public interface UiBinder<U, O> {

U createAndBindUi(O owner);

public static interface Pair<U, O>{
R getRoot();
O getOwner();
}

Pair<U, O> createAndBindUi();

}

where createAndBind() without parameters could instantiate an owner
class, enabling injection by constructor for UiField for more robust
code.

- Andrés



On 5 ago, 10:32, Ray Ryan <rj...@google.com> wrote:
> The GWT standard widgets already have custom parsers built for them.
> DockPanel, DisclosurePanel, Menubar, etc. all work just fine despite their
> wonky api needs. The bug here is that you can't indulge in similar glue for
> your custom widgets yet. No Google team has found that to be a problem with
> their custom widgets, which is I why I felt like I could get away with
> ducking that issue a bit longer.
>
> On Wed, Aug 5, 2009 at 1:31 AM, brett.wooldridge <brett.wooldri...@gmail.com

Ray Ryan

unread,
Aug 6, 2009, 11:32:25 AM8/6/09
to Google-Web-Tool...@googlegroups.com
Submitted at r5896

Venkatesh Babu

unread,
Aug 12, 2009, 5:27:28 PM8/12/09
to Google Web Toolkit Contributors
Hi All,

Pardon me for my ignorance, but just wanted to know - Is the UiBinder
source code available for public review/use? If so, where can I get
the svn location or the URL to download the source code? Would really
appreciate if somebody throws light on this.

Thank you,
Venkatesh



On Aug 6, 11:32 am, Ray Ryan <rj...@google.com> wrote:
> Submitted at r5896
>

Amir Kashani

unread,
Aug 12, 2009, 5:31:54 PM8/12/09
to Google-Web-Tool...@googlegroups.com
Hi Venkatesh,

The code is only available as part of GWT trunk; it's not a separately downloadable library. To get going with the trunk, take a look at:

http://code.google.com/webtoolkit/makinggwtbetter.html#workingoncode

- Amir

puttyshell

unread,
Aug 21, 2009, 10:13:24 PM8/21/09
to Google Web Toolkit Contributors
Ray,

You mentioned that DisclosurePanel is supported by Uibinder. Do you
know how to config the *.ui.xml?

UiBinder greatly bridges the gap between traditional html design and
the java coding. I am already very happy just using HTMLPanel + normal
html + ui:field + styleName. :)

~Xijiang

Amir Kashani

unread,
Aug 23, 2009, 2:57:58 PM8/23/09
to google-web-tool...@googlegroups.com
Xijiang,

Take a look at com.google.gwt.uibinder.sample.client.WidgetBasedUi & WidgetBasedUi.ui.xml (part of gwt-user.jar). That test template uses DisclosurePanel along with the other supported custom panel types.

- Amir

Xijiang Miao

unread,
Aug 29, 2009, 11:44:10 PM8/29/09
to google-web-tool...@googlegroups.com
Yes. That's what I did. Thanks!

I have to enable the animation to use two nested DisclosurePanel. Otherwise, the parent disclosure panel does not resize properly when the child panel is opening/closing.  
Reply all
Reply to author
Forward
0 new messages