0

I'm exploring a few possible solutions to a common problem (your input is welcomed). I've simplified the problem for the sake of clarity.

Let's say that I have a widget which displays a number of rectangular boxes. Each box has the same static width & hight. There are lots of boxes over 1000, this number will grow over time.

I'm thinking of using pagination to display the boxes. I'd like to a avoid using scrollbars. So I'd like to dynamically change the number of boxes that show on each page based on the size of the page.

What is the best way to solve this problem, at first I thought if the container-widget implements RequiresResize I should be able to capture the dimensions of the widget. But I think I'd need to have every parent widget to also implement RequiresResize and ProvidesResize.

Is there a better way?

Thanks

Community
  • 1
  • 1
hba
  • 7,406
  • 10
  • 63
  • 105

3 Answers3

2

Within a vanilla GWT project the easiest way to go about getting this is to use the layout panel classes - these use the RequiresResize and ProvidesResize interfaces you mentioned. The best way to get this started then is not with RootPanel, but with RootLayoutPanel. This alternative starting point wraps a single RootPanel instance, and will size its child to the available browser space, by invoking RequiresResize.onResize if it exists.

The rest of your widget tree (children added to parents, etc) then should also use these interfaces to declare that they need resize information. It is very likely that you won't actually end up building any widgets that don't, but mostly wrapping existing ones (with UiBinder or Composite) into a new widget - the trick there is that you are making a new widget, and by default one that doesn't implement ProvidesResize or RequiresResize. Two basic solutions to that as you build out your app:

  • Implement these two interfaces. Then, in your onResize() method, invoke onResize() of the top-level widget that needs to know that its size has changed. This allows more control, but requires more explicit code to make sizing work. The easiest way to do this is to extend ResizeComposite instead of Composite. Or,

  • Don't extend a Widget (i.e. don't extend Composite/ResizeComposite/etc), but instead, implement IsWidget. This will let you avoid adding a new Widget type to the tree, and just group all of the widgets you are using into a type that happens to build and set them all up. This is my preferred option - it won't look like a widget, often easier to mock, etc. Now you need to have a asWidget() method that returns the base of your widget structure - anything this is added to will talk directly to that (and call its onResize() directly), letting you ignore the details of how they need to interact. This is my preferred option.

Colin Alworth
  • 17,801
  • 2
  • 26
  • 39
  • Thanks for the clear explanation...I think however that Andrei's solution will work for me. – hba Jan 16 '13 at 01:55
1

It's much simpler:

Window.addResizeHandler(new ResizeHandler() {

    @Override
    public void onResize(ResizeEvent event) {
        resize();
    }

});

private void resize() {
        // Measure your widget
        // Decide how many squares to display
}

You will need to call resize() when your view first loads, and then any window resize will trigger this method as well.

Andrei Volgin
  • 40,755
  • 6
  • 49
  • 58
0

You only need to implement RequiresResize and maintain the Provides/RequiresResize chain if your want resize events. But in your case you just want to know the size of the window or the container, not the resize event (at least, that's what I infer from your question).

In that case, you can use the getOffsetWidth() and getOffsetHeight() methods of the container widget before deciding pagination (see http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/user/client/ui/UIObject.html#getOffsetHeight() ).

On the other hand, if you then need to relayout things when the window size changes, then you must use the Provides/RequireResize as you say. If you don't want to maintain the full hierarchy, just place a hidden LayoutPanel in the root layout panel and route resize events to whatever you want. Not a very clean solution, but a solution...

xxxxxxxxx
  • 999
  • 5
  • 11