Cleans up the mobile web app sample for 2.4.
Review at http://gwt-code-reviews.appspot.com/1468801
Review by: jlabanca@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10358 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/samples/mobilewebapp/pom.xml b/samples/mobilewebapp/pom.xml
index 530873e..38641da 100644
--- a/samples/mobilewebapp/pom.xml
+++ b/samples/mobilewebapp/pom.xml
@@ -12,7 +12,7 @@
<properties>
<!-- Convenience property to set the GWT version -->
- <gwtVersion>2.3.0</gwtVersion>
+ <gwtVersion>2.4.0</gwtVersion>
<!-- GWT needs at least java 1.6 -->
<maven.compiler.source>1.6</maven.compiler.source>
@@ -56,6 +56,12 @@
<dependencies>
<dependency>
+ <groupId>javax.inject</groupId>
+ <artifactId>javax.inject</artifactId>
+ <version>1</version>
+ </dependency>
+
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthRequestTransport.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthRequestTransport.java
index 3c87b17..5e224d7 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthRequestTransport.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthRequestTransport.java
@@ -15,13 +15,13 @@
*/
package com.google.gwt.sample.gaerequest.client;
-import com.google.gwt.event.shared.EventBus;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.sample.gaerequest.shared.GaeHelper;
import com.google.gwt.user.client.Window.Location;
+import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.requestfactory.gwt.client.DefaultRequestTransport;
import com.google.web.bindery.requestfactory.shared.ServerFailure;
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthenticationFailureEvent.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthenticationFailureEvent.java
index 3720e95..d7fa66a 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthenticationFailureEvent.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthenticationFailureEvent.java
@@ -15,20 +15,20 @@
*/
package com.google.gwt.sample.gaerequest.client;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.GwtEvent;
-import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.web.bindery.event.shared.Event;
+import com.google.web.bindery.event.shared.EventBus;
+import com.google.web.bindery.event.shared.HandlerRegistration;
+
/**
* An event posted when an authentication failure is detected.
*/
-public class GaeAuthenticationFailureEvent extends GwtEvent<GaeAuthenticationFailureEvent.Handler> {
+public class GaeAuthenticationFailureEvent extends Event<GaeAuthenticationFailureEvent.Handler> {
/**
* Implemented by handlers of this type of event.
*/
- public interface Handler extends EventHandler {
+ public interface Handler {
/**
* Called when a {@link GaeAuthenticationFailureEvent} is fired.
*
@@ -64,7 +64,7 @@
}
@Override
- public GwtEvent.Type<Handler> getAssociatedType() {
+ public Type<Handler> getAssociatedType() {
return TYPE;
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/ReloadOnAuthenticationFailure.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/ReloadOnAuthenticationFailure.java
index 1560a65..a345f1d 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/ReloadOnAuthenticationFailure.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/gaerequest/client/ReloadOnAuthenticationFailure.java
@@ -16,9 +16,9 @@
package com.google.gwt.sample.gaerequest.client;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window.Location;
+import com.google.web.bindery.event.shared.EventBus;
+import com.google.web.bindery.event.shared.HandlerRegistration;
/**
* A minimal auth failure handler which takes the user a login page.
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/MobileWebApp.gwt.xml b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/MobileWebApp.gwt.xml
index da6dd17..c701f4a 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/MobileWebApp.gwt.xml
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/MobileWebApp.gwt.xml
@@ -17,6 +17,9 @@
<inherits name='com.google.gwt.sample.gaerequest.GaeRequest'/>
<inherits name='com.google.gwt.sample.core.Core'/>
+ <inherits name='com.google.gwt.sample.ui.UI'/>
+
+ <inherits name="com.google.gwt.logging.Logging"/>
<!-- Specify the app entry point class. -->
<entry-point class='com.google.gwt.sample.mobilewebapp.client.MobileWebApp'/>
@@ -43,5 +46,6 @@
<!-- Specify the paths for translatable code -->
<source path='client'/>
+ <source path='presenter'/>
<source path='shared'/>
</module>
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/App.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/App.java
index 1fb6997..b1eb60b 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/App.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/App.java
@@ -15,34 +15,38 @@
*/
package com.google.gwt.sample.mobilewebapp.client;
+import com.google.gwt.activity.shared.ActivityManager;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
-import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceChangeEvent;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.place.shared.PlaceHistoryHandler;
import com.google.gwt.sample.gaerequest.client.ReloadOnAuthenticationFailure;
-import com.google.gwt.sample.mobilewebapp.client.event.AddTaskEvent;
-import com.google.gwt.sample.mobilewebapp.client.event.EditingCanceledEvent;
-import com.google.gwt.sample.mobilewebapp.client.event.GoHomeEvent;
+import com.google.gwt.sample.mobilewebapp.client.activity.AppPlaceHistoryMapper;
+import com.google.gwt.sample.mobilewebapp.client.event.ActionEvent;
+import com.google.gwt.sample.mobilewebapp.client.event.ActionNames;
import com.google.gwt.sample.mobilewebapp.client.event.ShowTaskEvent;
-import com.google.gwt.sample.mobilewebapp.client.event.TaskSavedEvent;
-import com.google.gwt.sample.mobilewebapp.client.place.AppPlaceHistoryMapper;
-import com.google.gwt.sample.mobilewebapp.client.place.TaskEditPlace;
-import com.google.gwt.sample.mobilewebapp.client.place.TaskListPlace;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskPlace;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListPlace;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
import com.google.gwt.storage.client.Storage;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
+import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.UmbrellaException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
/**
* The heart of the applicaiton, mainly concerned with bootstrapping.
*/
public class App {
private static final String HISTORY_SAVE_KEY = "SAVEPLACE";
+ private static final Logger log = Logger.getLogger(App.class.getName());
+
private final Storage storage;
/**
@@ -61,6 +65,8 @@
*/
private final MobileWebAppShell shell;
+ private final ActivityManager activityManager;
+
private final AppPlaceHistoryMapper historyMapper;
private final PlaceHistoryHandler historyHandler;
@@ -68,12 +74,14 @@
private final ReloadOnAuthenticationFailure reloadOnAuthenticationFailure;
public App(Storage storage, EventBus eventBus, PlaceController placeController,
- AppPlaceHistoryMapper historyMapper, PlaceHistoryHandler historyHandler,
+ ActivityManager activityManager, AppPlaceHistoryMapper historyMapper,
+ PlaceHistoryHandler historyHandler,
ReloadOnAuthenticationFailure reloadOnAuthenticationFailure, MobileWebAppShell shell) {
this.storage = storage;
this.eventBus = eventBus;
this.placeController = placeController;
+ this.activityManager = activityManager;
this.historyMapper = historyMapper;
this.historyHandler = historyHandler;
this.reloadOnAuthenticationFailure = reloadOnAuthenticationFailure;
@@ -86,12 +94,14 @@
* @param parentView where to show the app's widget
*/
public void run(HasWidgets.ForIsWidget parentView) {
+ activityManager.setDisplay(shell);
+
parentView.add(shell);
- eventBus.addHandler(AddTaskEvent.TYPE, new AddTaskEvent.Handler() {
+ ActionEvent.register(eventBus, ActionNames.ADD_TASK, new ActionEvent.Handler() {
@Override
- public void onAddTask(AddTaskEvent event) {
- placeController.goTo(TaskEditPlace.getTaskCreatePlace());
+ public void onAction(ActionEvent event) {
+ placeController.goTo(TaskPlace.getTaskCreatePlace());
}
});
@@ -99,27 +109,27 @@
@Override
public void onShowTask(ShowTaskEvent event) {
TaskProxy task = event.getTask();
- placeController.goTo(TaskEditPlace.createTaskEditPlace(task.getId(), task));
+ placeController.goTo(TaskPlace.createTaskEditPlace(task.getId(), task));
}
});
- eventBus.addHandler(GoHomeEvent.TYPE, new GoHomeEvent.Handler() {
+ ActionEvent.register(eventBus, ActionNames.GO_HOME, new ActionEvent.Handler() {
@Override
- public void onGoHome(GoHomeEvent event) {
+ public void onAction(ActionEvent event) {
placeController.goTo(new TaskListPlace(false));
}
});
- eventBus.addHandler(TaskSavedEvent.TYPE, new TaskSavedEvent.Handler() {
+ ActionEvent.register(eventBus, ActionNames.TASK_SAVED, new ActionEvent.Handler() {
@Override
- public void onTaskSaved(TaskSavedEvent event) {
+ public void onAction(ActionEvent event) {
placeController.goTo(new TaskListPlace(true));
}
});
- eventBus.addHandler(EditingCanceledEvent.TYPE, new EditingCanceledEvent.Handler() {
+ ActionEvent.register(eventBus, ActionNames.EDITING_CANCELED, new ActionEvent.Handler() {
@Override
- public void onEditCanceled(EditingCanceledEvent event) {
+ public void onAction(ActionEvent event) {
placeController.goTo(new TaskListPlace(false));
}
});
@@ -130,8 +140,13 @@
while (e instanceof UmbrellaException) {
e = ((UmbrellaException) e).getCauses().iterator().next();
}
- Window.alert("An unexpected error occurred: " + e.getMessage());
- placeController.goTo(new TaskListPlace(false));
+
+ String message = e.getMessage();
+ if (message == null) {
+ message = e.toString();
+ }
+ log.log(Level.SEVERE, "Uncaught exception", e);
+ Window.alert("An unexpected error occurred: " + message);
}
});
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactory.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactory.java
index 47da8f5..f75fd52 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactory.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactory.java
@@ -15,13 +15,12 @@
*/
package com.google.gwt.sample.mobilewebapp.client;
-import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.PlaceController;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskReadView;
-import com.google.gwt.storage.client.Storage;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditView;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskReadView;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListView;
import com.google.gwt.sample.mobilewebapp.shared.MobileWebAppRequestFactory;
+import com.google.web.bindery.event.shared.EventBus;
/**
* The factory responsible for instantiating everything interesting in this
@@ -29,8 +28,6 @@
* "http://google-gin.googlecode.com/svn/trunk/javadoc/com/google/gwt/inject/client/Ginjector.html"
* >Ginjector</a> code generated by <a
* href="http://code.google.com/p/google-gin/">GIN</a>.
- * <p>
- * Note that {@link #init} must be called before anything else.
*/
public interface ClientFactory {
/**
@@ -41,20 +38,13 @@
App getApp();
/**
- * Get the event bus.
+ * Get the {@link EventBus}
*
- * @return the {@link EventBus} used throughout the app
+ * @return the event bus used through the app
*/
EventBus getEventBus();
/**
- * Get the local {@link Storage} object if supported.
- *
- * @return the local {@link Storage} object, or null unsupporting browsers
- */
- Storage getLocalStorageIfSupported();
-
- /**
* Get the {@link PlaceController}.
*
* @return the place controller
@@ -94,9 +84,4 @@
* Get an implementation of {@link TaskEditView}.
*/
TaskReadView getTaskReadView();
-
- /**
- * Must be called before any get methods.
- */
- void init();
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java
index ec18f04..93bc04b 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java
@@ -18,25 +18,26 @@
import com.google.gwt.activity.shared.ActivityManager;
import com.google.gwt.activity.shared.ActivityMapper;
import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.place.shared.PlaceHistoryHandler;
import com.google.gwt.sample.gaerequest.client.GaeAuthRequestTransport;
import com.google.gwt.sample.gaerequest.client.ReloadOnAuthenticationFailure;
import com.google.gwt.sample.mobilewebapp.client.activity.AppActivityMapper;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListActivity;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskReadView;
+import com.google.gwt.sample.mobilewebapp.client.activity.AppPlaceHistoryMapper;
import com.google.gwt.sample.mobilewebapp.client.desktop.DesktopTaskEditView;
import com.google.gwt.sample.mobilewebapp.client.desktop.DesktopTaskListView;
import com.google.gwt.sample.mobilewebapp.client.desktop.DesktopTaskReadView;
import com.google.gwt.sample.mobilewebapp.client.desktop.MobileWebAppShellDesktop;
-import com.google.gwt.sample.mobilewebapp.client.place.AppPlaceHistoryMapper;
+import com.google.gwt.sample.mobilewebapp.client.ui.PieChart;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditView;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskReadView;
+import com.google.gwt.sample.mobilewebapp.presenter.taskchart.TaskChartPresenter;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListView;
import com.google.gwt.sample.mobilewebapp.shared.MobileWebAppRequestFactory;
import com.google.gwt.storage.client.Storage;
import com.google.gwt.user.client.Window;
+import com.google.web.bindery.event.shared.EventBus;
+import com.google.web.bindery.event.shared.SimpleEventBus;
import com.google.web.bindery.requestfactory.shared.RequestTransport;
/**
@@ -57,7 +58,7 @@
private final TaskProxyLocalStorage taskProxyLocalStorage;
private TaskEditView taskEditView;
private TaskListView taskListView;
- private final ActivityManager activityManager;
+ private ActivityManager activityManager;
private final AppPlaceHistoryMapper historyMapper = GWT.create(AppPlaceHistoryMapper.class);
@@ -82,34 +83,19 @@
localStorage = null;
}
taskProxyLocalStorage = new TaskProxyLocalStorage(localStorage);
-
- /*
- * ActivityMapper determines an Activity to run for a particular place.
- */
- ActivityMapper activityMapper = new AppActivityMapper(this, getIsTaskListIncludedProvider());
- /*
- * Owns a panel in the window, in this case the entire {@link #shell}.
- * Monitors the {@link #eventBus} for {@link PlaceChangeEvent}s posted by
- * the {@link #placeController}, and chooses what {@link Activity} gets to
- * take over the panel at the current place. Configured by an {@link
- * AppActivityMapper}.
- */
- activityManager = new ActivityManager(activityMapper, eventBus);
}
public App getApp() {
- return new App(getLocalStorageIfSupported(), getEventBus(), getPlaceController(),
- historyMapper, historyHandler, new ReloadOnAuthenticationFailure(), getShell());
+ return new App(getLocalStorageIfSupported(), eventBus, getPlaceController(),
+ getActivityManager(), historyMapper, historyHandler, new ReloadOnAuthenticationFailure(),
+ getShell());
}
+ @Override
public EventBus getEventBus() {
return eventBus;
}
-
- public Storage getLocalStorageIfSupported() {
- return localStorage;
- }
-
+
public PlaceController getPlaceController() {
return placeController;
}
@@ -150,8 +136,12 @@
return taskReadView;
}
- public void init() {
- activityManager.setDisplay(getShell());
+ /**
+ * ActivityMapper determines an Activity to run for a particular place,
+ * configures the {@link #getActivityManager()}
+ */
+ protected ActivityMapper createActivityMapper() {
+ return new AppActivityMapper(this);
}
/**
@@ -160,7 +150,13 @@
* @return the UI shell
*/
protected MobileWebAppShell createShell() {
- return new MobileWebAppShellDesktop(eventBus, placeController, getTaskListView(),
+ PieChart pieChart = PieChart.createIfSupported();
+ TaskChartPresenter presenter = null;
+ if (pieChart != null) {
+ presenter = new TaskChartPresenter(pieChart);
+ presenter.start(getEventBus());
+ }
+ return new MobileWebAppShellDesktop(eventBus, presenter, placeController, getTaskListView(),
getTaskEditView(), getTaskReadView());
}
@@ -187,31 +183,22 @@
}
/**
- * Returns provider that indicates whether the task list is always visible.
- * The default implementation returned by this method always indicates false.
- *
- * @return provider that always provides false
+ * Owns a panel in the window, in this case the entire {@link #shell}.
+ * Monitors the {@link #eventBus} for
+ * {@link com.google.gwt.place.shared.PlaceChangeEvent PlaceChangeEvent}s posted by the
+ * {@link #placeController}, and chooses what
+ * {@link com.google.gwt.activity.shared.Activity Activity} gets to take
+ * over the panel at the current place. Configured by the
+ * {@link #createActivityMapper()}.
*/
- protected Provider<Boolean> getIsTaskListIncludedProvider() {
- return new Provider<Boolean>() {
- @Override
- public Boolean get() {
- return false;
- }
- };
+ protected ActivityManager getActivityManager() {
+ if (activityManager == null) {
+ activityManager = new ActivityManager(createActivityMapper(), eventBus);
+ }
+ return activityManager;
}
- protected Provider<TaskListActivity> getTaskListActivityProvider() {
- return new Provider<TaskListActivity>() {
- @Override
- public TaskListActivity get() {
-
- /*
- * TODO (rjrjr) the false arg is needed by MobileWebAppShellTablet,
- * which shouldn't be using activities at all
- */
- return new TaskListActivity(ClientFactoryImpl.this, false);
- }
- };
+ private Storage getLocalStorageIfSupported() {
+ return localStorage;
}
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImplMobile.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImplMobile.java
index a2e3d93..e668cbb 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImplMobile.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImplMobile.java
@@ -15,30 +15,26 @@
*/
package com.google.gwt.sample.mobilewebapp.client;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListActivity;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListView.Presenter;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskReadView;
import com.google.gwt.sample.mobilewebapp.client.mobile.MobileTaskEditView;
import com.google.gwt.sample.mobilewebapp.client.mobile.MobileTaskListView;
import com.google.gwt.sample.mobilewebapp.client.mobile.MobileTaskReadView;
import com.google.gwt.sample.mobilewebapp.client.mobile.MobileWebAppShellMobile;
-import com.google.gwt.sample.mobilewebapp.client.ui.OrientationHelper;
-import com.google.gwt.sample.mobilewebapp.client.ui.WindowBasedOrientationHelper;
-import com.google.gwt.user.client.ui.AcceptsOneWidget;
-import com.google.gwt.user.client.ui.IsWidget;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditView;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskReadView;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListView;
+import com.google.gwt.sample.ui.client.OrientationHelper;
+import com.google.gwt.sample.ui.client.WindowBasedOrientationHelper;
/**
* Mobile version of {@link ClientFactory}.
*/
public class ClientFactoryImplMobile extends ClientFactoryImpl {
private final OrientationHelper orientationHelper = new WindowBasedOrientationHelper();
-
+
@Override
protected MobileWebAppShell createShell() {
- return new MobileWebAppShellMobile(orientationHelper, getTaskListView(),
- getTaskEditView(), getTaskReadView(), getEventBus());
+ return new MobileWebAppShellMobile(getEventBus(), orientationHelper, getTaskListView(),
+ getTaskEditView(), getTaskReadView());
}
@Override
@@ -48,21 +44,7 @@
@Override
protected TaskListView createTaskListView() {
- ProvidesPresenter<TaskListView.Presenter, TaskListView> factory =
- new ProvidesPresenter<TaskListView.Presenter, TaskListView>() {
- @Override
- public Presenter getPresenter(TaskListView view) {
- TaskListActivity taskListActivity = new TaskListActivity(ClientFactoryImplMobile.this, false);
- taskListActivity.start(new AcceptsOneWidget() {
- @Override
- public void setWidget(IsWidget w) {
- // No op until we separate presenter and activity
- }
- }, getEventBus());
- return taskListActivity;
- }
- };
- return new MobileTaskListView(factory);
+ return new MobileTaskListView();
}
@Override
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImplTablet.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImplTablet.java
index 65257ca..d0b3b04 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImplTablet.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImplTablet.java
@@ -15,13 +15,15 @@
*/
package com.google.gwt.sample.mobilewebapp.client;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskReadView;
+import com.google.gwt.activity.shared.ActivityMapper;
+import com.google.gwt.sample.mobilewebapp.client.activity.AppActivityMapperTablet;
import com.google.gwt.sample.mobilewebapp.client.tablet.MobileWebAppShellTablet;
import com.google.gwt.sample.mobilewebapp.client.tablet.TabletTaskEditView;
import com.google.gwt.sample.mobilewebapp.client.tablet.TabletTaskReadView;
-import com.google.gwt.sample.mobilewebapp.client.ui.OrientationHelper;
-import com.google.gwt.sample.mobilewebapp.client.ui.WindowBasedOrientationHelper;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditView;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskReadView;
+import com.google.gwt.sample.ui.client.OrientationHelper;
+import com.google.gwt.sample.ui.client.WindowBasedOrientationHelper;
/**
* Tablet version of {@link ClientFactory}.
@@ -30,8 +32,13 @@
private final OrientationHelper orientationHelper = new WindowBasedOrientationHelper();
@Override
+ protected ActivityMapper createActivityMapper() {
+ return new AppActivityMapperTablet(super.createActivityMapper(), orientationHelper);
+ }
+
+ @Override
protected MobileWebAppShell createShell() {
- return new MobileWebAppShellTablet(getEventBus(), orientationHelper, getTaskListView());
+ return new MobileWebAppShellTablet(this, orientationHelper, getTaskListView());
}
@Override
@@ -43,18 +50,4 @@
protected TaskReadView createTaskReadView() {
return new TabletTaskReadView();
}
-
- @Override
- protected Provider<Boolean> getIsTaskListIncludedProvider() {
- /*
- * TODO(rjrjr) This is awkward. Seems like we should be wrapping the tablet
- * version of the ActivityMapper or something.
- */
- return new Provider<Boolean>() {
- @Override
- public Boolean get() {
- return !orientationHelper.isPortrait();
- }
- };
- }
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/MobileWebApp.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/MobileWebApp.java
index c86304c..a31fe8c 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/MobileWebApp.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/MobileWebApp.java
@@ -25,7 +25,6 @@
public class MobileWebApp implements EntryPoint {
public void onModuleLoad() {
ClientFactory clientFactory = GWT.create(ClientFactory.class);
- clientFactory.init();
clientFactory.getApp().run(RootLayoutPanel.get());
}
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/MobileWebAppShell.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/MobileWebAppShell.java
index 4b1c792..596b904 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/MobileWebAppShell.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/MobileWebAppShell.java
@@ -1,12 +1,12 @@
/*
* Copyright 2011 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,7 +15,6 @@
*/
package com.google.gwt.sample.mobilewebapp.client;
-import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.IsWidget;
@@ -24,10 +23,16 @@
*/
public interface MobileWebAppShell extends AcceptsOneWidget, IsWidget {
/**
- * Set the handler to invoke when the add button is pressed. If no handler is
- * specified, the button is hidden.
+ * Show or hide the Add button, which must post an
+ * {@link com.google.gwt.sample.mobilewebapp.client.event.ActionEvent
+ * ActionEvent} with a source name of
+ * {@link com.google.gwt.sample.mobilewebapp.client.event.ActionNames#ADD_TASK
+ * ActionEventNames.ADD_TASK} when clicked.
+ * <p>
+ * TODO: this is ridiculous, and is in the process of being changed to
+ * something much simpler
*
- * @param handler the handler to add to the button, or null to hide
+ * @param visible to show the button, false to hide it
*/
- void setAddButtonHandler(ClickHandler handler);
+ void setAddButtonVisible(boolean visible);
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/AppActivityMapper.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/AppActivityMapper.java
index 36c3000..7fcf29b 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/AppActivityMapper.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/AppActivityMapper.java
@@ -15,13 +15,16 @@
*/
package com.google.gwt.sample.mobilewebapp.client.activity;
+import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.activity.shared.Activity;
import com.google.gwt.activity.shared.ActivityMapper;
+import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.sample.mobilewebapp.client.ClientFactory;
-import com.google.gwt.sample.mobilewebapp.client.Provider;
-import com.google.gwt.sample.mobilewebapp.client.place.TaskEditPlace;
-import com.google.gwt.sample.mobilewebapp.client.place.TaskListPlace;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskPlace;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListPlace;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListPresenter;
+import com.google.gwt.user.client.ui.AcceptsOneWidget;
/**
* A mapping of places to activities used by this application.
@@ -29,25 +32,34 @@
public class AppActivityMapper implements ActivityMapper {
private final ClientFactory clientFactory;
- private final Provider<Boolean> isTaskListIncluded;
- public AppActivityMapper(ClientFactory clientFactory, Provider<Boolean> isTaskListIncluded) {
- this.isTaskListIncluded = isTaskListIncluded;
+ public AppActivityMapper(ClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
- public Activity getActivity(Place place) {
+ public Activity getActivity(final Place place) {
if (place instanceof TaskListPlace) {
// The list of tasks.
- if (!isTaskListIncluded.get()) {
- // Do not start a task list activity if the task list is always visible.
- return new TaskListActivity(clientFactory, (TaskListPlace) place);
- }
- } else if (place instanceof TaskEditPlace) {
- // Editable view of a task.
- return new TaskEditActivity(clientFactory, (TaskEditPlace) place);
+ return new AbstractActivity() {
+ @Override
+ public void start(AcceptsOneWidget panel, EventBus eventBus) {
+ TaskListPresenter presenter = new TaskListPresenter(clientFactory, (TaskListPlace) place);
+ presenter.start(eventBus);
+ panel.setWidget(presenter);
+ }
+
+ /*
+ * Note no call to presenter.stop(). The TaskListViews do that
+ * themselves as a side effect of setPresenter.
+ */
+ };
}
+
+ if (place instanceof TaskPlace) {
+ // Editable view of a task.
+ return new TaskActivity(clientFactory, (TaskPlace) place);
+ }
+
return null;
}
-
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/AppActivityMapperTablet.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/AppActivityMapperTablet.java
new file mode 100644
index 0000000..65ccfd6
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/AppActivityMapperTablet.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.client.activity;
+
+import com.google.gwt.activity.shared.Activity;
+import com.google.gwt.activity.shared.ActivityMapper;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListPlace;
+import com.google.gwt.sample.ui.client.OrientationHelper;
+
+/**
+ * A mapping of places to activities used by the table version of the
+ * application.
+ */
+public class AppActivityMapperTablet implements ActivityMapper {
+
+ private final ActivityMapper wrapped;
+ private final OrientationHelper orientationHelper;
+
+ public AppActivityMapperTablet(ActivityMapper wrapped, OrientationHelper orientationHelper) {
+ this.wrapped = wrapped;
+ this.orientationHelper = orientationHelper;
+ }
+
+ public Activity getActivity(Place place) {
+ if (place instanceof TaskListPlace && !orientationHelper.isPortrait()) {
+ // The task list is always visible in landscape, so don't start one
+ return null;
+ }
+
+ return wrapped.getActivity(place);
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/AppPlaceHistoryMapper.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/AppPlaceHistoryMapper.java
new file mode 100644
index 0000000..cdba21e
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/AppPlaceHistoryMapper.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.client.activity;
+
+import com.google.gwt.place.shared.PlaceHistoryMapper;
+import com.google.gwt.place.shared.WithTokenizers;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskPlace;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListPlace;
+
+/**
+ * This interface is the hub of your application's navigation system. It links
+ * the {@link com.google.gwt.place.shared.Place Place}s your user navigates to
+ * with the browser history system — that is, it makes the browser's back
+ * and forth buttons work for you, and also makes each spot in your app
+ * bookmarkable.
+ * <p>
+ * Its implementation is code generated based on the @WithTokenizers
+ * annotation.
+ */
+@WithTokenizers({TaskListPlace.Tokenizer.class, TaskPlace.Tokenizer.class})
+public interface AppPlaceHistoryMapper extends PlaceHistoryMapper {
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskActivity.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskActivity.java
new file mode 100644
index 0000000..c983816
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskActivity.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.client.activity;
+
+import com.google.gwt.activity.shared.AbstractActivity;
+import com.google.gwt.sample.mobilewebapp.client.ClientFactory;
+import com.google.gwt.sample.mobilewebapp.client.event.TaskEditEvent;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditPresenter;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskPlace;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskReadPresenter;
+import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+import com.google.gwt.sample.ui.client.PresentsWidgets;
+import com.google.gwt.user.client.ui.AcceptsOneWidget;
+import com.google.web.bindery.event.shared.ResettableEventBus;
+
+/**
+ * An activity that shows details on a particular task, and allows the user to
+ * edit it.
+ */
+public class TaskActivity extends AbstractActivity {
+ private PresentsWidgets presenter;
+
+ private final TaskPlace place;
+
+ private final ClientFactory clientFactory;
+
+ private ResettableEventBus childEventBus;
+
+ /**
+ * Construct a new {@link TaskActivity}.
+ *
+ * @param clientFactory the {@link ClientFactory} of shared resources
+ * @param place configuration for this activity
+ */
+ public TaskActivity(ClientFactory clientFactory, TaskPlace place) {
+ this.place = place;
+ this.clientFactory = clientFactory;
+ }
+
+ @Override
+ public String mayStop() {
+ return presenter.mayStop();
+ }
+
+ @Override
+ public void onCancel() {
+ presenter.stop();
+ }
+
+ @Override
+ public void onStop() {
+ childEventBus.removeHandlers();
+ presenter.stop();
+ }
+
+ public void start(final AcceptsOneWidget container, com.google.gwt.event.shared.EventBus eventBus) {
+ this.childEventBus = new ResettableEventBus(eventBus);
+ eventBus.addHandler(TaskEditEvent.TYPE, new TaskEditEvent.Handler() {
+ @Override
+ public void onTaskEdit(TaskEditEvent event) {
+ // Stop the read presenter
+ onStop();
+ presenter = startEdit(event.getReadOnlyTask());
+ container.setWidget(presenter);
+ }
+ });
+
+ if (place.getTaskId() == null) {
+ presenter = startCreate();
+ } else {
+ presenter = startDisplay(place);
+ }
+ container.setWidget(presenter);
+ }
+
+ private PresentsWidgets startCreate() {
+ PresentsWidgets rtn = new TaskEditPresenter(clientFactory);
+ rtn.start(childEventBus);
+ return rtn;
+ }
+
+ private PresentsWidgets startDisplay(TaskPlace place) {
+ PresentsWidgets rtn = new TaskReadPresenter(clientFactory, place);
+ rtn.start(childEventBus);
+ return rtn;
+ }
+
+ private PresentsWidgets startEdit(TaskProxy readOnlyTask) {
+ PresentsWidgets rtn = new TaskEditPresenter(clientFactory, readOnlyTask);
+ rtn.start(childEventBus);
+ return rtn;
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskEditActivity.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskEditActivity.java
deleted file mode 100644
index 62d8159..0000000
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskEditActivity.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.mobilewebapp.client.activity;
-
-import com.google.gwt.activity.shared.AbstractActivity;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.sample.mobilewebapp.client.ClientFactory;
-import com.google.gwt.sample.mobilewebapp.client.event.EditingCanceledEvent;
-import com.google.gwt.sample.mobilewebapp.client.event.TaskSavedEvent;
-import com.google.gwt.sample.mobilewebapp.client.place.TaskEditPlace;
-import com.google.gwt.sample.mobilewebapp.client.ui.SoundEffects;
-import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
-import com.google.gwt.sample.mobilewebapp.shared.TaskRequest;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.AcceptsOneWidget;
-import com.google.web.bindery.requestfactory.shared.Receiver;
-import com.google.web.bindery.requestfactory.shared.Request;
-import com.google.web.bindery.requestfactory.shared.ServerFailure;
-
-import java.util.Set;
-import java.util.logging.Logger;
-
-import javax.validation.ConstraintViolation;
-
-/**
- * Activity that presents a task to be edited.
- */
-public class TaskEditActivity extends AbstractActivity implements TaskEditView.Presenter,
- TaskReadView.Presenter {
-
- private static final Logger log = Logger.getLogger(TaskEditActivity.class.getName());
- private final ClientFactory clientFactory;
-
- /**
- * A boolean indicating whether or not this activity is still active. The user
- * might move to another activity while this one is loading, in which case we
- * do not want to do any more work.
- */
- private boolean isDead = false;
-
- /**
- * Indicates whether the activity is editing an existing task or creating a
- * new task.
- */
- private boolean isEditing;
-
- /**
- * The current task being displayed, might not be possible to edit it.
- */
- private TaskProxy readOnlyTask;
-
- /**
- * The current task being edited, provided by RequestFactory.
- */
- private TaskProxy editTask;
-
- /**
- * The ID of the current task being edited.
- */
- private final Long taskId;
-
- /**
- * The request used to persist the modified task.
- */
- private Request<Void> taskPersistRequest;
- private AcceptsOneWidget container;
-
- /**
- * Construct a new {@link TaskEditActivity}.
- *
- * @param clientFactory the {@link ClientFactory} of shared resources
- * @param place configuration for this activity
- */
- public TaskEditActivity(ClientFactory clientFactory, TaskEditPlace place) {
- this.taskId = place.getTaskId();
- this.readOnlyTask = place.getTask();
- this.clientFactory = clientFactory;
- }
-
- public void deleteTask() {
- if (isEditing) {
- doDeleteTask();
- } else {
- doCancelTask();
- }
- }
-
- @Override
- public void editTask() {
- // Load the existing task.
- final TaskEditView editView = clientFactory.getTaskEditView();
-
- if (taskId == null) {
- isEditing = false;
- editView.setEditing(false);
- TaskRequest request = clientFactory.getRequestFactory().taskRequest();
- editTask = request.create(TaskProxy.class);
- editView.getEditorDriver().edit(editTask, request);
- } else {
- editView.setLocked(true);
- clientFactory.getRequestFactory().taskRequest().findTask(this.taskId).fire(
- new Receiver<TaskProxy>() {
- @Override
- public void onSuccess(TaskProxy response) {
- // Early exit if this activity has already been cancelled.
- if (isDead) {
- return;
- }
-
- // Task not found.
- if (response == null) {
- Window.alert("The task with id '" + taskId + "' could not be found."
- + " Please select a different task from the task list.");
- doCancelTask();
- return;
- }
-
- // Show the task.
- editTask = response;
- editView.getEditorDriver().edit(response,
- clientFactory.getRequestFactory().taskRequest());
- editView.setLocked(false);
- }
- });
- }
- container.setWidget(editView);
- }
-
- @Override
- public void onCancel() {
- // Ignore all incoming responses to the requests from this activity.
- isDead = true;
- clientFactory.getTaskEditView().setLocked(false);
- }
-
- @Override
- public void onStop() {
- // Ignore all incoming responses to the requests from this activity.
- isDead = true;
- clientFactory.getTaskEditView().setLocked(false);
- }
-
- public void saveTask() {
- // Flush the changes into the editable task.
- TaskRequest context = (TaskRequest) clientFactory.getTaskEditView().getEditorDriver().flush();
-
- /*
- * Create a persist request the first time we try to save this task. If a
- * request already exists, reuse it.
- */
- if (taskPersistRequest == null) {
- taskPersistRequest = context.persist().using(editTask);
- }
-
- // Fire the request.
- taskPersistRequest.fire(new Receiver<Void>() {
- @Override
- public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
- handleConstraintViolations(violations);
- }
-
- @Override
- public void onSuccess(Void response) {
- // Notify the user that the task was updated.
- TaskEditActivity.this.notify("Task Saved");
-
- // Return to the task list.
- clientFactory.getEventBus().fireEvent(new TaskSavedEvent());
- }
- });
- }
-
- public void start(AcceptsOneWidget container, EventBus eventBus) {
- this.container = container;
- // Prefetch the sounds used in this activity.
- SoundEffects.get().prefetchError();
-
- // Hide the 'add' button in the shell.
- clientFactory.getShell().setAddButtonHandler(null);
-
- // Set the presenter on the views.
- final TaskEditView editView = clientFactory.getTaskEditView();
- editView.setPresenter(this);
- editView.setNameViolation(null);
-
- final TaskReadView readView = clientFactory.getTaskReadView();
- readView.setPresenter(this);
-
- if (taskId == null) {
- editTask();
- return;
- } else {
- // Lock the display until the task is loaded.
- isEditing = true;
- editView.setEditing(true);
-
- // Try to load the task from local storage.
- if (readOnlyTask == null) {
- readOnlyTask = clientFactory.getTaskProxyLocalStorage().getTask(taskId);
- }
-
- if (readOnlyTask == null) {
- // Load the existing task.
- clientFactory.getRequestFactory().taskRequest().findTask(this.taskId).fire(
- new Receiver<TaskProxy>() {
- @Override
- public void onSuccess(TaskProxy response) {
- // Early exit if this activity has already been cancelled.
- if (isDead) {
- return;
- }
-
- // Task not found.
- if (response == null) {
- Window.alert("The task with id '" + taskId + "' could not be found."
- + " Please select a different task from the task list.");
- doCancelTask();
- return;
- }
-
- // Show the task.
- readOnlyTask = response;
- readView.getEditorDriver().edit(response);
- }
- });
- } else {
- // Use the task that was passed with the place.
- readView.getEditorDriver().edit(readOnlyTask);
- }
- }
-
- // Display the view.
- container.setWidget(readView);
- }
-
- /**
- * Cancel the current task.
- */
- private void doCancelTask() {
- clientFactory.getEventBus().fireEvent(new EditingCanceledEvent());
- }
-
- /**
- * Delete the current task.
- */
- private void doDeleteTask() {
- if (editTask == null) {
- return;
- }
-
- // Delete the task in the data store.
- final TaskProxy toDelete = this.editTask;
- clientFactory.getRequestFactory().taskRequest().remove().using(toDelete).fire(
- new Receiver<Void>() {
- @Override
- public void onFailure(ServerFailure error) {
- Window.alert("An error occurred on the server while deleting this task: \"."
- + error.getMessage() + "\".");
- }
-
- @Override
- public void onSuccess(Void response) {
- onTaskDeleted();
- }
- });
- }
-
- /**
- * Handle constraint violations.
- */
- private void handleConstraintViolations(Set<ConstraintViolation<?>> violations) {
- // Display the violations.
- clientFactory.getTaskEditView().getEditorDriver().setConstraintViolations(violations);
-
- // Play a sound.
- SoundEffects.get().playError();
- }
-
- /**
- * Notify the user of a message.
- *
- * @param message the message to display
- */
- private void notify(String message) {
- // TODO Add notification pop-up
- log.fine("Tell the user: " + message);
- }
-
- /**
- * Called when a task has been successfully deleted.
- */
- private void onTaskDeleted() {
- // Notify the user that the task was deleted.
- notify("Task Deleted");
-
- // Return to the task list.
- clientFactory.getEventBus().fireEvent(new TaskSavedEvent());
- }
-}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskListActivity.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskListActivity.java
deleted file mode 100644
index e543e98..0000000
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskListActivity.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.sample.mobilewebapp.client.activity;
-
-import com.google.gwt.activity.shared.AbstractActivity;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.GwtEvent;
-import com.google.gwt.sample.mobilewebapp.client.ClientFactory;
-import com.google.gwt.sample.mobilewebapp.client.event.AddTaskEvent;
-import com.google.gwt.sample.mobilewebapp.client.event.ShowTaskEvent;
-import com.google.gwt.sample.mobilewebapp.client.place.TaskListPlace;
-import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.AcceptsOneWidget;
-import com.google.web.bindery.requestfactory.shared.Receiver;
-import com.google.web.bindery.requestfactory.shared.ServerFailure;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Activity that presents a list of tasks.
- */
-public class TaskListActivity extends AbstractActivity implements TaskListView.Presenter {
-
- /**
- * Event fired when the task list is updated.
- */
- public static class TaskListUpdateEvent extends GwtEvent<TaskListActivity.TaskListUpdateHandler> {
-
- /**
- * Handler type.
- */
- private static Type<TaskListUpdateHandler> TYPE;
-
- /**
- * Gets the type associated with this event.
- *
- * @return returns the handler type
- */
- public static Type<TaskListUpdateHandler> getType() {
- if (TYPE == null) {
- TYPE = new Type<TaskListUpdateHandler>();
- }
- return TYPE;
- }
-
- private final List<TaskProxy> tasks;
-
- public TaskListUpdateEvent(List<TaskProxy> tasks) {
- this.tasks = tasks;
- }
-
- @Override
- public Type<TaskListUpdateHandler> getAssociatedType() {
- return TYPE;
- }
-
- public List<TaskProxy> getTasks() {
- return tasks;
- }
-
- @Override
- protected void dispatch(TaskListUpdateHandler handler) {
- handler.onTaskListUpdated(this);
- }
- }
-
- /**
- * Handler for {@link TaskListUpdateEvent}.
- */
- public static interface TaskListUpdateHandler extends EventHandler {
-
- /**
- * Called when the task list is updated.
- */
- void onTaskListUpdated(TaskListUpdateEvent event);
- }
-
- /**
- * The delay in milliseconds between calls to refresh the task list.
- */
- private static final int REFRESH_DELAY = 5000;
-
- /**
- * The handler that handlers add button clicks.
- */
- private final ClickHandler addButtonHandler = new ClickHandler() {
- public void onClick(ClickEvent event) {
- clientFactory.getEventBus().fireEvent(new AddTaskEvent());
- }
- };
-
- /**
- * A boolean indicating that we should clear the task list when started.
- */
- private final boolean clearTaskList;
-
- private final ClientFactory clientFactory;
-
- /**
- * A boolean indicating whether or not this activity is still active. The user
- * might move to another activity while this one is loading, in which case we
- * do not want to do any more work.
- */
- private boolean isDead = false;
-
- /**
- * The refresh timer used to periodically refresh the task list.
- */
- private Timer refreshTimer;
-
- public TaskListActivity(ClientFactory clientFactory, boolean clearTaskList) {
- this.clientFactory = clientFactory;
- this.clearTaskList = clearTaskList;
- }
-
- /**
- * Construct a new {@link TaskListActivity}.
- *
- * @param clientFactory the {@link ClientFactory} of shared resources
- * @param place configuration for this activity
- */
- public TaskListActivity(ClientFactory clientFactory, TaskListPlace place) {
- this(clientFactory, place.isTaskListStale());
- }
-
- public ClickHandler getAddButtonHandler() {
- return addButtonHandler;
- }
-
- @Override
- public void onCancel() {
- killActivity();
- }
-
- @Override
- public void onStop() {
- killActivity();
- }
-
- public void selectTask(TaskProxy selected) {
- // Go into edit mode when a task is selected.
- clientFactory.getEventBus().fireEvent(new ShowTaskEvent(selected));
- }
-
- public void start(AcceptsOneWidget container, EventBus eventBus) {
- // Add a handler to the 'add' button in the shell.
- clientFactory.getShell().setAddButtonHandler(addButtonHandler);
-
- // Set the presenter on the view.
- final TaskListView view = clientFactory.getTaskListView();
- view.setPresenter(this);
-
- // Clear the task list and display it.
- if (clearTaskList) {
- view.clearList();
- }
- container.setWidget(view);
-
- // Create a timer to periodically refresh the task list.
- refreshTimer = new Timer() {
- @Override
- public void run() {
- refreshTaskList();
- }
- };
-
- // Load the saved task list from storage
- List<TaskProxy> list = clientFactory.getTaskProxyLocalStorage().getTasks();
- setTasks(list);
-
- // Request the task list now.
- refreshTaskList();
- }
-
- /**
- * Kill this activity.
- */
- private void killActivity() {
- // Ignore all incoming responses to the requests from this activity.
- isDead = true;
-
- // Kill the refresh timer.
- if (refreshTimer != null) {
- refreshTimer.cancel();
- }
- }
-
- /**
- * Refresh the task list.
- */
- private void refreshTaskList() {
- clientFactory.getRequestFactory().taskRequest().findAllTasks().fire(
- new Receiver<List<TaskProxy>>() {
- @Override
- public void onFailure(ServerFailure error) {
- // ignore
- }
-
- @Override
- public void onSuccess(List<TaskProxy> response) {
- // Early exit if this activity has already been canceled.
- if (isDead) {
- return;
- }
-
- // Display the tasks in the view.
- if (response == null) {
- response = Collections.<TaskProxy> emptyList();
- }
- setTasks(response);
-
- // save the response to storage
- clientFactory.getTaskProxyLocalStorage().setTasks(response);
-
- // Restart the timer.
- refreshTimer.schedule(REFRESH_DELAY);
- }
- });
- }
-
- /**
- * Set the list of tasks.
- */
- private void setTasks(List<TaskProxy> tasks) {
- clientFactory.getTaskListView().setTasks(tasks);
- clientFactory.getEventBus().fireEventFromSource(new TaskListUpdateEvent(tasks), this);
- }
-}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskEditView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskEditView.java
index 4bae38c..81d6677 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskEditView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskEditView.java
@@ -36,9 +36,9 @@
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
import com.google.gwt.sample.mobilewebapp.client.ui.DateButton;
import com.google.gwt.sample.mobilewebapp.client.ui.EditorDecorator;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditView;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxyImpl;
import com.google.gwt.uibinder.client.UiBinder;
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskListView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskListView.java
index 69fac21..f93acf2 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskListView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskListView.java
@@ -16,7 +16,7 @@
package com.google.gwt.sample.mobilewebapp.client.desktop;
import com.google.gwt.cell.client.DateCell;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListView;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListView;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.DataGrid;
@@ -106,8 +106,10 @@
taskList.setVisibleRangeAndClearData(taskList.getVisibleRange(), true);
}
- @Override
public void setPresenter(Presenter presenter) {
+ if (this.presenter != null) {
+ this.presenter.stop();
+ }
this.presenter = presenter;
}
@@ -119,16 +121,4 @@
public void setTasks(List<TaskProxy> tasks) {
taskList.setRowData(tasks);
}
-
- @Override
- public void start() {
- //TODO
- throw new UnsupportedOperationException("Auto-generated method stub");
- }
-
- @Override
- public void stop() {
- //TODO
- throw new UnsupportedOperationException("Auto-generated method stub");
- }
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskReadView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskReadView.java
index 9c6eb11..290dff9 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskReadView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskReadView.java
@@ -19,7 +19,7 @@
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskReadView;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskReadView;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
@@ -32,7 +32,7 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * View used to edit a task.
+ * View used to see the details of a task.
*/
public class DesktopTaskReadView extends Composite implements TaskReadView {
@@ -42,8 +42,7 @@
interface DesktopTaskReadViewUiBinder extends UiBinder<Widget, DesktopTaskReadView> {
}
-
- interface Driver extends SimpleBeanEditorDriver<TaskProxy, DesktopTaskReadView> {
+ interface EditorDriver extends SimpleBeanEditorDriver<TaskProxy, DesktopTaskReadView> {
}
/**
@@ -68,9 +67,9 @@
@UiField
Label notesEditor;
@UiField
- Button saveButton;
+ Button editButton;
- private final Driver driver = GWT.create(Driver.class);
+ private final EditorDriver editorDriver = GWT.create(EditorDriver.class);
/**
* The {@link TaskReadView.Presenter} for this view.
@@ -82,10 +81,9 @@
*/
public DesktopTaskReadView() {
initWidget(uiBinder.createAndBindUi(this));
- driver.initialize(this);
-
+ editorDriver.initialize(this);
// Create a new task or modify the current task when done is pressed.
- saveButton.addClickHandler(new ClickHandler() {
+ editButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
if (presenter != null) {
presenter.editTask();
@@ -95,7 +93,7 @@
}
public SimpleBeanEditorDriver<TaskProxy, ?> getEditorDriver() {
- return driver;
+ return editorDriver;
}
public void setPresenter(Presenter presenter) {
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskReadView.ui.xml b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskReadView.ui.xml
index 941bc98..bf08bab 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskReadView.ui.xml
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskReadView.ui.xml
@@ -127,7 +127,7 @@
colspan='2'
align='center'>
<g:Button
- ui:field="saveButton"
+ ui:field="editButton"
addStyleNames="{style.button} {style.saveButton}">Edit</g:Button>
</td>
</tr>
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/MobileWebAppShellDesktop.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/MobileWebAppShellDesktop.java
index 117dfec..fd53bf9 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/MobileWebAppShellDesktop.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/MobileWebAppShellDesktop.java
@@ -15,7 +15,6 @@
*/
package com.google.gwt.sample.mobilewebapp.client.desktop;
-import com.google.gwt.canvas.dom.client.CssColor;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.VideoElement;
@@ -26,14 +25,12 @@
import com.google.gwt.place.shared.PlaceChangeEvent;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.sample.mobilewebapp.client.MobileWebAppShell;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListActivity;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListActivity.TaskListUpdateEvent;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskReadView;
-import com.google.gwt.sample.mobilewebapp.client.place.TaskEditPlace;
-import com.google.gwt.sample.mobilewebapp.client.place.TaskListPlace;
-import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditView;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskPlace;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskReadView;
+import com.google.gwt.sample.mobilewebapp.presenter.taskchart.TaskChartPresenter;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListPlace;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListView;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.cellview.client.CellList;
@@ -57,7 +54,6 @@
import com.google.web.bindery.event.shared.EventBus;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
/**
@@ -131,11 +127,6 @@
private boolean firstContentWidget = true;
/**
- * A pie chart showing a snapshot of the tasks.
- */
- private PieChart pieChart;
-
- /**
* The {@link DialogBox} used to display the tutorial.
*/
private PopupPanel tutoralPopup;
@@ -147,10 +138,10 @@
/**
* Construct a new {@link MobileWebAppShellDesktop}.
- * @param clientFactory the {@link ClientFactory} of shared resources
*/
- public MobileWebAppShellDesktop(EventBus bus, final PlaceController placeController,
- TaskListView taskListView, TaskEditView taskEditView, TaskReadView taskReadView) {
+ public MobileWebAppShellDesktop(EventBus bus, TaskChartPresenter pieChart,
+ final PlaceController placeController, TaskListView taskListView, TaskEditView taskEditView,
+ TaskReadView taskReadView) {
// Initialize the main menu.
Resources resources = GWT.create(Resources.class);
@@ -169,7 +160,7 @@
return p instanceof TaskListPlace;
}
});
- menuItems.add(new MainMenuItem("Add Task", TaskEditPlace.getTaskCreatePlace()));
+ menuItems.add(new MainMenuItem("Add Task", TaskPlace.getTaskCreatePlace()));
mainMenu.setRowData(menuItems);
// Choose a place when a menu item is selected.
@@ -206,7 +197,6 @@
initWidget(uiBinder.createAndBindUi(this));
// Initialize the pie chart.
- pieChart = PieChart.createIfSupported();
String chartUrlValue = Window.Location.getParameter(CHART_URL_ATTRIBUTE);
if (chartUrlValue != null && chartUrlValue.startsWith("f")) {
// Chart manually disabled.
@@ -217,36 +207,27 @@
pieChartContainer.setWidget(new Label("Try upgrading to a modern browser to enable charts."));
} else {
// Chart supported.
- pieChart.setWidth("90%");
- pieChart.setHeight("90%");
- pieChart.getElement().getStyle().setMarginLeft(5.0, Unit.PCT);
- pieChart.getElement().getStyle().setMarginTop(5.0, Unit.PCT);
+ Widget pieWidget = pieChart.asWidget();
+ pieWidget.setWidth("90%");
+ pieWidget.setHeight("90%");
+ pieWidget.getElement().getStyle().setMarginLeft(5.0, Unit.PCT);
+ pieWidget.getElement().getStyle().setMarginTop(5.0, Unit.PCT);
+
pieChartContainer.setWidget(pieChart);
}
- // Initialize the add button.
- setAddButtonHandler(null);
-
/*
* Add all views to the DeckLayoutPanel so we can animate between them.
- * Using a DeckLayoutPanel here works because we only have a few views, and we
- * always know that the task views should animate in from the right side of
- * the screen. A more complex app will require more complex logic to figure
- * out which direction to animate.
+ * Using a DeckLayoutPanel here works because we only have a few views, and
+ * we always know that the task views should animate in from the right side
+ * of the screen. A more complex app will require more complex logic to
+ * figure out which direction to animate.
*/
contentContainer.add(taskListView);
contentContainer.add(taskReadView);
contentContainer.add(taskEditView);
contentContainer.setAnimationDuration(800);
- // Listen for events from the task list activity.
- bus.addHandler(TaskListUpdateEvent.getType(),
- new TaskListActivity.TaskListUpdateHandler() {
- public void onTaskListUpdated(TaskListUpdateEvent event) {
- updatePieChart(event.getTasks());
- }
- });
-
// Show a tutorial when the help link is clicked.
helpLink.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
@@ -255,13 +236,8 @@
});
}
- /**
- * Set the handler to invoke when the add button is pressed. If no handler is
- * specified, the button is hidden.
- *
- * @param handler the handler to add to the button, or null to hide
- */
- public void setAddButtonHandler(ClickHandler handler) {
+ @Override
+ public void setAddButtonVisible(boolean isVisible) {
// No-op: Adding a task is handled in the main menu.
}
@@ -347,52 +323,4 @@
tutoralPopup = popup;
popup.center();
}
-
- /**
- * Update the pie chart with the list of tasks.
- *
- * @param tasks the list of tasks
- */
- @SuppressWarnings("deprecation")
- private void updatePieChart(List<TaskProxy> tasks) {
- if (pieChart == null) {
- return;
- }
-
- // Calculate the slices based on the due date.
- double pastDue = 0;
- double dueSoon = 0;
- double onTime = 0;
- double noDate = 0;
- final Date now = new Date();
- final Date tomorrow = new Date(now.getYear(), now.getMonth(), now.getDate() + 1, 23, 59, 59);
- for (TaskProxy task : tasks) {
- Date dueDate = task.getDueDate();
- if (dueDate == null) {
- noDate++;
- } else if (dueDate.before(now)) {
- pastDue++;
- } else if (dueDate.before(tomorrow)) {
- dueSoon++;
- } else {
- onTime++;
- }
- }
-
- // Update the pie chart.
- pieChart.clearSlices();
- if (pastDue > 0) {
- pieChart.addSlice(pastDue, CssColor.make(255, 100, 100));
- }
- if (dueSoon > 0) {
- pieChart.addSlice(dueSoon, CssColor.make(255, 200, 100));
- }
- if (onTime > 0) {
- pieChart.addSlice(onTime, CssColor.make(100, 255, 100));
- }
- if (noDate > 0) {
- pieChart.addSlice(noDate, CssColor.make(200, 200, 200));
- }
- pieChart.redraw();
- }
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/ActionEvent.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/ActionEvent.java
new file mode 100644
index 0000000..7dcd011
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/ActionEvent.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.sample.mobilewebapp.client.event;
+
+import com.google.web.bindery.event.shared.Event;
+import com.google.web.bindery.event.shared.EventBus;
+import com.google.web.bindery.event.shared.HandlerRegistration;
+
+
+/**
+ * Fired when the user wants the app to do something. Action events are fired
+ * with a string name, and handlers monitor the event bus for them based on that
+ * name.
+ */
+public class ActionEvent extends Event<ActionEvent.Handler> {
+
+ /**
+ * Implemented by objects that handle {@link ActionEvent}.
+ */
+ public interface Handler {
+ void onAction(ActionEvent event);
+ }
+
+ /**
+ * The event type.
+ */
+ private static final Type<ActionEvent.Handler> TYPE = new Type<ActionEvent.Handler>();
+
+ public static void fire(EventBus eventBus, String sourceName) {
+ eventBus.fireEventFromSource(new ActionEvent(), sourceName);
+ }
+
+ public static HandlerRegistration register(EventBus eventBus, String sourceName, Handler handler) {
+ return eventBus.addHandlerToSource(TYPE, sourceName, handler);
+ }
+
+ /**
+ * Protected contructor to encourage the use of
+ * {@link #fire(EventBus, String)}.
+ */
+ protected ActionEvent() {
+ }
+
+ @Override
+ public final Type<ActionEvent.Handler> getAssociatedType() {
+ return TYPE;
+ }
+
+ @Override
+ protected void dispatch(ActionEvent.Handler handler) {
+ handler.onAction(this);
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/Provider.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/ActionNames.java
similarity index 65%
rename from samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/Provider.java
rename to samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/ActionNames.java
index 7ce2b32..5a29f9f 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/Provider.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/ActionNames.java
@@ -13,11 +13,14 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.sample.mobilewebapp.client;
+package com.google.gwt.sample.mobilewebapp.client.event;
/**
- * Just like javax.inject.Provider, makes things.
+ * Names of the {@link ActionEvent}s used in this app.
*/
-public interface Provider<T> {
- T get();
-}
\ No newline at end of file
+public interface ActionNames {
+ final String ADD_TASK = "addTask";
+ final String EDITING_CANCELED = "editingCanceled";
+ final String GO_HOME = "goHome";
+ final String TASK_SAVED = "taskSaved";
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/ShowTaskEvent.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/ShowTaskEvent.java
index 9e0ea11..feeccce 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/ShowTaskEvent.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/ShowTaskEvent.java
@@ -32,17 +32,17 @@
void onShowTask(ShowTaskEvent event);
}
- private final TaskProxy task;
-
/**
* The event type.
*/
public static final Type<ShowTaskEvent.Handler> TYPE = new Type<ShowTaskEvent.Handler>();
+ private final TaskProxy task;
+
public ShowTaskEvent(TaskProxy task) {
this.task = task;
}
-
+
@Override
public final Type<ShowTaskEvent.Handler> getAssociatedType() {
return TYPE;
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/TaskEditEvent.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/TaskEditEvent.java
new file mode 100644
index 0000000..c1e0479
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/TaskEditEvent.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.sample.mobilewebapp.client.event;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+
+/**
+ * Fired when the user wants to edit a task.
+ */
+public class TaskEditEvent extends GwtEvent<TaskEditEvent.Handler> {
+ /**
+ * Implemented by objects that handle {@link TaskEditEvent}.
+ */
+ public interface Handler extends EventHandler {
+ void onTaskEdit(TaskEditEvent event);
+ }
+
+ /**
+ * The event type.
+ */
+ public static final Type<TaskEditEvent.Handler> TYPE = new Type<TaskEditEvent.Handler>();
+
+ private final TaskProxy task;
+
+ public TaskEditEvent(TaskProxy task) {
+ this.task = task;
+ }
+
+ @Override
+ public final Type<TaskEditEvent.Handler> getAssociatedType() {
+ return TYPE;
+ }
+
+ public TaskProxy getReadOnlyTask() {
+ return task;
+ }
+
+ @Override
+ protected void dispatch(TaskEditEvent.Handler handler) {
+ handler.onTaskEdit(this);
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/TaskListUpdateEvent.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/TaskListUpdateEvent.java
new file mode 100644
index 0000000..22a29a2
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/event/TaskListUpdateEvent.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.client.event;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+
+import java.util.List;
+
+/**
+ * Event fired when the task list is updated.
+ */
+public class TaskListUpdateEvent extends GwtEvent<TaskListUpdateEvent.Handler> {
+
+ /**
+ * Handler for {@link TaskListUpdateEvent}.
+ */
+ public interface Handler extends EventHandler {
+
+ /**
+ * Called when the task list is updated.
+ */
+ void onTaskListUpdated(TaskListUpdateEvent event);
+ }
+
+ public static final Type<TaskListUpdateEvent.Handler> TYPE = new Type<TaskListUpdateEvent.Handler>();
+
+ private final List<TaskProxy> tasks;
+
+ public TaskListUpdateEvent(List<TaskProxy> tasks) {
+ this.tasks = tasks;
+ }
+
+ @Override
+ public Type<TaskListUpdateEvent.Handler> getAssociatedType() {
+ return TYPE;
+ }
+
+ public List<TaskProxy> getTasks() {
+ return tasks;
+ }
+
+ @Override
+ protected void dispatch(TaskListUpdateEvent.Handler handler) {
+ handler.onTaskListUpdated(this);
+ }
+}
\ No newline at end of file
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskEditView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskEditView.java
index 449e136..ee99f4a 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskEditView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskEditView.java
@@ -19,9 +19,9 @@
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
import com.google.gwt.sample.mobilewebapp.client.ui.DateButton;
import com.google.gwt.sample.mobilewebapp.client.ui.EditorDecorator;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditView;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskListView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskListView.java
index 5d7b1ce..3fe8f33 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskListView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskListView.java
@@ -1,12 +1,12 @@
/*
* Copyright 2011 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -16,8 +16,7 @@
package com.google.gwt.sample.mobilewebapp.client.mobile;
import com.google.gwt.core.client.GWT;
-import com.google.gwt.sample.mobilewebapp.client.ProvidesPresenter;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListView;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListView;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
@@ -27,7 +26,6 @@
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.NoSelectionModel;
import com.google.gwt.view.client.SelectionChangeEvent;
-import com.google.gwt.view.client.SelectionModel;
import java.util.List;
@@ -38,35 +36,27 @@
/**
* Resources used by the mobile CellList.
*/
- static interface CellListResources extends CellList.Resources {
+ interface CellListResources extends CellList.Resources {
@Source({CellList.Style.DEFAULT_CSS, "MobileCellList.css"})
CellListStyle cellListStyle();
}
-
/**
* Styles used by the mobile CellList.
*/
- static interface CellListStyle extends CellList.Style {
+ interface CellListStyle extends CellList.Style {
}
/**
* The UiBinder interface.
*/
- interface MobileTaskListViewUiBinder extends
- UiBinder<Widget, MobileTaskListView> {
+ interface MobileTaskListViewUiBinder extends UiBinder<Widget, MobileTaskListView> {
}
/**
- * Provides a new presenter for each session with this view.
- */
- private final ProvidesPresenter<TaskListView.Presenter, TaskListView> presenterFactory;
-
- /**
* The UiBinder used to generate the view.
*/
- private static MobileTaskListViewUiBinder uiBinder = GWT
- .create(MobileTaskListViewUiBinder.class);
+ private static MobileTaskListViewUiBinder uiBinder = GWT.create(MobileTaskListViewUiBinder.class);
/**
* Displays the list of tasks.
@@ -82,9 +72,8 @@
/**
* Construct a new {@link MobileTaskListView}.
*/
- public MobileTaskListView(ProvidesPresenter<TaskListView.Presenter, TaskListView> presenterFactory) {
- this.presenterFactory = presenterFactory;
-
+ public MobileTaskListView() {
+
// Create the CellList.
CellListResources cellListRes = GWT.create(CellListResources.class);
taskList = new CellList<TaskProxy>(new TaskProxyCell(), cellListRes);
@@ -97,15 +86,14 @@
*/
final NoSelectionModel<TaskProxy> selectionModel = new NoSelectionModel<TaskProxy>();
taskList.setSelectionModel(selectionModel);
- selectionModel
- .addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
- public void onSelectionChange(SelectionChangeEvent event) {
- // Edit the task.
- if (presenter != null) {
- presenter.selectTask(selectionModel.getLastSelectedObject());
- }
- }
- });
+ selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
+ public void onSelectionChange(SelectionChangeEvent event) {
+ // Edit the task.
+ if (presenter != null) {
+ presenter.selectTask(selectionModel.getLastSelectedObject());
+ }
+ }
+ });
// Initialize the widget.
initWidget(uiBinder.createAndBindUi(this));
@@ -116,24 +104,13 @@
}
public void setPresenter(Presenter presenter) {
+ if (this.presenter != null) {
+ this.presenter.stop();
+ }
this.presenter = presenter;
}
- public void setSelectionModel(SelectionModel<TaskProxy> selectionModel) {
- taskList.setSelectionModel(selectionModel);
- }
-
public void setTasks(List<TaskProxy> tasks) {
taskList.setRowData(tasks);
}
-
- @Override
- public void start() {
- setPresenter(presenterFactory.getPresenter(this));
- }
-
- @Override
- public void stop() {
- presenter.onStop();
- }
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskReadView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskReadView.java
index c901caf..695db93 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskReadView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileTaskReadView.java
@@ -19,7 +19,7 @@
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskReadView;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskReadView;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
@@ -89,7 +89,7 @@
public SimpleBeanEditorDriver<TaskProxy, ?> getEditorDriver() {
return driver;
}
-
+
public void setPresenter(Presenter presenter) {
this.presenter = presenter;
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileWebAppShellMobile.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileWebAppShellMobile.java
index 1521ba6..758e0ee 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileWebAppShellMobile.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileWebAppShellMobile.java
@@ -21,14 +21,13 @@
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.sample.mobilewebapp.client.MobileWebAppShell;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskReadView;
-import com.google.gwt.sample.mobilewebapp.client.event.GoHomeEvent;
-import com.google.gwt.sample.mobilewebapp.client.ui.OrientationHelper;
+import com.google.gwt.sample.mobilewebapp.client.event.ActionEvent;
+import com.google.gwt.sample.mobilewebapp.client.event.ActionNames;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditView;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskReadView;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListView;
+import com.google.gwt.sample.ui.client.OrientationHelper;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Command;
@@ -38,6 +37,7 @@
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.ResizeComposite;
import com.google.gwt.user.client.ui.Widget;
+import com.google.web.bindery.event.shared.EventBus;
/**
* Mobile version of the UI shell.
@@ -47,8 +47,8 @@
interface MobileWebAppShellMobileUiBinder extends UiBinder<Widget, MobileWebAppShellMobile> {
}
- private static MobileWebAppShellMobileUiBinder uiBinder =
- GWT.create(MobileWebAppShellMobileUiBinder.class);
+ private static MobileWebAppShellMobileUiBinder uiBinder = GWT
+ .create(MobileWebAppShellMobileUiBinder.class);
/**
* The width of the menu bar in landscape mode in EX.
@@ -97,11 +97,6 @@
Element titleElem;
/**
- * A reference to the handler for the add button.
- */
- private HandlerRegistration addButtonHandler;
-
- /**
* A boolean indicating that we have not yet seen the first content widget.
*/
private boolean firstContentWidget = true;
@@ -109,20 +104,27 @@
/**
* Construct a new {@link MobileWebAppShellMobile}.
*/
- public MobileWebAppShellMobile(OrientationHelper orientationHelper, TaskListView taskListView,
- TaskEditView taskEditView, TaskReadView taskReadView, final EventBus eventBus) {
+ public MobileWebAppShellMobile(final EventBus eventBus, OrientationHelper orientationHelper,
+ TaskListView taskListView, TaskEditView taskEditView, TaskReadView taskReadView) {
initWidget(uiBinder.createAndBindUi(this));
// Initialize the add button.
- setAddButtonHandler(null);
+ // Initialize the add button.
+ addButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ ActionEvent.fire(eventBus, ActionNames.ADD_TASK);
+ }
+ });
+ setAddButtonVisible(false);
/*
* Add all views to the DeckLayoutPanel so we can animate between them.
- * Using a DeckLayoutPanel here works because we only have a few views, and we
- * always know that the task views should animate in from the right side of
- * the screen. A more complex app will require more complex logic to figure
- * out which direction to animate.
+ * Using a DeckLayoutPanel here works because we only have a few views, and
+ * we always know that the task views should animate in from the right side
+ * of the screen. A more complex app will require more complex logic to
+ * figure out which direction to animate.
*/
contentContainer.add(taskListView);
contentContainer.add(taskReadView);
@@ -142,35 +144,17 @@
});
// Return to the task list when the title is clicked.
- titleBar.addDomHandler(new ClickHandler() {
+ titleBar.addDomHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
- eventBus.fireEvent(new GoHomeEvent());
+ ActionEvent.fire(eventBus, ActionNames.GO_HOME);
}
}, ClickEvent.getType());
}
- /**
- * Set the handler to invoke when the add button is pressed. If no handler is
- * specified, the button is hidden.
- *
- * @param handler the handler to add to the button, or null to hide
- */
- public void setAddButtonHandler(ClickHandler handler) {
- // Clear the old handler.
- if (addButtonHandler != null) {
- addButtonHandler.removeHandler();
- addButtonHandler = null;
- }
-
- if (handler == null) {
- // Hide the button.
- addButton.setVisible(false);
- } else {
- // Show the button and add the handler.
- addButton.setVisible(true);
- addButtonHandler = addButton.addClickHandler(handler);
- }
+ @Override
+ public void setAddButtonVisible(boolean visible) {
+ addButton.setVisible(visible);
}
/**
@@ -199,7 +183,8 @@
layoutPanel.setWidgetLeftRight(contentContainer, LANDSCAPE_MENU_WIDTH_EX, Unit.EX, 0, Unit.PX);
layoutPanel.setWidgetTopHeight(addButtonContainer, 5, Unit.PX, 4, Unit.EX);
- layoutPanel.setWidgetLeftWidth(addButtonContainer, 0, Unit.PX, LANDSCAPE_MENU_WIDTH_EX, Unit.EX);
+ layoutPanel
+ .setWidgetLeftWidth(addButtonContainer, 0, Unit.PX, LANDSCAPE_MENU_WIDTH_EX, Unit.EX);
layoutPanel.setWidgetBottomHeight(backButtonContainer, 5, Unit.PX, 4, Unit.EX);
layoutPanel.setWidgetLeftWidth(backButtonContainer, 0, Unit.PX, LANDSCAPE_MENU_WIDTH_EX,
@@ -215,7 +200,8 @@
layoutPanel.setWidgetTopBottom(contentContainer, PORTRAIT_MENU_HEIGHT_PT, Unit.PT, 0, Unit.PX);
layoutPanel.setWidgetLeftRight(contentContainer, 0, Unit.EX, 0, Unit.PX);
- layoutPanel.setWidgetTopHeight(addButtonContainer, 0, Unit.PX, PORTRAIT_MENU_HEIGHT_PT, Unit.PT);
+ layoutPanel
+ .setWidgetTopHeight(addButtonContainer, 0, Unit.PX, PORTRAIT_MENU_HEIGHT_PT, Unit.PT);
layoutPanel.setWidgetRightWidth(addButtonContainer, 8, Unit.PX, 3, Unit.EX);
layoutPanel.setWidgetTopHeight(backButtonContainer, 0, Unit.PX, PORTRAIT_MENU_HEIGHT_PT,
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/TaskProxyCell.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/TaskProxyCell.java
index c6b881c..d46aad5 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/TaskProxyCell.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/TaskProxyCell.java
@@ -30,7 +30,7 @@
/**
* A {@link com.google.gwt.cell.client.Cell} used to render a {@link TaskProxy}.
*/
-public class TaskProxyCell extends AbstractCell<TaskProxy> {
+class TaskProxyCell extends AbstractCell<TaskProxy> {
/**
* The template used by this cell.
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/MobileWebAppShellTablet.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/MobileWebAppShellTablet.java
index e98b290..49066ec 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/MobileWebAppShellTablet.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/MobileWebAppShellTablet.java
@@ -18,14 +18,13 @@
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.sample.mobilewebapp.client.ClientFactory;
import com.google.gwt.sample.mobilewebapp.client.MobileWebAppShell;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskListView;
-import com.google.gwt.sample.mobilewebapp.client.event.AddTaskEvent;
-import com.google.gwt.sample.mobilewebapp.client.event.GoHomeEvent;
-import com.google.gwt.sample.mobilewebapp.client.ui.OrientationHelper;
+import com.google.gwt.sample.mobilewebapp.client.event.ActionEvent;
+import com.google.gwt.sample.mobilewebapp.client.event.ActionNames;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListPresenter;
+import com.google.gwt.sample.mobilewebapp.presenter.tasklist.TaskListView;
+import com.google.gwt.sample.ui.client.OrientationHelper;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Command;
@@ -37,25 +36,29 @@
import com.google.gwt.user.client.ui.ResizeComposite;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
+import com.google.web.bindery.event.shared.EventBus;
/**
* Tablet version of the UI shell.
*
- * TODO(rjrjr): this thing needs a presenter. Not an activity. A presenter.
+ * TODO(rjrjr): this thing needs a presenter or two. Also, too much copy paste
+ * btw. this and the desktop version.
*/
public class MobileWebAppShellTablet extends ResizeComposite implements MobileWebAppShell {
interface MobileWebAppShellTabletUiBinder extends UiBinder<Widget, MobileWebAppShellTablet> {
}
- private static MobileWebAppShellTabletUiBinder uiBinder =
- GWT.create(MobileWebAppShellTabletUiBinder.class);
+ private static MobileWebAppShellTabletUiBinder uiBinder = GWT
+ .create(MobileWebAppShellTabletUiBinder.class);
/**
* The width of the task list in landscape mode in PCT.
*/
private static final double LANDSCAPE_TASK_LIST_WIDTH_PCT = 30.0;
+ private final ClientFactory clientFactory;
+
/**
* The button used to add items.
*/
@@ -93,30 +96,23 @@
Label titleLabel;
/**
- * A reference to the handler for the add button.
- */
- private HandlerRegistration addButtonHandler;
-
- /**
* A boolean indicating that we have not yet seen the first content widget.
*/
private boolean firstContentWidget = true;
- private final EventBus eventBus;
-
private final TaskListView taskListView;
private boolean isShowingTaskList;
+ private final EventBus eventBus;
+
/**
* Construct a new {@link MobileWebAppShellTablet}.
- *
- * @param clientFactory the {@link ClientFactory} of shared resources
*/
- public MobileWebAppShellTablet(final EventBus eventBus, OrientationHelper orientationHelper,
+ public MobileWebAppShellTablet(ClientFactory clientFactory, OrientationHelper orientationHelper,
TaskListView taskListView) {
- this.eventBus = eventBus;
-
+ this.clientFactory = clientFactory;
+ this.eventBus = clientFactory.getEventBus();
this.taskListView = taskListView;
// Inject the tablet specific styles.
@@ -127,7 +123,13 @@
initWidget(uiBinder.createAndBindUi(this));
// Initialize the add button.
- setAddButtonHandler(null);
+ addButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ ActionEvent.fire(eventBus, ActionNames.ADD_TASK);
+ }
+ });
+ setAddButtonVisible(false);
orientationHelper.setCommands(this, new Command() {
@Override
@@ -145,32 +147,14 @@
titleLabel.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
- eventBus.fireEvent(new GoHomeEvent());
+ ActionEvent.fire(eventBus, ActionNames.GO_HOME);
}
});
}
- /**
- * Set the handler to invoke when the add button is pressed. If no handler is
- * specified, the button is hidden.
- *
- * @param handler the handler to add to the button, or null to hide
- */
- public void setAddButtonHandler(ClickHandler handler) {
- // Clear the old handler.
- if (addButtonHandler != null) {
- addButtonHandler.removeHandler();
- addButtonHandler = null;
- }
-
- if (handler == null) {
- // Hide the button.
- addButton.setVisible(false);
- } else {
- // Show the button and add the handler.
- addButton.setVisible(true);
- addButtonHandler = addButton.addClickHandler(handler);
- }
+ @Override
+ public void setAddButtonVisible(boolean visible) {
+ addButton.setVisible(visible);
}
/**
@@ -183,12 +167,7 @@
// If the content is null and we are in landscape mode, show the add button.
if (content == null && isShowingTaskList) {
- setAddButtonHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- eventBus.fireEvent(new AddTaskEvent());
- }
- });
+ setAddButtonVisible(true);
}
// Do not animate the first time we show a widget.
@@ -202,12 +181,19 @@
// Show the static task list view.
splitPanel.setWidgetSize(taskListContainer, LANDSCAPE_TASK_LIST_WIDTH_PCT);
- // TODO(rjrjr) View managing activity is an abomination
if (!isShowingTaskList) {
- taskListView.start();
taskListContainer.add(taskListView);
- // DeckLayoutPanel sets the display to none, so we need to clear it.
- taskListView.asWidget().getElement().getStyle().clearDisplay();
+ TaskListPresenter taskListPresenter = new TaskListPresenter(clientFactory, false);
+
+ /*
+ * Sleaze alert: We know that TaskListPresenter doesn't add any event
+ * handlers to the bus If it did, we should have to give it a
+ * ResettableEventBus and clear it out on stop
+ */
+ taskListPresenter.start(eventBus);
+
+ // DeckLayoutPanel hides the view, so we need to show it.
+ taskListView.asWidget().setVisible(true);
isShowingTaskList = true;
}
@@ -223,8 +209,9 @@
private void onShiftToPortrait() {
// Hide the static task list view.
if (isShowingTaskList) {
- taskListView.stop();
isShowingTaskList = false;
+ // We don't stop the presenter started in onShiftToLandscape,
+ // because we know TaskListView#setPresenter will do so for us.
}
splitPanel.setWidgetSize(taskListContainer, 0);
@@ -241,7 +228,7 @@
// Ensure that something is displayed.
Widget curWidget = contentContainer.getVisibleWidget();
if (curWidget == null || curWidget == contentEmptyMessage) {
- eventBus.fireEvent(new GoHomeEvent());
+ ActionEvent.fire(eventBus, ActionNames.GO_HOME);
contentContainer.animate(0);
}
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskEditView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskEditView.java
index 025b80e..0320ef8 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskEditView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskEditView.java
@@ -19,9 +19,9 @@
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
import com.google.gwt.sample.mobilewebapp.client.ui.DateButton;
import com.google.gwt.sample.mobilewebapp.client.ui.EditorDecorator;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditView;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
@@ -35,7 +35,7 @@
import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryEditorDriver;
/**
- * View used to edit a task.
+ * Tablet version of the {@link TaskEditView}.
*/
public class TabletTaskEditView extends Composite implements TaskEditView {
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskReadView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskReadView.java
index 84ceee1..d503129 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskReadView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskReadView.java
@@ -19,8 +19,7 @@
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
-import com.google.gwt.sample.mobilewebapp.client.activity.TaskReadView;
+import com.google.gwt.sample.mobilewebapp.presenter.task.TaskReadView;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
@@ -31,7 +30,7 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * View used to edit a task.
+ * Tablet version of the {@link TaskReadView}.
*/
public class TabletTaskReadView extends Composite implements TaskReadView {
@@ -68,7 +67,8 @@
private final Driver driver = GWT.create(Driver.class);
/**
- * The {@link TaskEditView.Presenter} for this view.
+ * The {@link com.google.gwt.sample.mobilewebapp.presenter.task.TaskEditView.Presenter
+ * TaskEditView.Presenter} for this view.
*/
private Presenter presenter;
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ui/PieChart.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ui/PieChart.java
new file mode 100644
index 0000000..3eb4bc4
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/ui/PieChart.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.client.ui;
+
+import com.google.gwt.canvas.client.Canvas;
+import com.google.gwt.canvas.dom.client.Context2d;
+import com.google.gwt.canvas.dom.client.FillStrokeStyle;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.PartialSupport;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.RequiresResize;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A pie chart representation of data.
+ */
+@PartialSupport
+public class PieChart extends Composite implements RequiresResize {
+
+ /**
+ * Information about a slice of pie.
+ */
+ private static class Slice {
+ private final double weight;
+ private final FillStrokeStyle fill;
+
+ public Slice(double weight, FillStrokeStyle fill) {
+ this.weight = weight;
+ this.fill = fill;
+ }
+ }
+
+ /**
+ * The number of radians in a circle.
+ */
+ private static final double RADIANS_IN_CIRCLE = 2 * Math.PI;
+
+ /**
+ * Return a new {@link Canvas} if supported, and null otherwise.
+ *
+ * @return a new {@link Canvas} if supported, and null otherwise
+ */
+ public static PieChart createIfSupported() {
+ return isSupported() ? new PieChart() : null;
+ }
+
+ /**
+ * Runtime check for whether the canvas element is supported in this browser.
+ *
+ * @return whether the canvas element is supported
+ */
+ public static boolean isSupported() {
+ return Canvas.isSupported();
+ }
+
+ private final Canvas canvas;
+ private final List<Slice> slices = new ArrayList<Slice>();
+
+ /**
+ * Create using factory methods.
+ */
+ private PieChart() {
+ canvas = Canvas.createIfSupported();
+ canvas.setCoordinateSpaceHeight(300);
+ canvas.setCoordinateSpaceWidth(300);
+ initWidget(canvas);
+ }
+
+ /**
+ * Add a slice to the chart.
+ *
+ * @param weight the weight of the slice
+ * @param fill the fill color
+ */
+ public void addSlice(double weight, FillStrokeStyle fill) {
+ slices.add(new Slice(weight, fill));
+ }
+
+ /**
+ * Clear all slices.
+ */
+ public void clearSlices() {
+ slices.clear();
+ }
+
+ public void onResize() {
+ redraw();
+ }
+
+ /**
+ * Redraw the pie chart.
+ */
+ public void redraw() {
+ if (!isAttached()) {
+ return;
+ }
+
+ // Get the dimensions of the chart.
+ int width = canvas.getCoordinateSpaceWidth();
+ int height = canvas.getCoordinateSpaceHeight();
+ double radius = Math.min(width, height) / 2.0;
+ double cx = width / 2.0;
+ double cy = height / 2.0;
+
+ // Clear the context.
+ Context2d context = canvas.getContext2d();
+ context.clearRect(0, 0, width, height);
+
+ // Get the total weight of all slices.
+ double totalWeight = 0;
+ for (Slice slice : slices) {
+ totalWeight += slice.weight;
+ }
+
+ // Draw the slices.
+ double startAngle = -0.5 * Math.PI;
+ for (Slice slice : slices) {
+ double weight = slice.weight / totalWeight;
+ double endAngle = startAngle + (weight * RADIANS_IN_CIRCLE);
+ context.setFillStyle(slice.fill);
+ context.beginPath();
+ context.moveTo(cx, cy);
+ context.arc(cx, cy, radius, startAngle, endAngle);
+ context.fill();
+ startAngle = endAngle;
+ }
+ }
+
+ @Override
+ protected void onLoad() {
+ super.onLoad();
+ Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+ public void execute() {
+ redraw();
+ }
+ });
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskEditPresenter.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskEditPresenter.java
new file mode 100644
index 0000000..81bf42c
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskEditPresenter.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.presenter.task;
+
+import com.google.gwt.sample.mobilewebapp.client.ClientFactory;
+import com.google.gwt.sample.mobilewebapp.client.event.ActionEvent;
+import com.google.gwt.sample.mobilewebapp.client.event.ActionNames;
+import com.google.gwt.sample.mobilewebapp.client.ui.SoundEffects;
+import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+import com.google.gwt.sample.mobilewebapp.shared.TaskRequest;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.web.bindery.event.shared.EventBus;
+import com.google.web.bindery.requestfactory.shared.Receiver;
+import com.google.web.bindery.requestfactory.shared.Request;
+import com.google.web.bindery.requestfactory.shared.ServerFailure;
+
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.validation.ConstraintViolation;
+
+/**
+ * Drives a {@link TaskEditView} to fetch and edit a given task, or to create a
+ * new one.
+ */
+public class TaskEditPresenter implements TaskEditView.Presenter {
+
+ private static final Logger log = Logger.getLogger(TaskEditPresenter.class.getName());
+ private final ClientFactory clientFactory;
+
+ /**
+ * Indicates whether the activity is editing an existing task or creating a
+ * new task.
+ */
+ private boolean isEditing;
+
+ /**
+ * The current task being edited, provided by RequestFactory.
+ */
+ private TaskProxy editTask;
+
+ /**
+ * The ID of the current task being edited.
+ */
+ private final Long taskId;
+
+ /**
+ * The request used to persist the modified task.
+ */
+ private Request<Void> taskPersistRequest;
+ private EventBus eventBus;
+
+ /**
+ * For creating a new task.
+ */
+ public TaskEditPresenter(ClientFactory clientFactory) {
+ this.taskId = null;
+ this.clientFactory = clientFactory;
+ clientFactory.getTaskEditView().setPresenter(this);
+ }
+
+ /**
+ * For editing an existing task.
+ */
+ public TaskEditPresenter(ClientFactory clientFactory, TaskProxy readOnlyTask) {
+ /*
+ * TODO surely we can find a way to show the read-only values while waiting
+ * for the async fetch
+ */
+ this.taskId = readOnlyTask.getId();
+ this.clientFactory = clientFactory;
+ clientFactory.getTaskEditView().setPresenter(this);
+ }
+
+ @Override
+ public Widget asWidget() {
+ return getView().asWidget();
+ }
+
+ public void deleteTask() {
+ if (isEditing) {
+ doDeleteTask();
+ } else {
+ doCancelTask();
+ }
+ }
+
+ @Override
+ public String mayStop() {
+ if ((eventBus != null && editTask != null) && getView().getEditorDriver().isDirty()) {
+ return "Are you sure you want to discard these changes?";
+ }
+ return null;
+ }
+
+ public void saveTask() {
+ // Flush the changes into the editable task.
+ TaskRequest context = (TaskRequest) clientFactory.getTaskEditView().getEditorDriver().flush();
+
+ /*
+ * Create a persist request the first time we try to save this task. If a
+ * request already exists, reuse it.
+ */
+ if (taskPersistRequest == null) {
+ taskPersistRequest = context.persist().using(editTask);
+ }
+
+ // Fire the request.
+ taskPersistRequest.fire(new Receiver<Void>() {
+ @Override
+ public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
+ handleConstraintViolations(violations);
+ }
+
+ @Override
+ public void onSuccess(Void response) {
+ editTask = null;
+
+ // Notify the user that the task was updated.
+ TaskEditPresenter.this.notify("Task Saved");
+
+ // Return to the task list.
+ ActionEvent.fire(eventBus, ActionNames.TASK_SAVED);
+ }
+ });
+ }
+
+ public void start(EventBus eventBus) {
+ this.eventBus = eventBus;
+ getView().setNameViolation(null);
+
+ // Prefetch the sounds used in this activity.
+ SoundEffects.get().prefetchError();
+
+ // Hide the 'add' button in the shell.
+ // TODO(rjrjr) Ick!
+ clientFactory.getShell().setAddButtonVisible(false);
+
+ if (taskId == null) {
+ startCreate();
+ } else {
+ startEdit();
+ }
+ }
+
+ @Override
+ public void stop() {
+ eventBus = null;
+ clientFactory.getTaskEditView().setLocked(false);
+ }
+
+ /**
+ * Cancel the current task.
+ */
+ private void doCancelTask() {
+ ActionEvent.fire(eventBus, ActionNames.EDITING_CANCELED);
+ }
+
+ /**
+ * Delete the current task.
+ */
+ private void doDeleteTask() {
+ if (editTask == null) {
+ return;
+ }
+
+ // Delete the task in the data store.
+ final TaskProxy toDelete = this.editTask;
+ clientFactory.getRequestFactory().taskRequest().remove().using(toDelete).fire(
+ new Receiver<Void>() {
+ @Override
+ public void onFailure(ServerFailure error) {
+ Window.alert("An error occurred on the server while deleting this task: \"."
+ + error.getMessage() + "\".");
+ }
+
+ @Override
+ public void onSuccess(Void response) {
+ onTaskDeleted();
+ }
+ });
+ }
+
+ private TaskEditView getView() {
+ return clientFactory.getTaskEditView();
+ }
+
+ /**
+ * Handle constraint violations.
+ */
+ private void handleConstraintViolations(Set<ConstraintViolation<?>> violations) {
+ // Display the violations.
+ getView().getEditorDriver().setConstraintViolations(violations);
+
+ // Play a sound.
+ SoundEffects.get().playError();
+ }
+
+ /**
+ * Notify the user of a message.
+ *
+ * @param message the message to display
+ */
+ private void notify(String message) {
+ // TODO Add notification pop-up
+ log.fine("Tell the user: " + message);
+ }
+
+ /**
+ * Called when a task has been successfully deleted.
+ */
+ private void onTaskDeleted() {
+ // Notify the user that the task was deleted.
+ notify("Task Deleted");
+
+ // Return to the task list.
+ ActionEvent.fire(eventBus, ActionNames.TASK_SAVED);
+ }
+
+ private void startCreate() {
+ isEditing = false;
+ getView().setEditing(false);
+ TaskRequest request = clientFactory.getRequestFactory().taskRequest();
+ editTask = request.create(TaskProxy.class);
+ getView().getEditorDriver().edit(editTask, request);
+ }
+
+ private void startEdit() {
+ isEditing = true;
+ getView().setEditing(true);
+ // Lock the display until the task is loaded.
+ getView().setLocked(true);
+ clientFactory.getRequestFactory().taskRequest().findTask(this.taskId).fire(
+ new Receiver<TaskProxy>() {
+ @Override
+ public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
+ getView().setLocked(false);
+ getView().getEditorDriver().setConstraintViolations(violations);
+ }
+
+ @Override
+ public void onFailure(ServerFailure error) {
+ getView().setLocked(false);
+ doCancelTask();
+ super.onFailure(error);
+ }
+
+ @Override
+ public void onSuccess(TaskProxy response) {
+ // Early exit if we have already stopped.
+ if (eventBus == null) {
+ return;
+ }
+
+ // Task not found.
+ if (response == null) {
+ Window.alert("The task with id '" + taskId + "' could not be found."
+ + " Please select a different task from the task list.");
+ doCancelTask();
+ return;
+ }
+
+ // Show the task.
+ editTask = response;
+ getView().getEditorDriver().edit(response,
+ clientFactory.getRequestFactory().taskRequest());
+ getView().setLocked(false);
+ }
+ });
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskEditView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskEditView.java
similarity index 87%
rename from samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskEditView.java
rename to samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskEditView.java
index f1d4cde..859dfc8 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskEditView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskEditView.java
@@ -13,22 +13,23 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.sample.mobilewebapp.client.activity;
+package com.google.gwt.sample.mobilewebapp.presenter.task;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+import com.google.gwt.sample.ui.client.PresentsWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryEditorDriver;
/**
- * A view of {@link TaskEditActivity}.
+ * Implemented by widgets that edit tasks.
*/
-public interface TaskEditView extends IsWidget, Editor<TaskProxy> {
+public interface TaskEditView extends Editor<TaskProxy>, IsWidget {
/**
* The presenter for this view.
*/
- public static interface Presenter {
+ public interface Presenter extends PresentsWidgets {
/**
* Delete the current task or cancel the creation of a task.
*/
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskPlace.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskPlace.java
new file mode 100644
index 0000000..71d0477
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskPlace.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.presenter.task;
+
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
+import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+
+/**
+ * The place in the app that shows and edits details of a task.
+ */
+public class TaskPlace extends Place {
+
+ /**
+ * The tokenizer for this place.
+ */
+ @Prefix("edit")
+ public static class Tokenizer implements PlaceTokenizer<TaskPlace> {
+
+ private static final String NO_ID = "create";
+
+ public TaskPlace getPlace(String token) {
+ try {
+ // Parse the task ID from the URL.
+ Long taskId = Long.parseLong(token);
+ return new TaskPlace(taskId, null);
+ } catch (NumberFormatException e) {
+ // If the ID cannot be parsed, assume we are creating a task.
+ return TaskPlace.getTaskCreatePlace();
+ }
+ }
+
+ public String getToken(TaskPlace place) {
+ Long taskId = place.getTaskId();
+ return (taskId == null) ? NO_ID : taskId.toString();
+ }
+ }
+
+ /**
+ * The singleton instance of this place used for creation.
+ */
+ private static TaskPlace singleton;
+
+ /**
+ * Create an instance of {@link TaskPlace} associated with the specified task
+ * ID.
+ *
+ * @param taskId the ID of the task to edit
+ * @param task the task to edit, or null if not available
+ * @return the place
+ */
+ public static TaskPlace createTaskEditPlace(Long taskId, TaskProxy task) {
+ return new TaskPlace(taskId, task);
+ }
+
+ /**
+ * Get the singleton instance of the {@link TaskPlace} used to create a new
+ * task.
+ *
+ * @return the place
+ */
+ public static TaskPlace getTaskCreatePlace() {
+ if (singleton == null) {
+ singleton = new TaskPlace(null, null);
+ }
+ return singleton;
+ }
+
+ private final TaskProxy task;
+ private final Long taskId;
+
+ /**
+ * Construct a new {@link TaskPlace} for the specified task id.
+ *
+ * @param taskId the ID of the task to edit
+ * @param task the task to edit, or null if not available
+ */
+ private TaskPlace(Long taskId, TaskProxy task) {
+ this.taskId = taskId;
+ this.task = task;
+ }
+
+ /**
+ * Get the task to edit.
+ *
+ * @return the task to edit, or null if not available
+ */
+ public TaskProxy getTask() {
+ return task;
+ }
+
+ /**
+ * Get the ID of the task to edit.
+ *
+ * @return the ID of the task, or null if creating a new task
+ */
+ public Long getTaskId() {
+ return taskId;
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskReadPresenter.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskReadPresenter.java
new file mode 100644
index 0000000..7c6ab03
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskReadPresenter.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.presenter.task;
+
+import com.google.gwt.sample.mobilewebapp.client.ClientFactory;
+import com.google.gwt.sample.mobilewebapp.client.event.ActionEvent;
+import com.google.gwt.sample.mobilewebapp.client.event.ActionNames;
+import com.google.gwt.sample.mobilewebapp.client.event.TaskEditEvent;
+import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.web.bindery.event.shared.EventBus;
+import com.google.web.bindery.requestfactory.shared.Receiver;
+
+/**
+ * Makes a TaskReadView display a task.
+ */
+public class TaskReadPresenter implements TaskReadView.Presenter {
+
+ private final ClientFactory clientFactory;
+
+ /**
+ * A boolean indicating whether or not this activity is still active. The user
+ * might move to another activity while this one is loading, in which case we
+ * do not want to do any more work.
+ */
+ private boolean isDead = false;
+
+ /**
+ * The current task being displayed, might not be possible to edit it.
+ */
+ private TaskProxy task;
+
+ /**
+ * The ID of the current task being edited.
+ */
+ private final Long taskId;
+ private EventBus eventBus;
+
+ /**
+ * Construct a new {@link TaskReadPresenter}.
+ *
+ * @param clientFactory the {@link ClientFactory} of shared resources
+ * @param place configuration for this activity
+ */
+ public TaskReadPresenter(ClientFactory clientFactory, TaskPlace place) {
+ this.taskId = place.getTaskId();
+ this.task = place.getTask();
+ this.clientFactory = clientFactory;
+ clientFactory.getTaskReadView().setPresenter(this);
+ }
+
+ @Override
+ public Widget asWidget() {
+ return getView().asWidget();
+ }
+
+ @Override
+ public void editTask() {
+ eventBus.fireEvent(new TaskEditEvent(task));
+ }
+
+ @Override
+ public String mayStop() {
+ return null;
+ }
+
+ public void start(EventBus newEventBus) {
+ this.eventBus = newEventBus;
+
+ // Hide the 'add' button in the shell.
+ // TODO(rjrjr) Ick!
+ clientFactory.getShell().setAddButtonVisible(false);
+
+ // Try to load the task from local storage.
+ if (task == null) {
+ task = clientFactory.getTaskProxyLocalStorage().getTask(taskId);
+ }
+
+ if (task == null) {
+ // Load the existing task.
+ clientFactory.getRequestFactory().taskRequest().findTask(this.taskId).fire(
+ new Receiver<TaskProxy>() {
+ @Override
+ public void onSuccess(TaskProxy response) {
+ // Early exit if this activity has already been cancelled.
+ if (isDead) {
+ return;
+ }
+
+ // Task not found.
+ if (response == null) {
+ Window.alert("The task with id '" + taskId + "' could not be found."
+ + " Please select a different task from the task list.");
+ ActionEvent.fire(eventBus, ActionNames.EDITING_CANCELED);
+ return;
+ }
+
+ // Show the task.
+ task = response;
+ getView().getEditorDriver().edit(response);
+ }
+ });
+ } else {
+ // Use the task that was passed with the place.
+ getView().getEditorDriver().edit(task);
+ }
+ }
+
+ @Override
+ public void stop() {
+ eventBus = null;
+ // Ignore all incoming responses to the requests from this activity.
+ isDead = true;
+ }
+
+ private TaskReadView getView() {
+ return clientFactory.getTaskReadView();
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskReadView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskReadView.java
similarity index 83%
rename from samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskReadView.java
rename to samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskReadView.java
index d6c6a66..3246cf3 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskReadView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/task/TaskReadView.java
@@ -13,22 +13,23 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.sample.mobilewebapp.client.activity;
+package com.google.gwt.sample.mobilewebapp.presenter.task;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+import com.google.gwt.sample.ui.client.PresentsWidgets;
import com.google.gwt.user.client.ui.IsWidget;
/**
* A readonly view of a task.
*/
-public interface TaskReadView extends IsWidget, Editor<TaskProxy> {
+public interface TaskReadView extends Editor<TaskProxy>, IsWidget {
/**
* The presenter for this view.
*/
- public static interface Presenter {
+ public interface Presenter extends PresentsWidgets {
/**
* Switch to an edit view of this task.
*/
@@ -39,10 +40,9 @@
* Get the driver used to edit tasks in the view.
*/
SimpleBeanEditorDriver<TaskProxy, ?> getEditorDriver();
-
+
/**
* Set the {@link Presenter} for this view.
- *
* @param presenter the presenter
*/
void setPresenter(Presenter presenter);
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/taskchart/TaskChartPresenter.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/taskchart/TaskChartPresenter.java
new file mode 100644
index 0000000..6692092
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/taskchart/TaskChartPresenter.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.presenter.taskchart;
+
+import com.google.gwt.canvas.dom.client.CssColor;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.sample.mobilewebapp.client.event.TaskListUpdateEvent;
+import com.google.gwt.sample.mobilewebapp.client.ui.PieChart;
+import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+import com.google.gwt.sample.ui.client.PresentsWidgets;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.web.bindery.event.shared.EventBus;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Drives a {@link PieChart} to summarize a set of tasks.
+ */
+public class TaskChartPresenter implements PresentsWidgets {
+
+ /**
+ * A pie chart showing a snapshot of the tasks.
+ */
+ private final PieChart pieChart;
+
+ /**
+ * Construct a new {@link TaskChartPresenter}.
+ *
+ * @param pieChart the {@link PieChart}
+ */
+ public TaskChartPresenter(PieChart pieChart) {
+ this.pieChart = pieChart;
+ }
+
+ public Widget asWidget() {
+ return pieChart;
+ }
+
+ @Override
+ public String mayStop() {
+ return null;
+ }
+
+ public void start(EventBus eventBus) {
+ pieChart.setWidth("90%");
+ pieChart.setHeight("90%");
+ pieChart.getElement().getStyle().setMarginLeft(5.0, Unit.PCT);
+ pieChart.getElement().getStyle().setMarginTop(5.0, Unit.PCT);
+
+ // Listen for events from the task list activity.
+ eventBus.addHandler(TaskListUpdateEvent.TYPE, new TaskListUpdateEvent.Handler() {
+ public void onTaskListUpdated(TaskListUpdateEvent event) {
+ updatePieChart(event.getTasks());
+ }
+ });
+ }
+
+ @Override
+ public void stop() {
+ }
+
+ /**
+ * Update the pie chart with the list of tasks.
+ *
+ * @param tasks the list of tasks
+ */
+ @SuppressWarnings("deprecation")
+ private void updatePieChart(List<TaskProxy> tasks) {
+ if (pieChart == null) {
+ return;
+ }
+
+ // Calculate the slices based on the due date.
+ double pastDue = 0;
+ double dueSoon = 0;
+ double onTime = 0;
+ double noDate = 0;
+ final Date now = new Date();
+ final Date tomorrow = new Date(now.getYear(), now.getMonth(), now.getDate() + 1, 23, 59, 59);
+ for (TaskProxy task : tasks) {
+ Date dueDate = task.getDueDate();
+ if (dueDate == null) {
+ noDate++;
+ } else if (dueDate.before(now)) {
+ pastDue++;
+ } else if (dueDate.before(tomorrow)) {
+ dueSoon++;
+ } else {
+ onTime++;
+ }
+ }
+
+ // Update the pie chart.
+ pieChart.clearSlices();
+ if (pastDue > 0) {
+ pieChart.addSlice(pastDue, CssColor.make(255, 100, 100));
+ }
+ if (dueSoon > 0) {
+ pieChart.addSlice(dueSoon, CssColor.make(255, 200, 100));
+ }
+ if (onTime > 0) {
+ pieChart.addSlice(onTime, CssColor.make(100, 255, 100));
+ }
+ if (noDate > 0) {
+ pieChart.addSlice(noDate, CssColor.make(200, 200, 200));
+ }
+ pieChart.redraw();
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/tasklist/TaskListPlace.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/tasklist/TaskListPlace.java
new file mode 100644
index 0000000..6f1616e
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/tasklist/TaskListPlace.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.presenter.tasklist;
+
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
+
+/**
+ * The place in the app that shows a list of tasks.
+ */
+public class TaskListPlace extends Place {
+
+ /**
+ * The tokenizer for this place. TaskList doesn't have any state, so we don't
+ * have anything to encode.
+ */
+ @Prefix("tl")
+ public static class Tokenizer implements PlaceTokenizer<TaskListPlace> {
+
+ public TaskListPlace getPlace(String token) {
+ return new TaskListPlace(true);
+ }
+
+ public String getToken(TaskListPlace place) {
+ return "";
+ }
+ }
+
+ private final boolean taskListStale;
+
+ /**
+ * Construct a new {@link TaskListPlace}.
+ *
+ * @param taskListStale true if the task list is stale and should be cleared
+ */
+ public TaskListPlace(boolean taskListStale) {
+ this.taskListStale = taskListStale;
+ }
+
+ /**
+ * Check if the task list is stale and should be cleared.
+ *
+ * @return true if stale, false if not
+ */
+ public boolean isTaskListStale() {
+ return taskListStale;
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/tasklist/TaskListPresenter.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/tasklist/TaskListPresenter.java
new file mode 100644
index 0000000..f47e779
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/tasklist/TaskListPresenter.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.mobilewebapp.presenter.tasklist;
+
+import com.google.gwt.sample.mobilewebapp.client.ClientFactory;
+import com.google.gwt.sample.mobilewebapp.client.event.ShowTaskEvent;
+import com.google.gwt.sample.mobilewebapp.client.event.TaskListUpdateEvent;
+import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.web.bindery.event.shared.EventBus;
+import com.google.web.bindery.requestfactory.shared.Receiver;
+import com.google.web.bindery.requestfactory.shared.ServerFailure;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Activity that presents a list of tasks.
+ */
+public class TaskListPresenter implements TaskListView.Presenter {
+
+ /**
+ * The delay in milliseconds between calls to refresh the task list.
+ */
+ private static final int REFRESH_DELAY = 5000;
+
+ /**
+ * A boolean indicating that we should clear the task list when started.
+ */
+ private final boolean clearTaskList;
+
+ private final ClientFactory clientFactory;
+
+ private EventBus eventBus;
+
+ /**
+ * The refresh timer used to periodically refresh the task list.
+ */
+ private Timer refreshTimer;
+
+ public TaskListPresenter(ClientFactory clientFactory, boolean clearTaskList) {
+ this.clientFactory = clientFactory;
+ this.clearTaskList = clearTaskList;
+ clientFactory.getTaskListView().setPresenter(this);
+ }
+
+ /**
+ * Construct a new {@link TaskListPresenter}.
+ *
+ * @param clientFactory the {@link ClientFactory} of shared resources
+ * @param place configuration for this activity
+ */
+ public TaskListPresenter(ClientFactory clientFactory, TaskListPlace place) {
+ this(clientFactory, place.isTaskListStale());
+ }
+
+ @Override
+ public Widget asWidget() {
+ return getView().asWidget();
+ }
+
+ @Override
+ public String mayStop() {
+ return null; // always happy to stop
+ }
+
+ public void selectTask(TaskProxy selected) {
+ // Go into edit mode when a task is selected.
+ eventBus.fireEvent(new ShowTaskEvent(selected));
+ }
+
+ @Override
+ public void start(EventBus eventBus) {
+ this.eventBus = eventBus;
+ // Add a handler to the 'add' button in the shell.
+ clientFactory.getShell().setAddButtonVisible(true);
+
+ // Clear the task list and display it.
+ if (clearTaskList) {
+ getView().clearList();
+ }
+
+ // Create a timer to periodically refresh the task list.
+ refreshTimer = new Timer() {
+ @Override
+ public void run() {
+ refreshTaskList();
+ }
+ };
+
+ // Load the saved task list from storage
+ List<TaskProxy> list = clientFactory.getTaskProxyLocalStorage().getTasks();
+ setTasks(list);
+
+ // Request the task list now.
+ refreshTaskList();
+ }
+
+ @Override
+ public void stop() {
+ eventBus = null;
+
+ // Kill the refresh timer.
+ if (refreshTimer != null) {
+ refreshTimer.cancel();
+ }
+ }
+
+ private TaskListView getView() {
+ return clientFactory.getTaskListView();
+ }
+
+ /**
+ * Refresh the task list.
+ */
+ private void refreshTaskList() {
+ clientFactory.getRequestFactory().taskRequest().findAllTasks().fire(
+ new Receiver<List<TaskProxy>>() {
+ @Override
+ public void onFailure(ServerFailure error) {
+ // ignore
+ }
+
+ @Override
+ public void onSuccess(List<TaskProxy> response) {
+ // Early exit if this activity has already been canceled.
+ if (eventBus == null) {
+ return;
+ }
+
+ // Display the tasks in the view.
+ if (response == null) {
+ response = Collections.<TaskProxy> emptyList();
+ }
+ setTasks(response);
+
+ // save the response to storage
+ clientFactory.getTaskProxyLocalStorage().setTasks(response);
+
+ // Restart the timer.
+ refreshTimer.schedule(REFRESH_DELAY);
+ }
+ });
+ }
+
+ /**
+ * Set the list of tasks.
+ */
+ private void setTasks(List<TaskProxy> tasks) {
+ getView().setTasks(tasks);
+ eventBus.fireEventFromSource(new TaskListUpdateEvent(tasks), this);
+ }
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskListView.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/tasklist/TaskListView.java
similarity index 72%
rename from samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskListView.java
rename to samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/tasklist/TaskListView.java
index 90faccb..6a16da5 100644
--- a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/activity/TaskListView.java
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/presenter/tasklist/TaskListView.java
@@ -1,40 +1,35 @@
/*
* Copyright 2011 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.sample.mobilewebapp.client.activity;
+package com.google.gwt.sample.mobilewebapp.presenter.tasklist;
-import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+import com.google.gwt.sample.ui.client.PresentsWidgets;
+import com.google.gwt.user.client.ui.IsWidget;
import java.util.List;
/**
- * A view of a {@link TaskListActivity}.
+ * Implemented by views that display a list of tasks.
*/
public interface TaskListView extends IsWidget {
/**
* The presenter for this view.
*/
- public static interface Presenter {
-
- /**
- * View was told to stop. Don't really expect to submit this.
- */
- void onStop();
-
+ public interface Presenter extends PresentsWidgets {
/**
* Select a task.
*
@@ -49,9 +44,8 @@
void clearList();
/**
- * Set the {@link Presenter} for this view.
- *
- * @param presenter the presenter
+ * Sets the new presenter, and calls {@link Presenter#stop()} on the previous
+ * one.
*/
void setPresenter(Presenter presenter);
@@ -61,14 +55,4 @@
* @param tasks the list of tasks
*/
void setTasks(List<TaskProxy> tasks);
-
- /**
- * Start a new session of this view.
- */
- void start();
-
- /**
- * Stop it!
- */
- void stop();
}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/UI.gwt.xml b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/UI.gwt.xml
new file mode 100644
index 0000000..b2ede8b
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/UI.gwt.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright 2011 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy of
+ the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ License for the specific language governing permissions and limitations under
+ the License.
+-->
+
+<!-- Candidates for addition to com.google.gwt.user.client.ui -->
+<module>
+ <inherits name="com.google.gwt.user.User" />
+ <source path="client"/>
+</module>
\ No newline at end of file
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/client/OrientationHelper.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/client/OrientationHelper.java
new file mode 100644
index 0000000..8fd05dc
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/client/OrientationHelper.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.ui.client;
+
+import com.google.gwt.event.logical.shared.HasAttachHandlers;
+import com.google.gwt.user.client.Command;
+import com.google.web.bindery.event.shared.HandlerRegistration;
+
+/**
+ * Accepts {@link Command}s to be run when the browser window or device's
+ * orientation changes. Commands operate only while the associated widget is
+ * attached.
+ * TODO(rjrjr) just use the event bus
+ */
+public interface OrientationHelper {
+ /**
+ * Gives efficient on demand access to the orientation of the window or
+ * device.
+ *
+ * @return true for portrait, false for landscape
+ */
+ boolean isPortrait();
+
+ /**
+ * Set commands to run on orientation change, one for portrait and one for
+ * landscape. The appropriate command is fired immediately if this method is
+ * called while the widget is attached.
+ * <p>
+ * Commands are also fired each time the widget is attached. If that is not
+ * desired a widget should call {@link HandlerRegistration#removeHandler()} on
+ * the returned object when it detaches.
+ *
+ * @param widget the widget to help
+ * @param forPortrait command to run when on shift to portrait
+ * @param forLandscape command to run when on shift to landscape
+ * @return registration object to be used to stop and dereference the commands
+ */
+ HandlerRegistration setCommands(HasAttachHandlers widget, Command forPortrait,
+ Command forLandscape);
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/client/PresentsWidgets.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/client/PresentsWidgets.java
new file mode 100644
index 0000000..cc47f8c
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/client/PresentsWidgets.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.ui.client;
+
+import com.google.gwt.user.client.ui.IsWidget;
+import com.google.web.bindery.event.shared.EventBus;
+
+/**
+ * Implemented by specialized widget drivers that can answer
+ * {@link com.google.gwt.activity.shared.Activity#mayStop() mayStop()} calls for
+ * {@link com.google.gwt.activity.shared.Activity Activities}.
+ * <p>
+ * Note that this interface extends {@link IsWidget}. This is to make it easier
+ * to evolve app code in MVP directions piecemeal, just where it is useful. If
+ * code that assembles widgets thinks of them strictly as IsWidget instances, it
+ * doesn't need to notice as they get refactored in to Presenter / View pairs.
+ * Or as they don't.
+ */
+public interface PresentsWidgets extends IsWidget {
+ /**
+ * Called (probably from
+ * {@link com.google.gwt.activity.shared.Activity#mayStop Activity.mayStop})
+ * to see if it's safe to stop this presenter.
+ *
+ * @return null if it's okay to stop, else a message to ask the user if she's
+ * sure
+ */
+ String mayStop();
+
+ void start(EventBus eventBus);
+
+ void stop();
+}
diff --git a/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/client/WindowBasedOrientationHelper.java b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/client/WindowBasedOrientationHelper.java
new file mode 100644
index 0000000..d388384
--- /dev/null
+++ b/samples/mobilewebapp/src/main/java/com/google/gwt/sample/ui/client/WindowBasedOrientationHelper.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.sample.ui.client;
+
+import com.google.gwt.event.logical.shared.AttachEvent;
+import com.google.gwt.event.logical.shared.HasAttachHandlers;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.logical.shared.ResizeHandler;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.Window;
+import com.google.web.bindery.event.shared.HandlerRegistration;
+
+import java.util.HashSet;
+
+/**
+ * OrientationHelper implementation that works by by monitoring window size
+ * changes, and so works on both mobile devices and desktop browsers.
+ * <p>
+ * Expected to be used as an app-wide singleton.
+ */
+public class WindowBasedOrientationHelper implements OrientationHelper {
+ private class CommandSet implements AttachEvent.Handler, HandlerRegistration {
+ final Command portraitCommand;
+ final Command landscapeCommand;
+ final HandlerRegistration attachEventReg;
+
+ boolean active;
+
+ CommandSet(HasAttachHandlers widget, Command portrait, Command landscape) {
+ this.portraitCommand = portrait;
+ this.landscapeCommand = landscape;
+
+ attachEventReg = widget.addAttachHandler(this);
+ active = widget.isAttached();
+ }
+
+ @Override
+ public void onAttachOrDetach(AttachEvent event) {
+ active = event.isAttached();
+ fire();
+ }
+
+ @Override
+ public void removeHandler() {
+ commandSets.remove(this);
+ attachEventReg.removeHandler();
+ }
+
+ void fire() {
+ if (active) {
+ if (isPortrait) {
+ portraitCommand.execute();
+ } else {
+ landscapeCommand.execute();
+ }
+ }
+ }
+ }
+
+ private static boolean calculateIsPortrait() {
+ return Window.getClientHeight() > Window.getClientWidth();
+ }
+
+ private boolean isPortrait;
+ private HandlerRegistration windowResizeReg;
+ private HashSet<CommandSet> commandSets = new HashSet<CommandSet>();
+
+ public WindowBasedOrientationHelper() {
+ isPortrait = calculateIsPortrait();
+ windowResizeReg = Window.addResizeHandler(new ResizeHandler() {
+ public void onResize(ResizeEvent event) {
+ update();
+ }
+ });
+ }
+
+ @Override
+ public boolean isPortrait() {
+ assertLive();
+ return isPortrait;
+ }
+
+ @Override
+ public HandlerRegistration setCommands(HasAttachHandlers widget, Command forPortrait,
+ Command forLandscape) {
+ assertLive();
+ CommandSet commandSet = new CommandSet(widget, forPortrait, forLandscape);
+ commandSets.add(commandSet);
+ commandSet.fire();
+ return commandSet;
+ }
+
+ public void stop() {
+ assertLive();
+ windowResizeReg.removeHandler();
+ windowResizeReg = null;
+
+ for (CommandSet commandSet : commandSets) {
+ commandSet.attachEventReg.removeHandler();
+ }
+ commandSets = null;
+ }
+
+ private void assertLive() {
+ assert windowResizeReg != null : "Cannot do this after stop() is called";
+ }
+
+ private void update() {
+ boolean was = isPortrait;
+ isPortrait = calculateIsPortrait();
+ if (was != isPortrait) {
+ for (CommandSet helper : commandSets) {
+ helper.fire();
+ }
+ }
+ }
+}
diff --git a/samples/mobilewebapp/src/test/java/com/google/gwt/sample/core/linker/SimpleAppCacheLinkerTest.java b/samples/mobilewebapp/src/test/java/com/google/gwt/sample/core/linker/SimpleAppCacheLinkerTest.java
index a64ee40..0c029ed 100644
--- a/samples/mobilewebapp/src/test/java/com/google/gwt/sample/core/linker/SimpleAppCacheLinkerTest.java
+++ b/samples/mobilewebapp/src/test/java/com/google/gwt/sample/core/linker/SimpleAppCacheLinkerTest.java
@@ -1,5 +1,18 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
package com.google.gwt.sample.core.linker;
import com.google.gwt.core.ext.LinkerContext;
@@ -10,7 +23,6 @@
import com.google.gwt.core.ext.linker.SelectionProperty;
import com.google.gwt.core.ext.linker.SyntheticArtifact;
import com.google.gwt.core.ext.linker.impl.SelectionInformation;
-import com.google.gwt.sample.core.linker.SimpleAppCacheLinker;
import junit.framework.TestCase;
@@ -21,131 +33,20 @@
import java.util.TreeSet;
/**
- * Tests {@link SimpleAppCacheLinker}
+ * Tests {@link SimpleAppCacheLinker}.
*/
public class SimpleAppCacheLinkerTest extends TestCase {
- private ArtifactSet artifacts;
- private TreeLogger logger;
-
- @Override
- public void setUp() {
- artifacts = new ArtifactSet();
- artifacts.add(new SelectionInformation("foo", 0, new TreeMap<String, String>()));
- logger = TreeLogger.NULL;
- }
-
- public void testAddCachableArtifacts() throws UnableToCompleteException {
- SimpleAppCacheLinker linker = new SimpleAppCacheLinker();
-
- // Some cacheable artifact
- artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.bar", new byte[0]));
-
- ArtifactSet result = linker.link(logger, new MockLinkerContext(), artifacts, false);
-
- assertEquals(3, result.size());
- assertHasOneManifest(result);
- assertTrue(getManifestContents(result).contains("foo.bar"));
- }
-
- public void testNoNonCachableArtifacts() throws UnableToCompleteException {
- SimpleAppCacheLinker linker = new SimpleAppCacheLinker();
-
- // Some non-cacheable artifacts
- artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.symbolMap", new byte[0]));
- artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.xml.gz", new byte[0]));
- artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.rpc.log", new byte[0]));
- artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.gwt.rpc", new byte[0]));
- artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "rpcPolicyManifest.bar", new byte[0]));
-
- ArtifactSet result = linker.link(TreeLogger.NULL, new MockLinkerContext(), artifacts, false);
-
- assertEquals(7, result.size());
- assertHasOneManifest(result);
- assertFalse(getManifestContents(result).contains("symbolMap"));
- assertFalse(getManifestContents(result).contains("xml.gz"));
- assertFalse(getManifestContents(result).contains("rpc.log"));
- assertFalse(getManifestContents(result).contains("gwt.rpc"));
- assertFalse(getManifestContents(result).contains("rpcPolicyManifest"));
- }
-
- public void testAddStaticFiles() throws UnableToCompleteException {
- SimpleAppCacheLinker linker = new OneStaticFileAppCacheLinker();
-
- ArtifactSet result = linker.link(logger, new MockLinkerContext(), artifacts, false);
-
- assertEquals(2, result.size());
- assertHasOneManifest(result);
- assertTrue(getManifestContents(result).contains("aStaticFile"));
- }
-
- public void testEmptyManifestDevMode() throws UnableToCompleteException {
- // No SelectionInformation artifact
- artifacts = new ArtifactSet();
-
- SimpleAppCacheLinker linker = new SimpleAppCacheLinker();
-
- // Some cacheable artifact
- artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.bar", new byte[0]));
-
- ArtifactSet result = linker.link(logger, new MockLinkerContext(), artifacts, false);
-
- assertHasOneManifest(result);
- assertFalse(getManifestContents(result).contains("foo.bar"));
- }
-
- public void testManifestOnlyOnLastPass() throws UnableToCompleteException {
- SimpleAppCacheLinker linker = new SimpleAppCacheLinker();
-
- ArtifactSet result = linker.link(logger, new MockLinkerContext(), artifacts, true);
-
- assertEquals(artifacts, result);
-
- result = linker.link(logger, new MockLinkerContext(), artifacts, false);
-
- assertEquals(2, result.size());
- assertHasOneManifest(result);
- }
-
- private void assertHasOneManifest(ArtifactSet artifacts) {
- int manifestCount = 0;
- for (SyntheticArtifact artifact : artifacts.find(SyntheticArtifact.class)) {
- if ("appcache.nocache.manifest".equals(artifact.getPartialPath())) {
- assertEquals("appcache.nocache.manifest", artifact.getPartialPath());
- manifestCount++;
- }
- }
- assertEquals(1, manifestCount);
- }
-
- private SyntheticArtifact getManifest(ArtifactSet artifacts) {
- for (SyntheticArtifact artifact : artifacts.find(SyntheticArtifact.class)) {
- if ("appcache.nocache.manifest".equals(artifact.getPartialPath())) {
- assertEquals("appcache.nocache.manifest", artifact.getPartialPath());
- return artifact;
- }
- }
- fail("Manifest not found");
- return null;
- }
-
- private String getManifestContents(ArtifactSet artifacts) throws UnableToCompleteException {
- return getArtifactContents(getManifest(artifacts));
- }
-
- private String getArtifactContents(SyntheticArtifact artifact) throws UnableToCompleteException {
- InputStream is = artifact.getContents(logger);
- String contents = new Scanner(is).useDelimiter("\\A").next();
- return contents;
- }
-
+ /**
+ * A {@code SimpleAppCacheLinker} mocking the addition of a static entry.
+ */
public static class OneStaticFileAppCacheLinker extends SimpleAppCacheLinker {
-
+
@Override
protected String[] otherCachedFiles() {
return new String[] {"aStaticFile"};
}
}
-
+
private static class MockLinkerContext implements LinkerContext {
public SortedSet<ConfigurationProperty> getConfigurationProperties() {
@@ -176,4 +77,119 @@
return jsProgram;
}
}
+
+ private ArtifactSet artifacts;
+
+ private TreeLogger logger;
+
+ @Override
+ public void setUp() {
+ artifacts = new ArtifactSet();
+ artifacts.add(new SelectionInformation("foo", 0, new TreeMap<String, String>()));
+ logger = TreeLogger.NULL;
+ }
+
+ public void testAddCachableArtifacts() throws UnableToCompleteException {
+ SimpleAppCacheLinker linker = new SimpleAppCacheLinker();
+
+ // Some cacheable artifact
+ artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.bar", new byte[0]));
+
+ ArtifactSet result = linker.link(logger, new MockLinkerContext(), artifacts, false);
+
+ assertEquals(3, result.size());
+ assertHasOneManifest(result);
+ assertTrue(getManifestContents(result).contains("foo.bar"));
+ }
+
+ public void testAddStaticFiles() throws UnableToCompleteException {
+ SimpleAppCacheLinker linker = new OneStaticFileAppCacheLinker();
+
+ ArtifactSet result = linker.link(logger, new MockLinkerContext(), artifacts, false);
+
+ assertEquals(2, result.size());
+ assertHasOneManifest(result);
+ assertTrue(getManifestContents(result).contains("aStaticFile"));
+ }
+
+ public void testEmptyManifestDevMode() throws UnableToCompleteException {
+ // No SelectionInformation artifact
+ artifacts = new ArtifactSet();
+
+ SimpleAppCacheLinker linker = new SimpleAppCacheLinker();
+
+ // Some cacheable artifact
+ artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.bar", new byte[0]));
+
+ ArtifactSet result = linker.link(logger, new MockLinkerContext(), artifacts, false);
+
+ assertHasOneManifest(result);
+ assertFalse(getManifestContents(result).contains("foo.bar"));
+ }
+
+ public void testManifestOnlyOnLastPass() throws UnableToCompleteException {
+ SimpleAppCacheLinker linker = new SimpleAppCacheLinker();
+
+ ArtifactSet result = linker.link(logger, new MockLinkerContext(), artifacts, true);
+
+ assertEquals(artifacts, result);
+
+ result = linker.link(logger, new MockLinkerContext(), artifacts, false);
+
+ assertEquals(2, result.size());
+ assertHasOneManifest(result);
+ }
+
+ public void testNoNonCachableArtifacts() throws UnableToCompleteException {
+ SimpleAppCacheLinker linker = new SimpleAppCacheLinker();
+
+ // Some non-cacheable artifacts
+ artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.symbolMap", new byte[0]));
+ artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.xml.gz", new byte[0]));
+ artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.rpc.log", new byte[0]));
+ artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "foo.gwt.rpc", new byte[0]));
+ artifacts.add(new SyntheticArtifact(SimpleAppCacheLinker.class, "rpcPolicyManifest.bar", new byte[0]));
+
+ ArtifactSet result = linker.link(TreeLogger.NULL, new MockLinkerContext(), artifacts, false);
+
+ assertEquals(7, result.size());
+ assertHasOneManifest(result);
+ assertFalse(getManifestContents(result).contains("symbolMap"));
+ assertFalse(getManifestContents(result).contains("xml.gz"));
+ assertFalse(getManifestContents(result).contains("rpc.log"));
+ assertFalse(getManifestContents(result).contains("gwt.rpc"));
+ assertFalse(getManifestContents(result).contains("rpcPolicyManifest"));
+ }
+
+ private void assertHasOneManifest(ArtifactSet artifacts) {
+ int manifestCount = 0;
+ for (SyntheticArtifact artifact : artifacts.find(SyntheticArtifact.class)) {
+ if ("appcache.nocache.manifest".equals(artifact.getPartialPath())) {
+ assertEquals("appcache.nocache.manifest", artifact.getPartialPath());
+ manifestCount++;
+ }
+ }
+ assertEquals(1, manifestCount);
+ }
+
+ private String getArtifactContents(SyntheticArtifact artifact) throws UnableToCompleteException {
+ InputStream is = artifact.getContents(logger);
+ String contents = new Scanner(is).useDelimiter("\\A").next();
+ return contents;
+ }
+
+ private SyntheticArtifact getManifest(ArtifactSet artifacts) {
+ for (SyntheticArtifact artifact : artifacts.find(SyntheticArtifact.class)) {
+ if ("appcache.nocache.manifest".equals(artifact.getPartialPath())) {
+ assertEquals("appcache.nocache.manifest", artifact.getPartialPath());
+ return artifact;
+ }
+ }
+ fail("Manifest not found");
+ return null;
+ }
+
+ private String getManifestContents(ArtifactSet artifacts) throws UnableToCompleteException {
+ return getArtifactContents(getManifest(artifacts));
+ }
}
diff --git a/tools/scripts/maven_script.sh b/tools/scripts/maven_script.sh
index a7770f2..2439582 100755
--- a/tools/scripts/maven_script.sh
+++ b/tools/scripts/maven_script.sh
@@ -15,7 +15,7 @@
# the License.
MAVEN_REPO=${MAVEN_REPO:-"~/.m2/repository"}
-GWT_VERSION=${GWT_VERSION:-"2.3.0"}
+GWT_VERSION=${GWT_VERSION:-"2.4.0"}
GWT_DIR=${GWT_DIR:-"build/lib"}
echo "Pushing GWT jars from ${GWT_DIR} into local maven repo with version ${GWT_VERSION}."