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();
}
}