GWT MVP

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

}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s