Thursday, June 12, 2008

Frames inside TabPanels in Google Web Toolkit (GWT)

I'm building a little app in GWT, and put an iframe into one of the tabs. I wanted the browser to fill the whole panel:



Unfortunately, this doesn't work:

tp = new TabPanel();
tp.add(mainTable, "Table");
page = new Frame("http://www.google.com/");
page.setHeight("100%");
tp.add(page, "Web")


It results in:



After a tedious investigation, it appears that the problem lies in the underlying iframe: setting the iframe style to "height: 100%" doesn't work in HTML in general. You can set the height in pixels, but it's up to you to figure out how many pixels high it should be to fit properly. There's a related but different problem for the TabPanel: 100% seems not to respect other widgets that it's packed with, so it ends up too large, resulting in a vertical scroll bar where you don't want it. Incidentally, "width=100%" works fine in both cases.

Here's a (slightly hacky) solution:

class ResizeListener implements WindowResizeListener {
public void onWindowResized(int width,int height) {
tp.setHeight((Window.getClientHeight() - tp.getAbsoluteTop() - 50) + "px");
page.setHeight((Window.getClientHeight() - page.getAbsoluteTop() - 10) + "px");
}
}

...
Window.addWindowResizeListener(new ResizeListener());
...


You also need to call both these functions initially as part of the setup code. This seems to be an unfortunate case where you need to know more than GWT's surface: you need to understand the underlying HTML implementation to solve the problem.

3 comments:

berto xxx said...

I like this blog. for real!


berto xxx

Manjunath said...

Hi Craig, Can u please provide the complete code as we have the same requirements(embedding frame inside a tabpanels). Additionally how can we open a new tabPanel on click of a href link.

A sample code would be much useful.

-Manju

Brendan said...

Here is another method which is even a bit of a bigger hack but seems to work in most cases. Add the following style to you .css page:

.gwt-TabPanelBottom {
height: 97%;
}