Introduces read only task view with an edit button.  Gets around
problems when we try to edit a TaskProxyImpl, which is unpossible.


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10165 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactory.java b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactory.java
index e9d6ba0..913ed2d 100644
--- a/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactory.java
+++ b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactory.java
@@ -17,9 +17,10 @@
 
 import com.google.gwt.event.shared.EventBus;
 import com.google.gwt.place.shared.PlaceController;
-import com.google.gwt.storage.client.Storage;
 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;
 
 /**
  * The factory responsible for instantiating everything interesting in this
@@ -84,6 +85,11 @@
   TaskListView getTaskListView();
 
   /**
+   * Get an implementation of {@link TaskEditView}.
+   */
+  TaskReadView getTaskReadView();
+
+  /**
    * Must be called before any get methods.
    */
   void init();
diff --git a/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java
index 9b12eeb..5809ccb 100644
--- a/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java
+++ b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java
@@ -22,16 +22,18 @@
 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.mobilewebapp.client.activity.AppActivityMapper;
 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.desktop.DesktopTaskEditView;
 import com.google.gwt.sample.mobilewebapp.client.desktop.DesktopTaskListView;
 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.tablet.TabletTaskReadView;
 import com.google.gwt.storage.client.Storage;
 import com.google.gwt.user.client.Window;
 import com.google.web.bindery.requestfactory.shared.RequestTransport;
@@ -63,6 +65,8 @@
    */
   private final PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper);
 
+  private TaskReadView taskReadView;
+
   public ClientFactoryImpl() {
     RequestTransport requestTransport = new GaeAuthRequestTransport(eventBus);
     requestFactory = GWT.create(MobileWebAppRequestFactory.class);
@@ -89,12 +93,7 @@
      */
     activityManager = new ActivityManager(activityMapper, eventBus);
   }
-  
-  public void init() {
-    activityManager.setDisplay(getShell());
-  }
 
-  @Override
   public App getApp() {
     return new App(getLocalStorageIfSupported(), getEventBus(), getPlaceController(),
         historyMapper, historyHandler, new ReloadOnAuthenticationFailure(), getShell());
@@ -137,6 +136,17 @@
     return taskListView;
   }
 
+  public TaskReadView getTaskReadView() {
+    if (taskReadView == null) {
+      taskReadView = createTaskReadView();
+    }
+    return taskReadView;
+  }
+
+  public void init() {
+    activityManager.setDisplay(getShell());
+  }
+
   /**
    * Create the application UI shell.
    * 
@@ -193,4 +203,8 @@
       }
     };
   }
+
+  private TaskReadView createTaskReadView() {
+    return new TabletTaskReadView();
+  }
 }
diff --git a/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/activity/TaskEditActivity.java b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/activity/TaskEditActivity.java
index d7a5ba5..470c85a 100644
--- a/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/activity/TaskEditActivity.java
+++ b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/activity/TaskEditActivity.java
@@ -37,7 +37,8 @@
 /**
  * Activity that presents a task to be edited.
  */
-public class TaskEditActivity extends AbstractActivity implements TaskEditView.Presenter {
+public class TaskEditActivity extends AbstractActivity implements TaskEditView.Presenter,
+    TaskReadView.Presenter {
 
   private static final Logger log = Logger.getLogger(TaskEditActivity.class.getName());
   private final ClientFactory clientFactory;
@@ -56,9 +57,14 @@
   private boolean isEditing;
 
   /**
-   * The current task being edited.
+   * The current task being displayed, might not be possible to edit it.
    */
-  private TaskProxy task;
+  private TaskProxy readOnlyTask;
+
+  /**
+   * The current task being edited, provided by RequestFactory.
+   */
+  private TaskProxy editTask;
 
   /**
    * The ID of the current task being edited.
@@ -69,15 +75,17 @@
    * 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.task = place.getTask();
+    this.readOnlyTask = place.getTask();
     this.clientFactory = clientFactory;
   }
 
@@ -112,7 +120,7 @@
      * request already exists, reuse it.
      */
     if (taskPersistRequest == null) {
-      taskPersistRequest = context.persist().using(task);
+      taskPersistRequest = context.persist().using(editTask);
     }
 
     // Fire the request.
@@ -141,32 +149,31 @@
   }
 
   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 view.
-    final TaskEditView view = clientFactory.getTaskEditView();
-    view.setPresenter(this);
-    view.setNameViolation(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) {
-      // Create a new task.
-      isEditing = false;
-      view.setEditing(false);
-      TaskRequest request = clientFactory.getRequestFactory().taskRequest();
-      task = request.create(TaskProxy.class);
-      view.getEditorDriver().edit(task, request);
+      editTask();
+      return;
     } else {
       // Lock the display until the task is loaded.
       isEditing = true;
-      view.setEditing(true);
+      editView.setEditing(true);
 
-      if (task == null) {
+      if (readOnlyTask == null) {
         // Load the existing task.
-        view.setLocked(true);
         clientFactory.getRequestFactory().taskRequest().findTask(this.taskId).fire(
             new Receiver<TaskProxy>() {
               @Override
@@ -192,20 +199,18 @@
                 }
 
                 // Show the task.
-                task = response;
-                view.getEditorDriver().edit(response,
-                    clientFactory.getRequestFactory().taskRequest());
-                view.setLocked(false);
+                readOnlyTask = response;
+                readView.getEditorDriver().edit(response);
               }
             });
       } else {
         // Use the task that was passed with the place.
-        view.getEditorDriver().edit(task, clientFactory.getRequestFactory().taskRequest());
+        readView.getEditorDriver().edit(readOnlyTask);
       }
     }
 
     // Display the view.
-    container.setWidget(view.asWidget());
+    container.setWidget(readView);
   }
 
   /**
@@ -219,12 +224,12 @@
    * Delete the current task.
    */
   private void doDeleteTask() {
-    if (task == null) {
+    if (editTask == null) {
       return;
     }
 
     // Delete the task in the data store.
-    final TaskProxy toDelete = this.task;
+    final TaskProxy toDelete = this.editTask;
     clientFactory.getRequestFactory().taskRequest().remove().using(toDelete).fire(
         new Receiver<Void>() {
           @Override
@@ -271,4 +276,52 @@
     // Return to the task list.
     clientFactory.getPlaceController().goTo(new TaskListPlace(true));
   }
+
+  @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 onFailure(ServerFailure error) {
+              Window.alert("An error occurred on the server while loading this task."
+                  + " Please select a different task from the task list.");
+              doCancelTask();
+            }
+
+            @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);
+  }
 }
diff --git a/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/activity/TaskReadView.java b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/activity/TaskReadView.java
new file mode 100644
index 0000000..2553774
--- /dev/null
+++ b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/activity/TaskReadView.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.editor.client.Editor;
+import com.google.gwt.editor.client.SimpleBeanEditorDriver;
+import com.google.gwt.sample.mobilewebapp.shared.TaskProxy;
+import com.google.gwt.user.client.ui.IsWidget;
+
+public interface TaskReadView extends IsWidget, Editor<TaskProxy> {
+
+  /**
+   * The presenter for this view.
+   */
+  public static interface Presenter {
+    /**
+     * Switch to an edit view of this task.
+     */
+    void editTask();
+  }
+
+  /**
+   * 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/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskReadView.java b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskReadView.java
new file mode 100644
index 0000000..84ceee1
--- /dev/null
+++ b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskReadView.java
@@ -0,0 +1,99 @@
+/*
+ * 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.tablet;
+
+import com.google.gwt.core.client.GWT;
+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.shared.TaskProxy;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.DateLabel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * View used to edit a task.
+ */
+public class TabletTaskReadView extends Composite implements TaskReadView {
+
+  /**
+   * Editor driver for this view.
+   */
+  interface Driver extends SimpleBeanEditorDriver<TaskProxy, TabletTaskReadView> {
+  }
+
+  /**
+   * The UiBinder interface.
+   */
+  interface TabletTaskReadViewUiBinder extends UiBinder<Widget, TabletTaskReadView> {
+  }
+
+  /**
+   * The UiBinder used to generate the view.
+   */
+  private static TabletTaskReadViewUiBinder uiBinder = GWT.create(TabletTaskReadViewUiBinder.class);
+
+  @UiField
+  DateLabel dueDateEditor;
+  @UiField
+  Label nameEditor;
+  @UiField
+  Label notesEditor;
+
+  /**
+   * The text box used to save changes or create a new task.
+   */
+  @UiField
+  Button editButton;
+
+  private final Driver driver = GWT.create(Driver.class);
+
+  /**
+   * The {@link TaskEditView.Presenter} for this view.
+   */
+  private Presenter presenter;
+
+  /**
+   * Construct a new {@link TabletTaskReadView}.
+   */
+  public TabletTaskReadView() {
+    initWidget(uiBinder.createAndBindUi(this));
+    driver.initialize(this);
+
+    // Create a new task or modify the current task when done is pressed.
+    editButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        if (presenter != null) {
+          presenter.editTask();
+        }
+      }
+    });
+  }
+
+  public SimpleBeanEditorDriver<TaskProxy, ?> getEditorDriver() {
+    return driver;
+  }
+
+  public void setPresenter(Presenter presenter) {
+    this.presenter = presenter;
+  }
+}
diff --git a/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskReadView.ui.xml b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskReadView.ui.xml
new file mode 100644
index 0000000..d35b070
--- /dev/null
+++ b/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/tablet/TabletTaskReadView.ui.xml
@@ -0,0 +1,147 @@
+<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
+<ui:UiBinder
+  xmlns:ui="urn:ui:com.google.gwt.uibinder"
+  xmlns:g="urn:import:com.google.gwt.user.client.ui"
+  xmlns:app="urn:import:com.google.gwt.sample.mobilewebapp.client.ui">
+
+  <ui:style>
+    .outer {
+      background: #eee;
+    }
+    
+    .title {
+      background: #393939;
+      color: white;
+      padding: 4px 10px;
+      font-size: 20pt;
+    }
+    
+    .editForm {
+      padding: 10px;
+      background: white;
+    }
+    
+    .label {
+      color: #666;
+      font-size: 20pt;
+      padding-bottom: 3px;
+    }
+    
+    .field {
+      width: 100%;
+      margin-bottom: 12px;
+      font-size: 20pt;
+    }
+    
+    .textBoxWrapper {
+      margin-right: 10px;
+    }
+    
+    .nameBox {
+      height: 2em;
+    }
+    
+    .notesBox {
+      height: 4em;
+    }
+    
+    .violation {
+      color: red;
+      font-size: 18pt;
+    }
+    
+    .button {
+      padding-top: 8px;
+      padding-bottom: 8px;
+      color: #3f3f3f;
+      font-size: 20pt;
+    }
+    
+    .dateButton {
+      text-align: left;
+    }
+    
+    .buttonPanel {
+      width: 100%;
+      padding: 10px;
+      margin-top: 15px;
+    }
+    
+    .saveButton {
+      width: 100%;
+    }
+    
+  </ui:style>
+
+  <g:DockLayoutPanel
+    unit="PT">
+    <!-- Title. -->
+    <g:north
+      size="28">
+      <g:Label
+        addStyleNames="{style.title}">DETAILS</g:Label>
+    </g:north>
+
+    <g:center>
+      <g:ScrollPanel
+        addStyleNames="{style.outer}">
+        <g:HTMLPanel>
+
+          <!-- Edit Form. -->
+          <div
+            class="{style.editForm}">
+            <!-- Task name. -->
+            <div
+              class="{style.label}">What</div>
+            <div
+              class="{style.textBoxWrapper}">
+              <g:Label
+                addStyleNames="{style.field} {style.nameBox}"
+                ui:field="nameEditor" />
+            </div>
+
+            <!-- Task notes. -->
+            <div
+              class="{style.label}">Notes</div>
+            <div
+              class="{style.textBoxWrapper}">
+              <g:Label
+                addStyleNames="{style.field} {style.notesBox}"
+                ui:field="notesEditor" />
+            </div>
+
+            <!-- Task due date. -->
+            <div
+              class="{style.label}">Due date</div>
+            <g:DateLabel
+              addStyleNames="{style.field} {style.button} {style.dateButton}"
+              ui:field="dueDateEditor" />
+          </div>
+
+          <!-- Button panel. -->
+          <table
+            class="{style.buttonPanel}"
+            cellspacing="0"
+            cellpadding="0">
+            <tr>
+              <td
+                align="center"
+                style="width:50%;padding-right:5px;">
+                <g:Button
+                  ui:field="editButton"
+                  addStyleNames="{style.button} {style.saveButton}">Edit</g:Button>
+              </td>
+              <td
+                align="center"
+                style="width:50%;padding-left:5px;">
+                &nbsp;
+              </td>
+            </tr>
+          </table>
+
+        </g:HTMLPanel>
+      </g:ScrollPanel>
+    </g:center>
+  </g:DockLayoutPanel>
+
+</ui:UiBinder>