Add View and ViewSite to simplify off screen DOM updating
These two classes can be used to implement an off-screen DOM update,
where a widget is attached invisibly to the browser DOM, updated by
RPC calls, and then swapped with a currently visible DOM node, thus
making the new information visible instantly.
Signed-off-by: Shawn O. Pearce <sop@google.com>
diff --git a/src/main/java/com/google/gwtexpui/user/client/View.java b/src/main/java/com/google/gwtexpui/user/client/View.java
new file mode 100644
index 0000000..c50625c
--- /dev/null
+++ b/src/main/java/com/google/gwtexpui/user/client/View.java
@@ -0,0 +1,44 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// 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.gwtexpui.user.client;
+
+import com.google.gwt.user.client.ui.Composite;
+
+/**
+ * Widget to display within a {@link ViewSite}.
+ *<p>
+ * Implementations must override <code>protected void onLoad()</code> and
+ * arrange for {@link #display()} to be invoked once the DOM within the view is
+ * consistent for presentation to the user. Typically this means that the
+ * subclass can start RPCs within <code>onLoad()</code> and then invoke
+ * <code>display()</code> from within the AsyncCallback's
+ * <code>onSuccess(Object)</code> method.
+ */
+public abstract class View extends Composite {
+ ViewSite<? extends View> site;
+
+ @Override
+ protected void onUnload() {
+ site = null;
+ super.onUnload();
+ }
+
+ /** Replace the current view in the parent ViewSite with this view. */
+ public final void display() {
+ if (site != null) {
+ site.swap(this);
+ }
+ }
+}
diff --git a/src/main/java/com/google/gwtexpui/user/client/ViewSite.java b/src/main/java/com/google/gwtexpui/user/client/ViewSite.java
new file mode 100644
index 0000000..d8c6b60
--- /dev/null
+++ b/src/main/java/com/google/gwtexpui/user/client/ViewSite.java
@@ -0,0 +1,77 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// 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.gwtexpui.user.client;
+
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.SimplePanel;
+
+/**
+ * Hosts a single {@link View}.
+ * <p>
+ * View instances are attached inside of an invisible DOM node, permitting their
+ * <code>onLoad()</code> method to be invoked and to update the DOM prior to the
+ * elements being made visible in the UI.
+ * <p>
+ * Complaint View instances must invoke {@link View#display()} once the DOM is
+ * ready for presentation.
+ */
+public class ViewSite<V extends View> extends Composite {
+ private final FlowPanel main;
+ private SimplePanel current;
+ private SimplePanel next;
+
+ public ViewSite() {
+ main = new FlowPanel();
+ initWidget(main);
+ }
+
+ /** Get the current view; null if there is no view being displayed. */
+ @SuppressWarnings("unchecked")
+ public V getView() {
+ return current != null ? (V) current.getWidget() : null;
+ }
+
+ /**
+ * Set the next view to display.
+ * <p>
+ * The view will be attached to the DOM tree within a hidden container,
+ * permitting its <code>onLoad()</code> method to execute and update the DOM
+ * without the user seeing the result.
+ *
+ * @param view the next view to display.
+ */
+ public void setView(final V view) {
+ if (next != null) {
+ main.remove(next);
+ }
+ view.site = this;
+ next = new SimplePanel();
+ next.setVisible(false);
+ main.add(next);
+ next.add(view);
+ }
+
+ final void swap(final View v) {
+ if (next != null && next.getWidget() == v) {
+ if (current != null) {
+ main.remove(current);
+ }
+ current = next;
+ next = null;
+ current.setVisible(true);
+ }
+ }
+}