Updated 2010-10-16: updated to GWT 2.1.0.
I'm not going to beat around the bush, GWT 2.1 Activities have no support for nesting. Let's see when you might think you need it, and how you could do without.
The scenario
So let's say you identified those four layouts in your app (this is based on a real example, the only difference is I only needed a single master-detail layout):
You might be tempted to build it as nested layouts, i.e. build the first one, and when needed put in the "main content" display region a master-detail or main-aside sub-layout, nesting two new display regions.
No nesting? Really?
Now, here's how you could do it without nesting, just showing hiding display regions when needed (and resizing the others to always fill the same dimensions):
Note that I chose the "detail" region to also serve as the "main content", but you could have decided otherwise, any region could have made it.
Mapping this layout to GWT 2.1 Activities
Each region is a display region, with its own ActivityManager
and ActivityMapper
.
ActivityManager vertMasterActivityManager = new ActivityManager(vertMasterActivityMapper, eventBus);
vertMasterActivityManager.setDisplay(vertMasterDisplay);
ActivityManager horizMasterActivityManager = new ActivityManager(horizMasterActivityMapper, eventBus);
horizMasterActivityManager.setDisplay(horizMasterDisplay);
ActivityManager mainActivityManager = new ActivityManager(mainActivityMapper, eventBus);
mainActivityManager.setDisplay(mainDisplay);
ActivityManager asideActivityManager = new ActivityManager(asideActivityMapper, eventBus);
asideActivityManager.setDisplay(asideDisplay);
When a region is not needed, the dedicated ActivityMapper
just returns null
, which the ActivityManager
will relay to the display region. And you'll code your display regions so that a null
activity widget hides it (in addition to emptying it).
// Assumes a LayoutPanel is used for the layout, with a SimplePanel for each display region
AcceptsOneWidget asideDisplay = new AcceptsOneWidget() {
public void setWidget(IsWidget activityWidget) {
Widget widget = Widget.asWidgetOrNull(activityWidget);
layoutPanel.setWidgetVisible(asidePanel, widget != null);
asidePanel.setWidget(widget);
}
};
Pros and Cons
On the pros side:
- no matter how many "screens" share the same layout, they all share the same dimensions (leading to a consistent layout) without duplicate coding or code sharing (or even reuse, there's a single code path to manage the panels sizes);
- using a
LayoutPanel
you can easily animate the transitions between layouts, with a single line of code!
On the cons side:
-
you'll have to dispatch between all the activities for a given "sub-region" in a single
ActivityMapper
; the no-nesting rule also applies here, but only in appearance: you'll just nest/split your dispatching code at another level.I'd suggest using a base
Place
, or a marker interface, to discriminate different groups of places/activities (a simple rule could be "those places with the vertical master-detail layout" vs. "those places with the main-aside layout" vs. etc., or a more complex, or more business-oriented one); and you can delegate each group to a more specific method, or even its ownActivityMapper
(and this is not limited to this use-case of complex layouts):public Activity getActivity(Place place) { if (place instanceof MailPlace) { return mailActivityMapper.getActivity(place); } if (place instanceof ContactsPlace) { return contactsActivityMapper.getActivity(place); } if (place instanceof SettingsPlace) { return settingsActivityMapper.getActivity(place); } return null; }
All in all, there are more advantages than drawbacks! As always, it's just a different way to approach the problem.
Conclusion
As the title said, you ain't gonna need nesting. But if you can come up with a use case that couldn't be addressed as explained above, I'd really like to hear about it! (and I believe the GWT team too)