Thursday, September 30, 2010

Testdriving GWT MVP from GWT 2.1 m3 Part I

The other day I was reading Thomas Broyers posts about GWT 2.1 not needing nested Activities. I was eager to try out the MVP stuff that went into GWT 2.1 so I thought I going to built a small sample app.


The idea of the GWT Team is that you don`t need to nest activities, instead you provide an ActivityMapper for every main Region of your screen. The Activitymanager provides the Activity for the region of your screen based on the current place (and it will change the activity if the place changes). From my point of view this is implemented the other way around, but before I post any jugdement lets try it out. By the way if you want to see the complete code you can download it here.

MyApp

My App has 3 regions (and therefore three activitymanagers). It should look like this:

head
Nav
Content

The Application has three Places called: Home, Admin, User.
The navbar will have 3 buttons from which you can navigate to the places. The app will start on the HomePlace.

I am using a DockLayoutPanel and Display containing a SimplePanel to represent the main structure of the ui.
First thing we need to instanciate the RootDisplays and place them in the LayoutPanel:

SimpleDisplay headDisplay = new SimpleDisplay();
SimpleDisplay navDisplay = new SimpleDisplay();
SimpleDisplay mainDisplay = new SimpleDisplay();

DockLayoutPanel p = new DockLayoutPanel(Unit.EM);
p.addNorth(headDisplay.getContainer(), 2);
p.addWest(navDisplay.getContainer(), 10);
p.add(mainDisplay.getContainer());
RootLayoutPanel.get().add(p);


Now we build an ActivityMapper and an ActivityManager for every Region of the UI:
HandlerManager eventBus = new HandlerManager(null);
TopActivityMapper topActivityMapper = new TopActivityMapper();
  ActivityManager topActicityManager = new ActivityManager(topActivityMapper, eventBus);
  topActicityManager.setDisplay(headDisplay);

  CenterActivityMapper centerActivityMapper = new CenterActivityMapper();
  ActivityManager activityManager = new ActivityManager(centerActivityMapper, eventBus);
  activityManager.setDisplay(mainDisplay);

  LeftActivityMapper leftActivityMapper = new LeftActivityMapper();
  ActivityManager leftActivityManager = new ActivityManager(leftActivityMapper, eventBus);
  leftActivityManager.setDisplay(navDisplay);


After that we tell the the PlaceController to start with the HomePlace and we are done:
PlaceController placeController = new PlaceController(eventBus);
placeController.goTo(new HomePlace());


The Mapping between Places and their activity is done in the ActivityMappers. The Mappers for the head and the navigation always return the same activity for any place. So lets take a look at the CenterActivityMapper, which can return 3 different activities:
public class CenterActivityMapper implements ActivityMapper {

 @Override
 public Activity getActivity(Place place) {

  if (place instanceof HomePlace)
   return new HomeActivity(new HomeDisplay());

  if (place instanceof AdminPlace)
   return new AdminActivity(new AdminDisplay());

  if (place instanceof UserPlace)
   return new UserActivity(new UserDisplay());

  return null;
 }

}

From what I can say so far (beeing used to work with gwt-presenter), activities are equivalent to presenters. Structuring the ui in regions and mapping the regions to activities seems a lot strange at first glance, but if you think about it: It makes sense. You may end up with a little more complex code in your activity mappers, but we can fix this by putting places into specific sub classes and delegating for specific groups of places.

Next up I am going to take a look at the place controller and how it integrates with the history mechanism.