Practice English Speaking&Listening with: Google I/O 2010 - GWT's UI overhaul

Difficulty: 0

>> WEBBER: Morning everybody. I'm sorry this is so early. We're all kind of in pain from

that, I think, after last night's party. My name is Joel Webber, this is Ray Ryan, both

from the GWT team. And we're going to talk a little bit about what we are now referring

to as our UI overhaul. Don't forget there's the live wave, good place to ask questions.

We'll try to pick questions up at the end from there as well as from the microphones.

And you can also heckle us virtually from there and we'll find out about it later.

>> RYAN: I hope you know how to run that thing. >> WEBBER: Yeah, I think I do.

>> RYAN: All right. >> WEBBER: I hope. So what do we mean by this

UI overhaul? This is not really a formal process. This is really just a set of things we've

been doing recently and been in 2.0 and things that we are doing as of 2.1 which we're working

on presently that constitute a lot of major changes in a way UIs are built in GWT. It's

not a replacement for what's there for the most part but a lot of additions and optimizations

and new bits and pieces. Really four things, you get UiBinder, if you're working in--the

first three, if you're working in 2.0 right now, you're probably at least passingly familiar

with these things; UiBinder, a way to move a lot of your code into XML which sometimes

can generate quite a savings in complexity; ClientBundle, the way to process CSS, one

of the biggest paying points I found in GWT Apps; LayoutPanels, where they cut the collection

of panels that make--that will hopefully make most of your layout problems much, much simpler

to solve. And for these first three, you can see an update to the mail sample as a 2.0,

uses all of these features. It's a really good starting point. They take nothing else

away. Go look at the way that's built and that tells you a lot of things about--a lot

about the things that we changed in 2.0. And then finally, these things we're referring

to is either data presentation Widgets or Cell Widgets depending on the phase of the

moon that we are adding in 2.1, which will solve the problem, I think once and for all,

of building large collections efficiently. So large tables, large trees, large lists,

things like that. And I'm going to let Ray take it and talk about the UiBinder and ClientBundle.

Those are what his babies. >> RYAN: Hi. I'm still Ray and...

>> Louder. >> RYAN: Hi.

>> WEBBER:Whoa. >> RYAN: Okay.

>> WEBBER: I think that turned up at both ends.

>> RYAN: Okay. So you can hear me now? Excellent. I'm Ray and I'm going to talk to you about

UiBinder and its best friend ClientBundle. Like Joel said, these are features that are

in GWT 2.0 now, had been for a few months, you can use them today. So UiBinder is a way

for you to write your HTML User Interfaces in HTML, which is a pretty natural way to

go. It gives you a lot of help in getting rid of the kind of Boilerplate that you face

when you're dealing with writing [INDISTINCT] or interfaces in Java, anonymous event classes,

and that kind of thing. You were into them a lot less often. And it also encourages you

to write your Apps in a style that's kind of inadvertently lead you to write them in

a more efficient and more performant manner. You'll use fewer widgets except where they're

appropriate. You'll wind up with an app with a smaller footprint. That is not an accident

to coin a phrase. We're trying to guide you into the pit of success where the easy and

pleasant way to work is also the correct way to work. So, here's how you write UI in Java.

You're not really expected to be able to read this. And even if you could read it, I doubt

you'd have a very clear idea of what was going to be in front of your users after this code

and all run. We're kind of making some panels, and some images, and I think there's some

text in there and we're going to stick it up. And it's just a nuisance to write and

nuisance to maintain. As of GWT 2.0, you can write it in a style that you, more or less,

would have written it, had you been working in a browser in a conventional system. We're

inside of a bunch of HTML. We got some divs. Looks like there's going to be a welcome message

and a signOutLink and an aboutLink and some serious set styling going on but, as a Web

developer, you probably understand what's in front of you here. So let's actually make

this thing do something. First, you want to look at the two anchor lines in bold there.

Those are a couple of GWT widgets that basically correspond to your old friend "a href=" da,

da, da, da, da, da. And you see the attribute on them called UiField. That is telling you

the name that--and I turn my head, I talk louder, neat. That's the name that your Java

code will use to get access to these fields to actually make them do something interesting.

So we'll jump over to the Java code that actually maintains this. Up at the top, you'll see

we have our UiField annotation declaring that the signOutLink and the aboutLink need to

get pressed to us from that XML file that we talked about. And our constructor, we're

sub-classing GWT composite here which if you're a good developer, you're probably familiar

with. And the only line of code we write to actually create this interface is a call to

the create and bind method on our binder and we pass it in to our net method and it--widget

method. And for event handling, we're just doing some more annotation. We're saying that's

the signOutLink. When it generates a click event, it should call this method. The aboutLink,

when it generates a click event, it should call this method. No anonymous classes, none

of that nonsense, just make your UI, make your code, and get on to the actual interesting

part. Now, one of the other--man... >> Hello.

>> RYAN: Hello. One of the other best features that shipped with GWT 2.0 was the ClientBundle.

You may have heard Webber talked about this at previous I/O conventions first as the FooBundle

then as the ImmutableResourceBundle, which is my personal favorite version of its name.

We finally settled on ClientBundle and we actually shipped the thing. ClientBundle is

a way to take all of the other stuff that makes up your App. The styling, the commands

in CSS, image resources, any text, any other arbitrary resource types that you want to

customize the thing to run and bake that right into your JavaScript. So, A, you have a lot

less work to do to figure out how you're actually going to stage this somewhere to pull it in

with later requests from you App; B, your users benefit hugely because they have a single

download that brings in everything at once rather than multiple network request going

over to fetch this little image and that little image and the other little image. We use every

trick that we can find; spriting to tie all images together into a single download; data

resources to bake things in, in a single download where possible. We know what browser you're

compiling to so we'll use the tricks that work for that browser, but not for this browser,

and so on. Oh, and one key thing to point out is that we don't just take CSS. We make

the CSS work a lot more like an engineering tool. There's no global name issues. If I

have a style class called main in widget A and my friend over here have made a class

called main in widget B, we don't stomp on each other and we didn't have to agree on

a convention of having a 24 character long, this, that, that about the other style name.

We have conditionals and we have namely constants and stuff like that. I'm not go into that

fun to see a success resource because it's been discussed here before. But look in the

docks. It's fun. The way it shows up in UiBinder is with an XML element called UiStyle where

I'll declare familiar looking CSS like the main div and this guy should have a background

color or text color of red. And I'll apply it in my usual styles at the class attribute.

The only bit of magic here are the squarely braces inside the class attribute to indicate--this

isn't a string that I'm putting here, this is an actual reference to another part of

the template. In this case, it--there's a reference to the style block and the main

class that was declared inside of there. And you're not typically going to actually put

all of your CSS inline in your template like that. It's nice for sketching, but you won't

normally work that way. And that's fine. You can punch it out into a CSS file on the side,

several CSS files on the side; maybe share some of those CSS files; that kind of a thing.

It's not just for play. And of course, when you're working on interfaces, you don't just

do styling. You like to use pictures as well and we've got you covered there. What I'm

doing here is I'm indicating to the template that there's an image around here somewhere

that I want to work with. I'm going to put it in a field, remember our friend UiField

named background image. I'm going to assume that the image file matches the field name,

and so I don't have to make a separate attribute for background image.png or whatever. We'll

just look around. We'll assume that you've made things sensible, although if you need

to get more explicit, you can. And finally in this case, I'm going to mention that when

this image is used that it's in a context where repeating is necessary. I want to re-tile

itself in a horizontal and in a vertical, both axes. I can now go back down to my CSS

in the style block there and use a bit of the CSS magic we've added. The "@sprite" marker

there indicates that this particular CSS class is to indicate spriting. It's going to use

this GWT image specified up above as background image. And now finally, when I go down to

my Hello world spam, if I apply that background style that I've declared here, I'll have my

nice tasteful image background which, in my case, tends to be a picture of my son at age

two, but I'm not sure that would be today. Finally, the trick that UiBinder knows is

it ties it nicely to a GWT's internalization system. Yet that's not new, our ability to

have localized messages and constants and so on. What is new is this ability to kind

of work with it directly in your code. All I've changed here is I've added this UI message

element around the existing Hello world message. And what I've done is I've signaled the GWT

system that this is a localizable strength. When the code is compiled, we're going to

generate on the side for you a properties file that has all of these messages baked

into it in the usual key equals Hello world style, a file that you can hand to your translators

so that they can in turn provide alternative languages and you can--and away you can go.

But an interest to full disclosure, I should mention that the early users of GWT 2.0--oh,

I'm sorry. This is a slide I just added. We can do more than just simple little strings.

I wanted to point out here that we can have bits of things that aren't message tucked

into the middle of the message because of the wrapping, this can be hard to read but

what's going on here is we have a message we're going to show our users that says, "To

do the thing, click here," and that's going to be a link that fires off a widget of some

kind and massage vigorously. On the bottom here, you can see what gets generated and

put in front of your translators. They get two little placeholders there, the 0 and the

1 to let them know that there's a bit of opacity here that they can't mess with when they translate

it. The tokens have to still show up here. And they can--but they can translate the message

with all of the context and not breaking it up into three separate substrings and hoping

that somehow things get pieced together for them. I've got the entire message placed there.

There's actually other attribute to comply on UI message to give them more of a notion

of what's going on, to provide a description for it, and so on. The docks go into some

detail. Now, for the full disclosure part, once you've actually compiled the system finding

the bits and putting them all together and getting it in front of your users work well

enough for Google's use. We didn't quite get the level of [INDISTINCT] that we should have

to get--make it easier for you to use with your system. I was so embarrassed by this

while writing these slides that I finally updated our public documentation to make it

really clear how to do that pulling in a lot of input from a particular bug report that

I saw on my sleep. So it's all been working for a while and now you actually have a hope

of making it work yourself. And that's all I had to say about UiBinder and ClientBundle.

I'm going to handoff to Joel now who wrote all the other interesting stuff and let him

talk about it. >> WEBBER: So layout, if you've been using

GWT for awhile, you probably noticed that layout is charitably a nightmare. That's true

of a lot of HTML in each UIs. And we really have two different approaches in the old way

of doing things which we'll now be the old way of doing things. You can either try and

use tables, put everything where you want it to go, which I think there's been a large

complaint about the [INDISTINCT] core widgets making at things like dock panel, horizontal

panel, et cetera, et cetera. Worked well for awhile but it doesn't work so well when it

get into standards mode. And people hate it because it makes CSS more of a pain and so

forth. There's an alternative which is to try and lay everything out manually. One pixel

at a time, top to bottom, all encode. And there are a number of frameworks to take that

approach and it works, except that it's kind of slow. And for a lot of the apps that we're

working on, it's just not sufficient. You end up with apps that are really, really slow

to resize, you know, you have to resizing draggable panels within the app, they're really

slow, and so forth and so on. We don't want apps to be out of the box sluggish. And if

you want to just [INDISTINCT] and make your apps sluggish, that's fine. But we don't want

to force you to do that. So we came up with an alternative that actually turns out there's

a nice little constraint system hiding inside CSS that people don't really use all that

often, probably a number of reasons for that. It doesn't work out of the box on some older

versions of some browsers. But it turns out by using left, top, right, bottom, width,

and height, those six properties on top of position absolute in which--please don't react

when I say position absolute with these actual constraints that works out fairly well, not

as bad as it sounds. You actually get something much more like the "springs & struts" model

that you have and something like Cocoa or the old next UIs. Those worked very well in

practice. So what we built is a series of widgets, a series of panels, containers that

use this--they all use the same structure. There's a core layout system they all share.

And the purpose of these things is to support application level layout. In other words,

there are some things that HTML and CSS layout models do very well. We should continue using

HTML and CSS layout for those things. But for the core screen application structure,

topper over here, footer over here, scrollable panel over here, splitter over there, the

top level of constructs in your app, these are very, very effective and much more--both

easier to use, more predictable, and more efficient than what you get out of source

standard CSS layout techniques. So all of them in standards mode, in fact, they require

standards mode but that shouldn't be a problem for most people since [INDISTINCT] mode is

mostly a nightmare. And they support animations right out of the box. There's actually a good

reason for doing that because it allows us to build certain things that would otherwise

be very difficult just with the simple constraint system of animation sort of layered on top.

I'll show a few examples of that in a few minutes. It also allows us to do things that

are more efficient out of the box than you might do by hand unless you're willing to

go dig very deeply into some [INDISTINCT] that's required. And they do actually support

browsers all the way back to IE6 with some Herculean hackering, but hacker that you don't

need to know about, unless you're really, really masochistic to want to read the code.

What are these things not? I mentioned this before. If it works well on HTML right now,

don't use layout panels. That's not the right place to use them. So forms, document style,

layouts, most of your widgets will not actually be used in the structure, just the core screen

layout. And it's also a simpler layout when you're maybe used to it, if you're familiar

with swing or SWT or these other sort of top-down and bottom-up merged layout models where there's

a negotiation between the outside and the inside. This is much simpler. Again, if you're

familiar with Cocoa and Interface builders, it's much closer to what you get up there.

So let me just show you. It's a lot easier for me to show you than to talk about it.

Okay, this is the GWT 2.0 mail sample. You may have noticed this, you may not have noticed

there is much to notice about it, but it was different in any significant way. But there

are some subtle and important differences. So the first, we see that. And this window's

a little bit large. Sorry about that. We will see that it is fast to resize. Now, not only

is this fast to resize, it's fast to resize on browsers like Firefox that defer layout.

So, if you notice on window resize events on Firefox are deferred. I think Opera does

the same thing. It's still smooth. So you won't have this weird horrible structure that

happens on some apps, even some Google Apps that you resize the window and the whole thing

lags and the UI feels sluggish and weird and flaky. It's very, very solid. It's very, very

fast in that respect. I mentioned animation earlier. So these kinds of transitions are

really, really easy to get out of the box and they're fast and they're smooth. You never

have to worry about how well I nested the dock panel inside the split panel inside a

stack panel and it jumped upside down and flipped over and crashed. None of that sort

thing happens. This is all straight--it's very straightforward. It's a coherent model

and it definitely works out of the box everywhere. And there's no code here to speak of. You

set up the structure, even the window resize event has handle it automatically and internally.

So you don't have to think about things like, "Okay, I'm going to write some code here to

figure out when the resize is and I've got a header up here so I need to measure that

and subtract 37 pixels, blah, blah, blah, blah, et cetera." And that's it, I mean, that's

the idea. These are things that should be simple and traditionally UI [INDISTINCT],

they're very straightforward. And GWT and/or the Web, they have always been kind of a nightmare,

no longer. I hope. It seems to be working well so far. So what was actually going on

in that? This is the--this is a rough fact simile of some of the mail.

>> RYAN: Actually, this is the exact copy-paste of the "mail.ui.xml" file.

>> WEBBER: Okay. This is not a rough fact simile. This is actually the "mail.ui.xml"

file. So what are we looking at here? We got a DockLayoutPanel. That's something that put

some things at north, west, you know, just like the dock panel if you use that before

in the past. I put a splitter inside the center region and that splitter contains shortcuts

on the left-hand side. That's the stack panels and all that stuff, MailList, MailDetails,

so forth and so on. So it's straightforward to use this way. If you set things--if you

set them up using these structures, it will more or less, just do exactly what you want

it to, which is sort of the goal we've always have. Okay, what does it not give you? It's

not going to give you, you know, all unicorns and rainbows. There are some constraints.

It's not sensitive to preferred size. This is probably the biggest complaint, but it's

also the most intractable. And this is much like, you see--you'll see in a lot of interface

builder Apps. You kind of have to give these things the space they need. You can't say,

for example, make this top section as tall as the HTML inside at once to push out, it's

top-down only. And that's actually another good reason to say this is really only meant

for application core screen super structure. You can--it require explicit sizes on a lot

of places, like you may have noticed on this case here, DockLayoutPanel--the outer DockLayoutPanel

specifies that it's in EM units. Those are font-relative of units. And the north is five

EMs tall. Good thing about being able to use things like EMs and percentages is that you

can make the layout fairly fluid. EMs make you font size-relative which is really convenient

and percentages make you container size-relative. So you can get a lot of things done that way

even without a preferred size negotiation. You do get resize events. This is another

point of contention of the browser the way it's typically done.


>> WEBBER: do get resize resize events. This is another point of contention in the

browser the way it's typically done. With the exception of Internet Explorer, nobody

provides an on resize event. It's really unfortunate because if you've ever had to do something

like, you have a list of icons and you want to make it--you only want to render enough

for the space that you have available in some panel, there's no way to find out when the

thing gets resized in the general case. We provide a limited series of resize events

that percolate through the layout panel structure. This seems to work out pretty well for most

reasonably use-cases, but there are some things who are--that are a little tricky to do. And

as I said before, it's not appropriate [INDISTINCT] during layout. You probably don't want to

use this to layout your forms. At least not at the leaves--not near the leaves, you know,

typical form, HTML form layout structure seemed to work pretty well for that kind of thing.

>> RYAN: So one more point to make here before we enter cellar cells. Although we require

some explicit sizes, you want to ay attention to the fact that in the--the main body here,

the center elements, there's no constraint provided there. We're requiring you to nail

down the margins. The body is going to take up what's available after that. And so, the

part that needs to be flexible is very flexible. >> WEBBER: Thanks Ray. I have a bit of underselling

myself sometimes. Okay, but what you get out of it? So you have some constraints you have

to conform to, but it's extremely fast, as I mentioned, because we're not running any

code, all right? One of my favorite quote is "The fastest code is the code you never

run," and we don't run any code in the default case. May well--okay, almost no code, some

small epsilon there. It handles a resize event to check a few things, but that's it. Everything

else leans in the browser's native code which is already running very quickly. Again, you

don't have to write a window resize listener and it's actually not leaning on the resize

listener to do most of the work. So that keeps it fast and saves you a lot of trouble. If

you use "em", "ex" font sizes--sorry--unit sizes, then you can react to font size changes

automatically. So, you don't have to worry about, "Well, I made this thing 37 pixels,

so very wide and it looks great, until my user decides to magnify the screen." That

sort of thing is handled automatically. Again, animation support is built-in because it allows

you to do things like touch that panel where it's not--it's normally animating from, you

know--from here to there, specified in absolute positions. It's actually animating among constraints.

So, this thing was constraining to be top height. I animated it and now it's constrained

to a different set of constraints that are bottom height, for example. If you play with

it, that will make sense. And again, they're predictable. They do exactly what you want

them to do. They go exactly where you tell them to. They don't bounce around on you.

And another point, it's not a bullet point in the slide, but another point about performance

is that because of the way they're constructed, they also make a number of other things faster.

They tend to constrain layout, and when I say layout. And when I say layout, I mean,

if you Kelly Norton's talk yesterday about layout performance--a number of things, layout

performance is among them. You know that browser layout--the reflow engine can be extremely

expensive. These things tend to compartmentalize your layout. So, a lot of things--a lot of

little things just get faster because they don't affect each other. Something that when

your header over here, changing doesn't cause the browser to reflow this part over here

that's completely unrelated. That a little--a subtle but really helpful benefit. So, you

got everything on the screen. You got it

actually where you want it to go for once, and without any major hackery. Probably one

of the biggest complaints we've had after layout is, "Okay, I got my app looking great.

I just put, you know, 100 table rows and five columns or 10 columns, 20 columns wide. And

it's excruciatingly slow. How do I fix this?" And we often said, "Well, you probably shouldn't

be using that many widgets. You got a widget in every single table cell here, that's really

expensive." And you say, reasonably, "Well, what should I do about that?" And we say,

"Uhh..." we scratch our heads and we come up with some strange hacks that involve HTML

and catching events at a high level and trying to pump them down and you find yourself in

a world possibly worst than the one you were hoping to escape in JavaScript. So we want

to fix that. We've wanted to fix this for a long time. And as of 2.1 when this is released

and obviously you can play with it right now. We feel like we have a pretty good solution.

We have the underpinnings of a really good solution to a lot of these problems. So, again,

we've been giving this advice often, don't use so many widgets. Why is that? Widgets

are necessarily more expensive than individual DOM elements because they simply have a little

extra book keeping. This is necessary for dealing with events properly, it's necessary

for cleaning up after potential memory leaks on some browsers and so forth and so on. That

if you don't--in a place where you don't use a widget, it will necessarily be faster because

there's no code running. What we're aiming to do is to let you get the benefits in this

and the performance of doing everything with giant fact inner HTML calls without the excruciating

details of trying to hook up events and keep track of all the elements that you've created.

And if you've looked at--if you've use the tables in the [INDISTINCT] that shipped in,

well, 1.0 ages ago, you'd noticed--probably somewhere around there, 1.1 maybe. We added

the ability to add widgets to everything because it was necessary for certain cases. But that

actually was a little bit under constrained. So, if you ever have tried to put a tab panel

inside a tree item, probably not. Or if you had, it was on a LARK. Definitely it wasn't

a good idea if you did. And it, even if it behaved properly, it was probably very, very

slow. What we need is something more constrained than that. Again, that's at lists, tables,

and trees. These are the kinds of things, what we need large numbers of the same thing

over and over again are very simple things, but you need them to be interactive. And--but

that interactivity tends to be limited, buttons, check boxes, text inputs, date pickers, you

know, just sort of standard editable table stuff has been a nightmare before. Then these,

you know, these one comes a surprise to anyone, but these are the kinds of things we're talking

about. We've got a--never mind that the word table and trees got reversed today. I'm going

to--I'm going to blame presently on that. >> RYAN: That was my fault. Surprise.

>> WEBBER: I'm going to blame Ray. I like blaming him presently though because he can't

defend itself. So, of the top we have a tree, that's straight out of the average Geo picker.

That is a very, very large tree because it includes every region in the world, every

region, city, et cetera, et cetera. But they needed a check box in each one because that's

the point. The point is selecting parts of a large tree. This is a really common case.

That actually is built out of widgets in the current day they may have optimized it by

hand. That should be really easy to do. Tree down there--table down there, I can't read,

thank you Ray. >> RYAN: They both start with T. I don't see

what you're so worked up about. >> WEBBER: So--oh, thanks for fixing that

demo too. I had not made point it out that thing was interactive. So, there we have a

table out of the AdWords UI, if you have ever used that, the campaign management UI. These

include a couple of really subtlety interactive thing and it's actually more interactive than

you can see here because it has a lot of hover effects and so forth. Again, the original

implementation used a lot of widgets and it was very, very slow. They fixed that by optimizing

by hand, we're taking a lot of the lessons they've learned and brought it into this framework.

And then the list here, this is really a good example of a thing. This is really a list

of simple things, but they're, I mean they're fairly complex. They're not super interactive.

But you need to be able render large numbers on them that comes out of way obviously. So,

let me show you an example of we've done. You may have seen this in the keynote. I promise

I'm not on wireless this time. So that should be a less of a problem. Okay, so this is not

a super exciting app unless you happen to be an accountant perhaps. I doubt many of

you are accountants. What's exciting about it is, to me anyway, being the performance

freak that I am, is that there are almost no widgets in this app, but it was really

easy to construct.


>> WEBBER: ...but it was really easy to construct. Sorry?

>> RYAN: I don't say a word. >> WEBBER: Okay. I'm hearing things now, wonderful.

Probably, I think on the order on 25 widgets. The last time I check, it's 25, 26 something

like that. And they're for things like, you know, the search box here, the super structure.

Again, this is using the same layout panels I showed earlier. But when it comes down to

individual pieces here, even when they're interactive in fairly complex ways, they are

just cells, which is a term I'll introduce to you in a moment. Table is the same way.

This, by the way, were some of the animation stuff we built-in in the layout panels. This

is--This was--I think this is five or six lines of codes. But here, we have--so we got

a table. Oops, if I can click the right thing with an interactive element, that also is

a cell. Those are efficient. They're very, very fast to render. Importantly, I forgot.

I should remember the number here but last time, one of my partners in crime measures

the speed... >> RYAN: [INDISTINCT] bazillion, I think,

was the term that we were using. >> WEBBER: Oh I was actually going to refer--I'll

be looking for smaller number. I was going to say, how long does it take to actually

render this table. And I think it's on the order of a few milliseconds. That's all backend

time right there. And what that allows you to do is crazy things like [INDISTINCT] the

other day morning where I can do a type of head search. You know, that is a really simple

implementation on top of what's already there. And that's even fast on old crafty slow browsers

because it's leaning on an HTML to get its work on. So the point is that of all this

is that you can do something that's easy to do. You can create your--create these widgets.

They're very straightforward. So I use these widgets to create individual cells to render

the contents. It's easy to do, but it ends up being really fast because the interface

is designed in such a way that you--that give us enough leverage to be able to leverage

innerHTML and so forth to get fast rendering, but still keep them interactive. We have very

simple idea of how this works. This is the simplest example I could think of. I got a

cell list of simple stackedview, got a simple text cell, the simplest thing you can impossibly

imagine rendering. So just give me a string, put it in the cell. And that parameterizes

the cell list that has--that gives the cell list a way of rendering itself. And I add

the view to an adaptor. The adaptor is really just a convenience class that pushes data

into it. When you sit down to use it, I think you'll find that it's really quite straightforward.

And in that adaptor, this actually behaves sort of like a glazed list if you ever use

that sort of library where anything I do in that Java util list is just reflected automatically

in the UI. And the cell list itself will go to great links to make sure that that gets

optimized. So if I change a few things, it will try to render the subset that get changed.

If I change a whole bunch of things at once, it'll try to render them all together very

quickly. It's, you know, again, designed to make sure that that is easy for us to do.

We have the right APIs so we have that kind of leverage. No pop quiz on this. I just wanted

to give a quick overview of the kinds of thing we're talking about. This is not a really

complex framework. It's really a small set of components that are very easy to use together

but don't require you to buy and do any complicated MVP architecture or anything like that, but

are design to work well with anyone. So basically, you have views, essentially mostly listviews,

tables or special case of list, entries, or nested list, so a list that contain list.

So it's really a small set of concepts there. You have an adaptor here where, again, which

is not a special thing. It's just a convenience class providing list on the client to the

table or to the view. I have a cell for rendering the contents and for dealing with events.

So cells can handle events but in very limited ways that allow you to build most of what

you want to build but don't require any heavyweight architecture, heavyweight bookkeeping work.

And then your app code, controller, or whatever you want to call it gets notification of updates.

So the way that cells are made editable is that cells provide updates to their content,

so each cell is bound to a type. So that allows--that type could be a string or that type could

be a built-in, an enum, or a complex DTO. It could be anything you want it to be. Again,

it's much easier to just dig into the code and just trying to read that diagram, but

I just wanted to give a rough overview. So I think I've already talked to everything

on the slide, almost. Oh, async data source is actually--that's actually another core

really, really in core part of the structure. It is designed from the ground up to deal

with asynchronous fetches--a synchronous slow fetches because we are talking about the distributed

network that is the Web. It is invariably slower than you want it to be when you're

over the Internet. And it can handle push data. So as long as you can find a way to

push data down to the client, maybe you're running an HTML5 App and you're just using

Web sockets or something really clever like that, or you're just pulling in the background.

The views don't have to know about this. You can always push new data into them and that

allows us to do all kinds of crazy things like--well, you saw the automatic update and

the keynote demo yesterday. You know, that sort of thing is very easy to do and there's

no hackery to make that work. And when we started this, we really found that there weren'tmany

frameworks that were designed around the asynchrony that is common in the Web. Most of them tended

to be--tended to assume that the models backing up or get the list or reflection were synchronously

available which requires you to do all sort of extra levels of caching and things like

that. So we really set up to make that simple from a get-go. If it's slow and it's async,

I can still--the UI is very, very simple to build. And we also wanted to keep simple stuff

simple. All right. If I've got a list on the client, then I should just be able to shove

it into a view without any extra work and shouldn't be--shouldn't require me to instantiate

three or four adaptor classes and a few other complicated thing. It should be very, very

simple. I want to talk a little bit about the cell itself. Cell is actually a very,

very simple concept. It's a flyweight--roughly a flyweight pattern. They tend to be stateless,

except in some rare cases. And this is the simplest cell you could possibly write. So

basically, the purpose of a cell is to take some value, turn it into HTML via string builder

and then get out of the way. It does very little alts. I think what's not shown here

is the event handling structure which is still in a little bit of flux but it basically allows

cells to handle events but in a stateless way so that they could communicate edits to

the outside world. But again, we've just driven really to keep that very simple and we'll

provide a lot of cells out of the box so that most common cases will be dealt with easily.

And--wow, did we really just make it all the way to the end?

>> RYAN: We did. >> WEBBER: Every practice, we ran 15 minutes

over. I can't really--we have lots of time for questions...

>> RYAN: He's not even talking fast. I don't know what we did.

>> WEBBER: So, four things, ClientBundle, let you actually process all the things that

weren't processing before, images, CSS really makes your life simpler in a lot of cases.

UiBinder, get rid of Boilerplate, [INDISTINCT] and HTML which makes your life easier hopefully.

And again, as Ray said before, just drive it as the pit of success, make the easy thing

the fast thing so that the App you want to write is the one you want to end up with.

And layout, make layout work, make it fast, make it easy, make it predictable so you can

stop worrying about it and just move on and write you App. And again, these Cell Widgets,

make it fast and efficient and simple and easy to render large collections, again, so

you can stop worrying about--hopefully, you stop worrying about UI performance

problems and worry about your actual app. And I'm still stunned we have this much time.

It's great. So, again, there is the live wave. There is, hopefully, there are some questions

on it which we'll switch to in a moment. And this link may even work if we're lucky, the

thing on where Ray assigned you. >> RYAN: Oop, I'm sorry. I forgot about that

bit of magic. Yeah. Please standby. >> WEBBER: Cool. You're about to login at

your own account. >> RYAN: Oh, so I am.

>> WEBBER: So, why don't we start with audience questions while we figure that out? [INDISTINCT].

>> Hello. >> WEBBER: Does it work?

>> Mic does work. >> WEBBER: I think so.

>> Hi. I was hoping if you guys could quickly explain how I could create my own widgets

in the UiBinder. I mean, I understand that there's a parser that you will have to overwrite

if it is--if it's not so. >> RYAN: Ninety percent of widgets work right

out of the box. If your widget works in a bean style--you can mess with that, I'll answer

this while I answer this. >> WEBBER: All right.

>> RYAN: If you write your widget in a bean style, zero args constructor, setters and

getters then it'll just go. Every attribute that you set in the XML element will result

in a set call. We've recognized a lot of the primitive types out of the box. So if you

put--if I have set height takes an int argument, I'm going to make sure that the user provides

you with an actual int literal and we'll throw appropriate exceptions if they don't.

>> Right. >> RYAN: As of the GWT 2.1 release, we'll

even show you the line numbers on the on the error messages that we generate them which

was going over sight. You have--and even with those constraints, you've got back doors,

like for example, if you're--we need to work with a widget that does have constructor arguments,

you've got the UI factory annotation so let you indicate a method that's responsible for

instantiating these things, so you can take care of that encode. You can actually annotate

the constructor itself saying I want the arguments on this constructor to be available as attributes

that the user can set from the markup, and so on. There are cases where we have to rely

on customized parsing. We haven't yet opened up--we haven't made that customized parsing

stuff pluggable. It's rare that it's actually necessary. We will get to ramping that at

some point but we've managed to get away without doing so this long because most people don't

ask for it. >> Okay. Thank you.

>> RYAN: Mm-hmm... Okay. So you want to do one mic, one mic, and pick from the screen?

>> WEBBER: Sure. Here's I'll give you one screen here. Wow, that's a lot of percent

20s in that question. He probably spends way too much time running URLs. Let's see. Let

me see if I can read this. Are there any plans to add more example documentation based around

the UI overhaul? Yes, absolutely, absolutely. So one of the things that I really wanted

to do in 2.0 but fell behind on, and I'm working on it right now is a new sample we're calling

the Cookbook for one of the better term. It will have a lot of necessarily called recipes,

but we're really trying--really trying to cover all the cases that people are actually

running into and we're accumulating lots of questions, bug reports, discussions on fora

and so forth that point to a lot of common cases where people get stuck. We're going

to try to encode those all on the sample. So rather than have a sample that shoots a

tour of what's there, it's--the idea is more to cover all of the things that you would

actually want to do and practice so that hopefully, you can just go find one of those, copy and

paste that out, then tweak it to your heart's content. So we definitely recognized that

there is a bit of a failing on in terms of the guidance provided by samples and that's

definitely something we're working on. That already is checked into the....


>> WEBBER: ...that's definitely something we're working on. That already has checked

in to the Byte Shed code, by the way, in the [INDISTINCT], sort of [INDISTINCT] you look

at it, it is actually there. It's a little sketchy right now or a little bit of a rough

sketch but we'll keep iterating on it in there. >> RYAN: Go ahead.

>> Hey, there, I've used the duct panel layout before and I really liked the way that the

north and the south stayed put on the top and the bottom of the browser and then the

center panel is expanded to fit the remaining space. But in the used case of having the

header and the footer at the bottom of the page where you want the scroll bar to be the

entire page, do you have any plans to make a layout panel like that?

>> WEBBER: There's not a formal layout panel that handles that out of the box, but it is

actually pretty easy to construct. I'll give you a very rough idea, and that's actually

one of the samples that I'm putting in to Cookbook because so that's came up a few times.

What you do there--is there's the base layout that has--it allows you to specify pretty

much any kinds of constraints you can imagine, a sort of an--it allows you to pretty much

build anything but it's a little bit like brain surgery. Well, maybe, a dietary or something,

not like brain surgery. What you would essentially do is add something that--add one panel, one

child that's constrained to be top, left, right bottom zero that is all pinned to the

edges, that has the scroll bar. And then anything you want to float on top of that, you just--you

can constrain it to be actually on top of it. So, for example, header and footer would

be, you know; top, zero; height, 5m, just something like that; and then bottom, zero;

height, 5m with the footer. The underlying panels that had a scroll bar within it, would

still be scrolled underneath that, so it covered the whole--it would cover the whole screen,

and it would look as though, where the document level scroll. It's not actually the document

level scroll, it's actually just sitting underneath it but it gives you the same effect. And it

actually ends up being a lot more efficient when scrolling the entire document because

things like pop-ups don't have to be moved to cache when you scroll the document around.

>> Okay, thank you. >> WEBBER: Does that maker sense?

>> Yeah, the header moves with that scrolling, right. The header doesn't stay at the top.

>> WEBBER: Right and it looks like it's moving with the scrolling but it's actually just

sitting on top of it. >> Got you.

>> WEBBER: But it has the same effect and it's faster. Go for it.

>> Thanks, Joel. >> WEBBER: Sure. All right, better theme.

Who's--who was going to work on the better theme? John is that you? No, we a--we definitely

are looking into creating much better themes out of the batch right now, they're pretty

weak, we recognized that. In 1.5, we had themes that were not and quite as incredibly bad

as the ones in very first release. But there are--there's a lot more work that we're doing

on that front. And we've recruited UI designers internally to help out with that process.

We're also looking at ways to--because CSS resource, UI binder and all this stuff is

fairly new, we haven't actually reworked all the way that we just work yet. This is also

the incumbent complaint, so it's hard to mix these with sort of traditional way to--perhaps,

sort of two-styling mechanisms. So after [INDISTINCT] some I/O, we all [INDISTINCT] for a few days.

We're going to be looking at creating themes that can actually can be used with CSS resource

to gain the efficiency benefits from that but still be flexible and still allow you

to pick and choose how you want to play on different widgets and so forth. And as part

of that process we will de-uglify them as well. So, hopefully that would be helpful.

>> RYAN: Go ahead. >> Could you talk about the division of labor

on UiBinder templates? So, I could imagine somebody with HTML, CMSs skills starting off

with something at HTML CMS and hand it over to a GWT program who converts it or the GWT

program that does the whole thing or you go back and forth. Could you talk about the tradeoffs?

>> RYAN: We've seen all those things happen. It's very common. The common point is that

you usually have a designer working at the prototype in HTML, and then they throw it

over the wall to the engineer. I think the web microprocessors were giving enough that

you can get something that renders pretty quickly and then work over to try to factor

things in the widgets that should with it and so on. I know of at least one team, and

I hope that they're not an exception. They had actually a lot of luck with setting up

their designer with the host of development mode build of their product talking to a mock

backend so that he could actually work. And they thought him enough eclipse to get it

to start and type in the files and mess with the stuff, and hit the refresh button on their

browser with thicken of backend that things refreshed and rebuilt quickly, and they actually

have a quite awhile of success with that. I've heard of other counter examples where

designers got very frustrated at dealing with--they're used to looking in Firefox and using Firebug

and messing with the CSS names there and we given these horrible mangled [INDISTINCT]

names. One way to make that more tolerable is to find the configuration option; I don't

remember that at the top of my head, to turn off, at least tone down [INDISTINCT] of the

CSS names. We can't just leave them completely unmodified because--then we lose the name

spacing. And all of the sudden those collisions I talked about start to happen and your app

goes up. But you can still at least read the things. I personally--when I'm messing with

it, well, I'll tend to experiment with inline styles on the specific elements and then go

back to my code to a--or my templates to put the successful experiments on the class names,

that kind of thing. We want to make that better for designers.

>> WEBBER: Yeah. That's still in the very much brainstorming phase. I mean making the--especially

the Firebug, dev tools, loop closer--close that loop. A couple of other things, I want

to mention, you mentioned, dead mode setup for designer. A way that I've actually seen

that worked really well is you don't even have to install eclipse for them because the...

>> RYAN: Push up. >> WEBBER: If you give them the browser plug-in

and just give them the URL to point at, you can run several clients off of dev but simultaneously.

If you set up a machine where they can work to get the refresh cycle going, and they--people

have used text involving and shared directories, and things like that. So, they're editing

one file but they don't actually even know--have know about eclipse. And by the way, in case

you're, I'm sure, at least somebody in this room is thinking, that's great but dead mode

refreshes really slow. We absolutely know that and there are people in Atlanta right

now working very diligently on making that less true. So, hopefully that will also help

that process. Are there any--just plans to add a designer functionality to plug in, it

significantly speed up more in tasks. We are not, to my knowledge, planning on actually

building designer our self into the equipments plug-in. There is at least one really good

one from instantiations that a--it's been a lot--it's been a little while since I've

used it But they are actually out in the Sandbox demonstrating it right now. Those guys are

much better at GUI builders than we are. So, we prefer to let the experts do there thing.

That would be the best recommendation that I'm aware of for doing--for getting a sort

drag and drop functionality. >> RYAN: Go ahead.

>> I played with Roo yesterday and had it generate a--kind of scuffled that application

and noticed that it was using some other things besides what you've covered, that seemed almost

a little bit more of an MVP framework, a little--some more framework level components, like place

and some other class that I haven't heard of before.

>> RYAN: I'll be talking about that in depth this afternoon at 3:30.

>> Okay. >> RYAN: And while you're looking at that

why don't you start to bump into the works and the missing creatures, please understand

that it's very much a work in progress. There are probably whole layers of abstraction that

will go away and will certainly change radically. >> Yeah, it just--it looked interesting like

you guys are providing a little more framework to get an app running.

>> RYAN: We are definitely working on an application framework and that will be part of the 2.1.

>> How about new data binding API? We have a data binding API.

>> RYAN: That is also part of the application framework.

>> Okay, I'll trust you on that. So come to the talk at 3:30 and/or watch it on YouTube.

>> So you mentioned that much of the speed of the data presentation widgets in 2.1 comes

from taking the thing and making it a giant set in your HTML. Right now, I'm using Grid

and FlexTable, and there's a thing called the setText, which specifically does set in

our texts... >> WEBBER: Right.

>> that won't render HTML on the screen. Is there going to be something similar to

that for the data presentation widgets? >> WEBBER: So, yes and no. Essentially out

of the box--not exactly, but it should be really easy to get the same effect. So when

you saw that list example I setup before, there was a--this is the simple case where

I just have data on my client. I want to get it into the widget fast. I don't want to involve

some data fetching layer or anything like that. The structure there that we're settling

on is essentially like glazed lists where you can--you have--you have one adaptor class

to re-instantiate that binds to the table and the lists in tables are more or less the

same structure; they're just telling definitions that break fields out into columns. And you

would simply be operating on, say, a Java Util list instead of a--like a setText call,

but the effect should be the same. But the effect is the same, but if you make a hundred

calls to it to set up lots of rows, the widget will optimize that automatically. So, you

don't have the effect where the amount of data you're changing really affects the speed

of you're app very much in a really significant way. So, essentially yes but slightly different.

>> Thank you. >> WEBBER: Sure. Ah, let's see, use templates

in UI binder. I'm not quite sure how to parse that question.

>> RYAN: You can only use templates in UiBinder. >> WEBBER: That sounds good.

>> RYAN: I've tried to understand the question. >> WEBBER: [INDISTINCT]. Hopefully that was

clear enough. >> RYAN: Okay. And I think over there.

>> Yeah. Could you talk a little bit about the limitations and the considerations you

have--you need to have in mind for developing for mobile devices, specifically for Android

and iPhone. I have to run through some hoops just to get the scroll is in the swipe motion.

It seems to be not straightforward, so could you talk about any limitations?

>> WEBBER: Sorry, the--what's the part about scrolling again?

>> Scrolling, you know, if you just swipe your finger and get the scrolling effect.

>> WEBBER: Right. >> I have to run through some hoops, it wasn't

straightforward. >> WEBBER: Uh-hmm, it's true. So, when it

comes to supporting mobile devices, we really have two problems, I guess. I mean, ignoring--just

keeping your apps small enough to start efficiently and so forth which is more of just a scale

issue. One is--again, your rendering has to be fast enough that populating individual

pages is not slow, that's part of what we've designed these data presentation widgets to

solve. On mobile, we found--we've measured that even filling in a fairly large list is--could

measured in milliseconds in terms about the time it takes. But there are lot of APIs we

currently had not route. And that is some--that is a gap we have to close in the near future.

So things you mentioned like swipe gestures and so forth, those are things that for which

there are built-in events. But we simply haven't brought an interface to them yet. And we're

looking, probably in the third quarter, so to be focusing on closing the gap on a lot

of these things. There is also the issue, subtle issue but it's also the issue of scrolling

an interior area. So, you've noticed most, not all but the vast majority of mobile web

apps will scroll the entire screen. In other words, they just let things flow naturally

and that's where you have to scroll the whole thing. And if you've seen for example, the

mobile Gmail App, they do some crazy hacks to work around the problem that you need,

say, an archive button that stays available on the screen. So one of these things will

sort of float around and try to follow you. What we have found is that, with the newest

releases of all the mobile browsers, later iPhone releases, later Android releases, it's

become possible to actually synthesized the need of scrolling behavior and still keeps

a headers and footers and then swipe animations and all of that. Actually, Apple really showed

the way on that with their--if you look at the iPhone help app, they have pretty much

duplicated the native functionality in JavaScript. And we're looking to--we just begun actually

doing the same thing in our own code. >> Just a follow up question, how does the

Gmail do it? Because it seems to do it really well.

>> WEBBER: My understanding of what Gmail is doing, and it's been a little while since

I've used the mobile version, since I got my Android phone, I believe what they are

doing is, they're using regular document level scroll, but then when you--when it settles

down, the little floaty bar just eventually follows you. So, it waits a minute to catch

up, so it's not constantly interfering with the UI and slowing things down but then it

slides back into place. You can do that sort of thing but I think, ultimately, the better

solution is to actually make it behave more like a native App, because that what everybody

really wants. That's what I really want anyway so.

>> RYAN: Cross-site widgets. Cross-site widget; what's a better way to add them to the page

UI without using a div element ID key to locate the injection points.

>> WEBBER: I would ask that you follow up with the question on the users group. I'm

not quite sure I understand the question. And, well, the new Cookbook--I'll just jump

to the next really quickly because it's easy. Will the new Cookbook contain an event bus

example? I certainly hope so. That would be Ryan's job to do though.

>> RYAN: I'm the... >> WEBBER: [INDISTINCT]

>> RYAN: Roo is generating an event plus example for you, right now. And it will be generating

a better event bus example for you before we shift, then again, I'll talk about that

some at 3:30. >> My question is about infinite scrolling.

Yesterday, you mentioned it with the bit of a brain surgery, can you comment, how would

you proceed with this surgery? How would you do it? And also, in what you have right now,

as I understand this adaptor, you put data there, you're supposed to put all the data

at once and then it... >> WEBBER: Right.

>> everything on your page, like candid elements or div elements.

>> WEBBER: Exactly. So that adaptor really--just to be really clear. I think, I probably wasn't

as clear about this as I should have been, that adaptor class was a convenience class

or when you do want to just punch large amounts of data into the widget directly and have

it just sit there. The general--the more general interface, the listview delegates to something

that asks, the list you keep track of a range. So for paging, for example, just a simple

case, it says, I'm looking at items 37 to 230 rate. The adaptor or the thing that is

providing data to the listview is responsible for making sure it gives that data. That's

sort of the asynchronous nature of it. For paging, I think it's pretty clear how that

would work. For the infinite scrolling or sort of on demand rendering, it's the same

idea except that the range is more fluid. I have some samples sort half-baked on my

desktop right now that implement this and it actually works really, really well in practice

even the basic data sources. So, for example, one of the Cookbook samples I want to create,

once I get the widgets in place is a Flickr browser. And I found--I've been able to flick--browse

through thousands of icons, thousands and thousands of icons really smoothly, really

efficiently and without having to fetch data in advance. So, look for those, probably in

the Byte Shed and the first--in the near future and a...

>> RYAN: The Expenses App, is that used the list [INDISTINCT] or did you do a customized...

>> WEBBER: the Expenses App has a custom adaptor that does handle the async data source.

>> RYAN: And the app is like a generated by [INDISTINCT]. So don't use the listview adapter.

It's really quite trivial to use your own if that's the appropriate thing to do. The

listview adapter is a convenience when you've got list to run.

>> WEBBER: They'll be sent out of the box for handling simple cases. For slightly less

simple and made after case but, you know, simple backend data source cases.

>> Thank you. >> We're using the paging scroll table and

the incubator. How is your new table related to that? Is it complete rewrite? Is the interface

completely different? >> WEBBER: It is a mostly complete re-write

but we've taken a lot of lessons learned from that table, from that implementation, we learned

a lot of good things and we learned a lot of bad things in the process.

>> Can you say, what's some of the weaknesses of the incubator one was?

>> WEBBER: Ah, lets see, and the guy who wrote it just left. So, I'll have to bug him later

but... >> RYAN: I remember it being hard to customize,

when we kept bringing stuff in there. It was difficult to make it fast. You had...

>> WEBBER: Right, actually... >> RYAN: [INDISTINCT] actually get bulk rendering

to work... >> WEBBER: Right.

>> RYAN: Rather than--but when we did that, that's like, all we do now.

>> WEBBER: Right, and the interface--exactly, so the things like bulk rendering were these

weird--I mean even the term is kind of odd and awkward. There are these--sort of weird

bolt-on cases and we really sort of flipped the problem around and made it--made the efficient

thing the easy thing rather than something you do after you've gotten it working and

then find out that it's slow. It also doesn't try--there are certain things that that table

tried to do, that we've just later on proven, especially with the help of Speed Tracer team,

are just physically impossible to do it efficiently in the browser. So it tried to do things where

it would adjust column sizes to the size of the contents and so forth, and they just never

really worked very well for those cases. And we found like, it really caused the AdWords

team no sense of--no end of trouble. So, what we're trying to do is extract the use-cases.

And I think we're mostly there at this point. So, extract the use-cases that we know can

be made to work well. So, we don't try to send you down to this primrose path and find

out later that you've ended up in a place where you just can't get a fast app. We hoped

the transition move really straightforward and if it's--to the extent that it's not,

hopefully we can. We'll try to provide samples to make it clear how to move from one to the

other. There will be a number of teams within Google as well who are in the same situation.

Sir? >> Yeah, so I think the cell stuff is really

interesting in terms of, you know, getting away from widgets. I'm not at all by means

an expert, but I thought the widgets were really interesting because there's--like one

of their jobs is handle all the cross browser of idiosyncrasies, So when you start doing

in like cells. And all of a sudden, they have input, you know, boxes in them and all of

those that are just like really native input boxes--is all of a sudden --is it going to

be easier to just build apps with no widgets at all? Like what, like--even your search

boxes. You said, "Well, the search box is a widget." But if you're doing input boxes

in cells, can't we just do input boxes anywhere that aren't widgets basically?

>> WEBBER: Right. What I actually see happening there is--well one, I see that we will provide

a lot of these cells out of the box that already handle a lot of the stuff for you. So, and

if there--if there are cross-browser issues that sit on top of--higher than the down level,

they will still be doing some work to take it--to deal with those kinds of situations.

But the other thing that I see happening is--so the cell on its own can't handle events. It

needs help from something to do that. And that's where a lot of the deficiency comes

from, but that has to move into the container. What I would like to see happen is that we

see a series of widgets come into being, or in some cases, just mutating the ones that

are there so that they have a cell at their core and they provide the feature--the facilities

that the container would otherwise provide. So if you need to use a select box and a regular

widget context or a form or something like that, you can still do that just as easily

but at sharing the same infrastructure. This is the way a lot of, more traditionally, UI

toolkits work as well if in fact the term cell, we stole from Cocoa essentially, we

stole it from--I've forgotten whom. But hopefully, that will provide more of a coherent stack

and a kind of smooth transition from, you know, if I got it here in a widget, I probably

got here in the cell as well that's appropriate. So you can mix and match more easily but still

not deal with cross-browser issues... >> RYAN: Looking at the--sorry.

>> WEBBER: Okay. >> RYAN: Looking at the clock in the back,

I think we're out of time. >> I just--do you have a timeframe on when

that might happen? >> Well--actually, they're probably the best

there. Everybody's behind so we're going to run outside and be available right out the

front door if that's okay. >> RYAN: Thank you.

>> WEBBER: Thanks everybody.

The Description of Google I/O 2010 - GWT's UI overhaul