Gwt has a nice feature, the mvp framework.
At the beginning I was confused on how to do this, until I stumbled upon the hellomvp project.
The first thing you have to do is to to create some essential classes and interfaces on your client package.
First you create a ClientFactory Interface.
package com.gwttest.client; import com.google.gwt.event.shared.EventBus; import com.google.gwt.place.shared.PlaceController; import com.gwttest.client.testview.TestView; /** * * @author gkatzioura * */ public interface ClientFactory { EventBus getEventBus(); PlaceController getPlaceController(); }
Then you create a PlaceHistoryMapper
import com.gwttest.client.testview.TestPlace; import com.google.gwt.place.shared.PlaceHistoryMapper; import com.google.gwt.place.shared.WithTokenizers; /** * * @author gkatzioura * */ public interface AppPlaceHistoryMapper extends PlaceHistoryMapper { }
and a ClientFactoryImpl class (implementing the ClientFactory interface)
package com.gwttest.client; import com.google.gwt.event.shared.EventBus; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.place.shared.PlaceController; /** * * @author gkatzioura * */ public class ClientFactoryImpl implements ClientFactory { private static final EventBus eventBus = new SimpleEventBus(); private static final PlaceController placeController = new PlaceController(eventBus); @Override public EventBus getEventBus() { return eventBus; } @Override public PlaceController getPlaceController() { return placeController; } }
Now is the time to add a view and an activity
The google plugin for eclipse provides you with a wizard in order to create views and save some time and effort.
Anyway on your client package you can create a subpackage named testview
and a subpackage called activity.
The testview package will contain the the Place the View interaface and the View Implementation
package com.gwttest.client.testview; import com.google.gwt.place.shared.Place; import com.google.gwt.place.shared.PlaceTokenizer; public class TestPlace extends Place { /** * Sample property (stores token). */ private String name; public TestPlace(String token) { this.name = token; } public String getName() { return name; } /** * PlaceTokenizer knows how to serialize the Place's state to a URL token. */ public static class Tokenizer implements PlaceTokenizer<TestPlace> { @Override public String getToken(TestPlace place) { return place.getName(); } @Override public NewsPlace getPlace(String token) { return new TestPlace(token); } } }
package com.gwttest.client.testview; import com.google.gwt.place.shared.Place; import com.google.gwt.user.client.ui.IsWidget; /** * View base interface. * Extends IsWidget so a view impl can easily provide its container widget. */ public interface TestView extends IsWidget { void setName(String testName); void setPresenter(Presenter listener); public interface Presenter { /** * Navigate to a new Place in the browser. */ void goTo(Place place); } }
package com.gwttest.client.testview; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.place.shared.Place; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; /** * Sample implementation of {@link NewsView}. */ public class TestViewImpl extends FlowPanel implements TestView { private Presenter listener; private Button button; public TestViewImpl() { button = new Button("button"); button.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { Place newPlace = null; // TODO listener.goTo(newPlace); } }); add(button); } @Override public void setName(String name) { button.setHTML(name); } @Override public void setPresenter(Presenter listener) { this.listener = listener; } }
package com.gwttest.client.activity; import com.gwttest.client.ClientFactory; import com.gwttest.client.testview.TestPlace; import com.gwttest.client.testview.TestView; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; import com.google.gwt.place.shared.Place; import com.google.gwt.user.client.ui.AcceptsOneWidget; /** * Activities are started and stopped by an ActivityManager associated with a container Widget. */ public class TestActivity extends AbstractActivity implements TestView.Presenter { /** * Used to obtain views, eventBus, placeController. * Alternatively, could be injected via GIN. */ private ClientFactory clientFactory; /** * Sample property. */ private String name; public TestActivity(TestPlace place, ClientFactory clientFactory) { this.name = place.getName(); this.clientFactory = clientFactory; } @Override public void start(AcceptsOneWidget containerWidget, EventBus eventBus) { TestView view = clientFactory.getTestView(); view.setName(name); view.setPresenter(this); containerWidget.setWidget(view.asWidget()); } @Override public String mayStop() { return "Please hold on. This activity is stopping."; } /** * @see TestView.Presenter#goTo(Place) */ public void goTo(Place place) { clientFactory.getPlaceController().goTo(place); } }
Now you are ready to change the ClientFactory and the ClientFactoryIml to
package com.gwttest.client; import com.google.gwt.event.shared.EventBus; import com.google.gwt.place.shared.PlaceController; import com.gwttest.testview.TestView; /** * * @author gkatzioura * */ public interface ClientFactory { EventBus getEventBus(); PlaceController getPlaceController(); public TestView getTestView(); }
package com.gwttest.client; import com.google.gwt.event.shared.EventBus; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.place.shared.PlaceController; import com.gwttest.client.testview.TestView; import com.gwttest.client.testview.TestViewImpl; /** * * @author gkatzioura * */ public class ClientFactoryImpl implements ClientFactory { private static final EventBus eventBus = new SimpleEventBus(); private static final PlaceController placeController = new PlaceController(eventBus); private static final TestView testView = new TestViewImpl(); @Override public EventBus getEventBus() { return eventBus; } @Override public PlaceController getPlaceController() { return placeController; } @Override public TestView getTestView() { return testView; } }
Change the mapper to
package com.gwttest.client; import com.gwttest.activity.NewsActivity; import com.gwttest.client.testview.NewsPlace; import com.google.gwt.activity.shared.Activity; import com.google.gwt.activity.shared.ActivityMapper; import com.google.gwt.place.shared.Place; /** * * @author gkatzioura * */ public class AppActivityMapper implements ActivityMapper { private ClientFactory clientFactory; public AppActivityMapper(ClientFactory clientFactory) { super(); this.clientFactory = clientFactory; } @Override public Activity getActivity(Place place) { if(place instanceof TestPlace) return new TestActivity((TestPlace) place, clientFactory); return null; } }
package com.gwttest.client; import com.gwttest.client.testview.TestPlace; import com.google.gwt.place.shared.PlaceHistoryMapper; import com.google.gwt.place.shared.WithTokenizers; /** * * @author gkatzioura * */ @WithTokenizers({TestPlace.Tokenizer.class}) public interface AppPlaceHistoryMapper extends PlaceHistoryMapper { } And it's time to modify the entry point public class GwtTest implements EntryPoint { /** * The message displayed to the user when the server cannot be reached or * returns an error. */ private Place defaultPlace = new TestPlace("a test"); private SimplePanel appWidget = new SimplePanel(); public void onModuleLoad() { ClientFactory clientFactory = GWT.create(ClientFactoryImpl.class); EventBus eventBus = clientFactory.getEventBus(); PlaceController placeController = clientFactory.getPlaceController(); ActivityMapper activityMapper = new AppActivityMapper(clientFactory); ActivityManager activityManager = new ActivityManager(activityMapper, eventBus); activityManager.setDisplay(appWidget); AppPlaceHistoryMapper appPlaceHistoryMapper = GWT.create(AppPlaceHistoryMapper.class); PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(appPlaceHistoryMapper); historyHandler.register(placeController, eventBus, defaultPlace); //just a div in the html file with the id 'mvphacks' RootPanel.get("mvphacks").add(appWidget); historyHandler.handleCurrentHistory(); } }