Revision: 7691
Author: [email protected]
Date: Wed Mar 10 05:41:10 2010
Log: Checkpoint work on Stock demo

Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=7691

Added:
/trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/Columns.java /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockQueryWidget.java /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/Updater.java
Modified:
 /trunk/bikeshed/src/com/google/gwt/bikeshed/list/shared/AsyncListModel.java
/trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockService.java /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockServiceAsync.java /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/TransactionTreeViewModel.java /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/server/NasdaqStocks.java /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/server/StockServiceImpl.java /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockQuoteList.java /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockRequest.java /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockResponse.java
 /trunk/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeNodeView.java
 /trunk/bikeshed/war/Stocks.html

=======================================
--- /dev/null
+++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/Columns.java Wed Mar 10 05:41:10 2010
@@ -0,0 +1,112 @@
+/*
+ * 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.bikeshed.sample.stocks.client;
+
+import com.google.gwt.bikeshed.cells.client.ButtonCell;
+import com.google.gwt.bikeshed.cells.client.CheckboxCell;
+import com.google.gwt.bikeshed.cells.client.CurrencyCell;
+import com.google.gwt.bikeshed.cells.client.TextCell;
+import com.google.gwt.bikeshed.list.client.Column;
+import com.google.gwt.bikeshed.sample.stocks.shared.StockQuote;
+import com.google.gwt.bikeshed.sample.stocks.shared.Transaction;
+
+/**
+ * Column definitions for the stock demo.
+ */
+public class Columns {
+
+ static Column<StockQuote, String> buyColumn = new Column<StockQuote, String>(
+      new ButtonCell()) {
+    @Override
+    protected String getValue(StockQuote object) {
+      return "Buy";
+    }
+  };
+
+  static Column<StockQuote, Integer> dollarsColumn =
+    new Column<StockQuote, Integer>(new CurrencyCell()) {
+    @Override
+    protected Integer getValue(StockQuote object) {
+      return object.getPrice() * object.getSharesOwned();
+    }
+  };
+
+  static Column<StockQuote, Boolean> favoriteColumn =
+    new Column<StockQuote, Boolean>(new CheckboxCell()) {
+    @Override
+    protected Boolean getValue(StockQuote object) {
+      return object.isFavorite();
+    }
+  };
+
+  static Column<StockQuote, String> nameColumn =
+    new Column<StockQuote, String>(new TextCell()) {
+    @Override
+    protected String getValue(StockQuote object) {
+      return object.getName();
+    }
+  };
+
+  static Column<StockQuote, Integer> priceColumn =
+    new Column<StockQuote, Integer>(new CurrencyCell()) {
+    @Override
+    protected Integer getValue(StockQuote object) {
+      return object.getPrice();
+    }
+  };
+
+  static Column<StockQuote, String> sellColumn =
+    new Column<StockQuote, String>(new ButtonCell()) {
+    @Override
+    protected String getValue(StockQuote object) {
+      return "Sell";
+    }
+  };
+
+  static Column<StockQuote, String> sharesColumn =
+    new Column<StockQuote, String>(new TextCell()) {
+    @Override
+    protected String getValue(StockQuote object) {
+      return "" + object.getSharesOwned();
+    }
+  };
+
+  static Column<Transaction, String> subtotalColumn =
+    new Column<Transaction, String>(new TextCell()) {
+    @Override
+    protected String getValue(Transaction object) {
+      int price = object.getActualPrice() * object.getQuantity();
+ return (object.isBuy() ? " (" : " ") + StockSample.getFormattedPrice(price) +
+          (object.isBuy() ? ")" : "");
+    }
+  };
+
+  static Column<StockQuote, String> tickerColumn =
+    new Column<StockQuote, String>(new TextCell()) {
+    @Override
+    protected String getValue(StockQuote object) {
+      return object.getTicker();
+    }
+  };
+
+  static Column<Transaction, String> transactionColumn =
+    new Column<Transaction, String>(new TextCell()) {
+    @Override
+    protected String getValue(Transaction object) {
+      return object.toString();
+    }
+  };
+}
=======================================
--- /dev/null
+++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockQueryWidget.java Wed Mar 10 05:41:10 2010
@@ -0,0 +1,74 @@
+/*
+ * 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.bikeshed.sample.stocks.client;
+
+import com.google.gwt.bikeshed.list.client.PagingTableListView;
+import com.google.gwt.bikeshed.list.shared.ListModel;
+import com.google.gwt.bikeshed.sample.stocks.shared.StockQuote;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.DockLayoutPanel;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.ScrollPanel;
+import com.google.gwt.user.client.ui.TextBox;
+
+/**
+ * A widget containing a search box and a results table.
+ */
+public class StockQueryWidget extends Composite {
+
+  private final TextBox queryField = new TextBox();
+  private PagingTableListView<StockQuote> resultsTable;
+
+ public StockQueryWidget(ListModel<StockQuote> searchListModel, final Updater updater) {
+    // Create the results table.
+ resultsTable = new PagingTableListView<StockQuote>(searchListModel, 10);
+    resultsTable.addColumn(Columns.favoriteColumn);
+    resultsTable.addColumn(Columns.tickerColumn);
+    resultsTable.addColumn(Columns.nameColumn);
+    resultsTable.addColumn(Columns.priceColumn);
+    resultsTable.addColumn(Columns.buyColumn);
+
+    // Focus the cursor on the name field when the app loads
+    queryField.setFocus(true);
+    queryField.selectAll();
+    queryField.setText("G");
+
+    // Add a handler to send the name to the server
+    queryField.addKeyUpHandler(new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
+        updater.update();
+      }
+    });
+
+    DockLayoutPanel layoutPanel = new DockLayoutPanel(Unit.EM);
+
+    HorizontalPanel panel = new HorizontalPanel();
+    panel.add(new Label("Enter query: "));
+    panel.add(queryField);
+    layoutPanel.addNorth(panel, 2.0);
+    layoutPanel.add(new ScrollPanel(resultsTable));
+
+    initWidget(layoutPanel);
+  }
+
+  public String getSearchQuery() {
+    return queryField.getText();
+  }
+}
=======================================
--- /dev/null
+++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/Updater.java Wed Mar 10 05:41:10 2010
@@ -0,0 +1,30 @@
+/*
+ * 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.bikeshed.sample.stocks.client;
+
+/**
+ * Bridge between StockSample and StockQueryWidget.
+ */
+public interface Updater {
+
+  /**
+   * Update the widget.
+   *
+   * TODO - refactor this
+   */
+  void update();
+
+}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/list/shared/AsyncListModel.java Fri Feb 26 09:32:06 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/list/shared/AsyncListModel.java Wed Mar 10 05:41:10 2010
@@ -30,6 +30,7 @@
    * @param <T> the data type
    */
   public static interface DataSource<T> {
+
     /**
      * Request that the data source pushes new data to the client. The data
* source should call {...@link #updateViewData} and/or {...@link #updateDataSize}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java Fri Mar 5 07:05:48 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java Wed Mar 10 05:41:10 2010
@@ -15,40 +15,36 @@
  */
 package com.google.gwt.bikeshed.sample.stocks.client;

-import com.google.gwt.bikeshed.cells.client.ButtonCell;
-import com.google.gwt.bikeshed.cells.client.CheckboxCell;
-import com.google.gwt.bikeshed.cells.client.CurrencyCell;
 import com.google.gwt.bikeshed.cells.client.FieldUpdater;
-import com.google.gwt.bikeshed.cells.client.TextCell;
-import com.google.gwt.bikeshed.list.client.Column;
 import com.google.gwt.bikeshed.list.client.PagingTableListView;
 import com.google.gwt.bikeshed.list.shared.AsyncListModel;
 import com.google.gwt.bikeshed.list.shared.ListListModel;
 import com.google.gwt.bikeshed.list.shared.Range;
 import com.google.gwt.bikeshed.list.shared.AsyncListModel.DataSource;
+import com.google.gwt.bikeshed.sample.stocks.client.TransactionTreeViewModel.SectorListModel;
 import com.google.gwt.bikeshed.sample.stocks.shared.StockQuote;
 import com.google.gwt.bikeshed.sample.stocks.shared.StockQuoteList;
 import com.google.gwt.bikeshed.sample.stocks.shared.StockRequest;
 import com.google.gwt.bikeshed.sample.stocks.shared.StockResponse;
 import com.google.gwt.bikeshed.sample.stocks.shared.Transaction;
 import com.google.gwt.bikeshed.tree.client.SideBySideTreeView;
-import com.google.gwt.bikeshed.tree.client.StandardTreeView;
 import com.google.gwt.core.client.EntryPoint;
 import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.dom.client.Style.Unit;
 import com.google.gwt.event.logical.shared.CloseEvent;
 import com.google.gwt.event.logical.shared.CloseHandler;
 import com.google.gwt.i18n.client.NumberFormat;
 import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.DockLayoutPanel;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.RootLayoutPanel;
+import com.google.gwt.user.client.ui.ScrollPanel;
+import com.google.gwt.user.client.ui.Widget;

 import java.util.HashMap;
 import java.util.List;
@@ -57,91 +53,14 @@
 /**
  * Entry point classes define <code>onModuleLoad()</code>.
  */
-public class StockSample implements EntryPoint {
-
-  static class Columns {
-
- private static Column<StockQuote, String> buyColumn = new Column<StockQuote, String>(
-        new ButtonCell()) {
-      @Override
-      protected String getValue(StockQuote object) {
-        return "Buy";
-      }
-    };
-
-    private static Column<StockQuote, Boolean> favoriteColumn =
-      new Column<StockQuote, Boolean>(new CheckboxCell()) {
-      @Override
-      protected Boolean getValue(StockQuote object) {
-        return object.isFavorite();
-      }
-    };
-
-    private static Column<StockQuote, String> nameColumn =
-      new Column<StockQuote, String>(new TextCell()) {
-      @Override
-      protected String getValue(StockQuote object) {
-        return object.getName();
-      }
-    };
-
-    private static Column<StockQuote, Integer> priceColumn =
-      new Column<StockQuote, Integer>(new CurrencyCell()) {
-      @Override
-      protected Integer getValue(StockQuote object) {
-        return object.getPrice();
-      }
-    };
-
-    private static Column<StockQuote, String> sellColumn =
-      new Column<StockQuote, String>(new ButtonCell()) {
-      @Override
-      protected String getValue(StockQuote object) {
-        return "Sell";
-      }
-    };
-
-    private static Column<StockQuote, String> sharesColumn =
-      new Column<StockQuote, String>(new TextCell()) {
-      @Override
-      protected String getValue(StockQuote object) {
-        return "" + object.getSharesOwned();
-      }
-    };
-
-    private static Column<Transaction, String> subtotalColumn =
-      new Column<Transaction, String>(new TextCell()) {
-      @Override
-      protected String getValue(Transaction object) {
-        int price = object.getActualPrice() * object.getQuantity();
-        return (object.isBuy() ? " (" : " ") + getFormattedPrice(price) +
-            (object.isBuy() ? ")" : "");
-      }
-    };
-
-    private static Column<StockQuote, String> tickerColumn =
-      new Column<StockQuote, String>(new TextCell()) {
-      @Override
-      protected String getValue(StockQuote object) {
-        return object.getTicker();
-      }
-    };
-
-    private static Column<Transaction, String> transactionColumn =
-      new Column<Transaction, String>(new TextCell()) {
-      @Override
-      protected String getValue(Transaction object) {
-        return object.toString();
-      }
-    };
-  }
-
+public class StockSample implements EntryPoint, Updater {
+
   /**
    * The delay between updates in milliseconds.
    */
   private static final int UPDATE_DELAY = 5000;

-  private static String getFormattedPrice(int price) {
+  static String getFormattedPrice(int price) {
     return NumberFormat.getCurrencyFormat("USD").format(price / 100.0);
   }

@@ -157,30 +76,27 @@
    */
private final StockServiceAsync dataService = GWT.create(StockService.class);

-  private final Label errorLabel = new Label();
-
   private AsyncListModel<StockQuote> favoritesListModel;

   private PagingTableListView<StockQuote> favoritesTable;

-  private final TextBox queryField = new TextBox();
-
-  private PagingTableListView<StockQuote> resultsTable;
-
+  private final Label netWorthLabel = new Label();
+
+  private StockQueryWidget queryWidget;
+
   private AsyncListModel<StockQuote> searchListModel;

private Map<String, ListListModel<Transaction>> transactionListListModelsByTicker =
     new HashMap<String, ListListModel<Transaction>>();
-
+
   private ListListModel<Transaction> transactionListModel;

   private List<Transaction> transactions;
-
+
   private PagingTableListView<Transaction> transactionTable;
-
-  private StandardTreeView transactionTree1;
-
-  private SideBySideTreeView transactionTree2;
+
+  private SideBySideTreeView transactionTree;
+
   /**
    * The timer used to update the stock quotes.
    */
@@ -191,20 +107,12 @@
     }
   };

+  private TransactionTreeViewModel treeModel;
+
   /**
    * This is the entry point method.
    */
   public void onModuleLoad() {
-    queryField.setText("G");
-
-    // Add the nameField and sendButton to the RootPanel
-    // Use RootPanel.get() to get the entire body element
-    RootPanel.get("queryFieldContainer").add(queryField);
-    RootPanel.get("errorLabelContainer").add(errorLabel);
-
-    // Focus the cursor on the name field when the app loads
-    queryField.setFocus(true);
-    queryField.selectAll();

     // Create the list models
     searchListModel = new AsyncListModel<StockQuote>(
@@ -224,19 +132,12 @@
     transactionListModel = new ListListModel<Transaction>();
     transactions = transactionListModel.getList();

-    // Create the results table.
- resultsTable = new PagingTableListView<StockQuote>(searchListModel, 10);
-    resultsTable.addColumn(Columns.favoriteColumn);
-    resultsTable.addColumn(Columns.tickerColumn);
-    resultsTable.addColumn(Columns.nameColumn);
-    resultsTable.addColumn(Columns.priceColumn);
-    resultsTable.addColumn(Columns.buyColumn);
-
     // Create the favorites table.
favoritesTable = new PagingTableListView<StockQuote>(favoritesListModel, 10);
     favoritesTable.addColumn(Columns.tickerColumn);
     favoritesTable.addColumn(Columns.priceColumn);
     favoritesTable.addColumn(Columns.sharesColumn);
+    favoritesTable.addColumn(Columns.dollarsColumn);
     favoritesTable.addColumn(Columns.buyColumn);
     favoritesTable.addColumn(Columns.sellColumn);

@@ -245,14 +146,9 @@
     transactionTable.addColumn(Columns.transactionColumn);
     transactionTable.addColumn(Columns.subtotalColumn);

-    // Create the transactions tree.
- transactionTree1 = new StandardTreeView(new TransactionTreeViewModel(favoritesListModel,
-        transactionListListModelsByTicker), null);
-    transactionTree1.setAnimationEnabled(true);
-
-    // Create the transactions tree.
- transactionTree2 = new SideBySideTreeView(new TransactionTreeViewModel(favoritesListModel,
-        transactionListListModelsByTicker), null, 200, 200);
+    treeModel = new TransactionTreeViewModel(this,
+        favoritesListModel, transactionListListModelsByTicker);
+    transactionTree = new SideBySideTreeView(treeModel, null, 200, 200);

Columns.favoriteColumn.setFieldUpdater(new FieldUpdater<StockQuote, Boolean>() {
       public void update(StockQuote object, Boolean value) {
@@ -309,32 +205,42 @@
               t.getList().add(result);
             }
           });
-        }
+       }
       }
     });

     // Add components to the page.
-    HorizontalPanel hPanel = new HorizontalPanel();
-    hPanel.add(new HTML("<b>Available cash:</b>"));
-    hPanel.add(cashLabel);
-    RootPanel.get().add(hPanel);
-
-    RootPanel.get().add(resultsTable);
-    RootPanel.get().add(new HTML("<hr>"));
-    RootPanel.get().add(favoritesTable);
-    RootPanel.get().add(new HTML("<hr>"));
-    RootPanel.get().add(transactionTable);
-    RootPanel.get().add(new HTML("<hr>"));
-    RootPanel.get().add(transactionTree1);
-    RootPanel.get().add(new HTML("<hr>"));
-    RootPanel.get().add(transactionTree2);
-
-    // Add a handler to send the name to the server
-    queryField.addKeyUpHandler(new KeyUpHandler() {
-      public void onKeyUp(KeyUpEvent event) {
-        update();
-      }
-    });
+
+    Widget headerWidget = new HTML("<b>Stock Game</b>");
+
+    HorizontalPanel cashPanel = new HorizontalPanel();
+    cashPanel.add(new HTML("<b>Available cash:</b>"));
+    cashPanel.add(cashLabel);
+
+    HorizontalPanel netWorthPanel = new HorizontalPanel();
+    netWorthPanel.add(new HTML("<b>Net worth:</b>"));
+    netWorthPanel.add(netWorthLabel);
+
+    DockLayoutPanel footerPanel = new DockLayoutPanel(Unit.PCT);
+    footerPanel.addWest(cashPanel, 50.0);
+    footerPanel.add(netWorthPanel);
+
+    DockLayoutPanel layoutPanel = new DockLayoutPanel(Unit.EM);
+    layoutPanel.addNorth(headerWidget, 4.0);
+    layoutPanel.addSouth(footerPanel, 2.0);
+    layoutPanel.addNorth(transactionTree, 18.0);
+
+    DockLayoutPanel innerLayoutPanel = new DockLayoutPanel(Unit.PCT);
+    this.queryWidget = new StockQueryWidget(searchListModel, this);
+    innerLayoutPanel.addWest(queryWidget, 50.0);
+
+    DockLayoutPanel favoritesLayoutPanel = new DockLayoutPanel(Unit.EM);
+    favoritesLayoutPanel.addNorth(new Label("Portfolio / Favorites"), 2.0);
+    favoritesLayoutPanel.add(new ScrollPanel(favoritesTable));
+    innerLayoutPanel.add(favoritesLayoutPanel);
+    layoutPanel.add(innerLayoutPanel);
+
+    RootLayoutPanel.get().add(layoutPanel);

     update();
   }
@@ -347,72 +253,56 @@
    */
   public void setFavorite(String ticker, boolean favorite) {
     if (favorite) {
-      dataService.addFavorite(ticker, new AsyncCallback<Void>() {
+      dataService.addFavorite(ticker, favoritesListModel.getRanges()[0],
+          new AsyncCallback<StockResponse>() {
         public void onFailure(Throwable caught) {
           Window.alert("Error adding favorite");
         }

-        public void onSuccess(Void result) {
-          // do nothing
+        public void onSuccess(StockResponse response) {
+          updateFavorites(response);
         }
       });
     } else {
-      dataService.removeFavorite(ticker, new AsyncCallback<Void>() {
+      dataService.removeFavorite(ticker, favoritesListModel.getRanges()[0],
+          new AsyncCallback<StockResponse>() {
         public void onFailure(Throwable caught) {
           Window.alert("Error removing favorite");
         }

-        public void onSuccess(Void result) {
-          // do nothing
+        public void onSuccess(StockResponse response) {
+          updateFavorites(response);
         }
       });
     }
   }

-  /**
-   * Process the {...@link StockResponse} from the server.
-   *
-   * @param response the stock response
-   */
-  private void processStockResponse(StockResponse response) {
-    // Update the search list.
-    StockQuoteList searchResults = response.getSearchResults();
-    searchListModel.updateDataSize(response.getNumSearchResults(), true);
-    searchListModel.updateViewData(searchResults.getStartIndex(),
-        searchResults.size(), searchResults);
-
-    // Update the favorites list.
-    StockQuoteList favorites = response.getFavorites();
-    favoritesListModel.updateDataSize(response.getNumFavorites(), true);
-    favoritesListModel.updateViewData(favorites.getStartIndex(),
-        favorites.size(), favorites);
-
-    // Update available cash.
-    int cash = response.getCash();
-    cashLabel.setText(getFormattedPrice(cash));
-    buySellPopup.setAvailableCash(cash);
-
-    // Restart the update timer.
-    updateTimer.schedule(UPDATE_DELAY);
-  }
-
   /**
    * Request data from the server using the last query string.
    */
-  private void update() {
+  public void update() {
+    if (queryWidget == null) {
+      return;
+    }
+
     updateTimer.cancel();
-
+
     Range[] searchRanges = searchListModel.getRanges();
     Range[] favoritesRanges = favoritesListModel.getRanges();
-
+    SectorListModel sectorListModel = treeModel.getSectorListModel();
+ Range[] sectorRanges = sectorListModel == null ? null : sectorListModel.getRanges();
+
     if (searchRanges == null || searchRanges.length == 0
         || favoritesRanges == null || favoritesRanges.length == 0) {
       return;
     }
-
-    String searchQuery = queryField.getText();
-    StockRequest request = new StockRequest(searchQuery, searchRanges[0],
-        favoritesRanges[0]);
+
+    String searchQuery = queryWidget.getSearchQuery();
+    StockRequest request = new StockRequest(searchQuery,
+        sectorListModel != null ? sectorListModel.getSector() : null,
+        searchRanges[0],
+        favoritesRanges[0],
+ sectorRanges != null && sectorRanges.length > 0 ? sectorRanges[0] : null); dataService.getStockQuotes(request, new AsyncCallback<StockResponse>() {
       public void onFailure(Throwable caught) {
         String message = caught.getMessage();
@@ -424,10 +314,56 @@
           updateTimer.schedule(UPDATE_DELAY);
         }
       }
-
+
       public void onSuccess(StockResponse result) {
         processStockResponse(result);
       }
     });
   }
-}
+
+  /**
+   * Process the {...@link StockResponse} from the server.
+   *
+   * @param response the stock response
+   */
+  private void processStockResponse(StockResponse response) {
+    // Update the search list.
+    StockQuoteList searchResults = response.getSearchResults();
+    searchListModel.updateDataSize(response.getNumSearchResults(), true);
+    searchListModel.updateViewData(searchResults.getStartIndex(),
+        searchResults.size(), searchResults);
+
+    // Update the favorites list.
+    updateFavorites(response);
+    updateSector(response);
+
+    // Update available cash.
+    int cash = response.getCash();
+    int netWorth = response.getNetWorth();
+    cashLabel.setText(getFormattedPrice(cash));
+    netWorthLabel.setText(getFormattedPrice(netWorth));
+    buySellPopup.setAvailableCash(cash);
+
+    // Restart the update timer.
+    updateTimer.schedule(UPDATE_DELAY);
+  }
+
+  private void updateFavorites(StockResponse response) {
+    // Update the favorites list.
+    StockQuoteList favorites = response.getFavorites();
+    favoritesListModel.updateDataSize(response.getNumFavorites(), true);
+    favoritesListModel.updateViewData(favorites.getStartIndex(),
+        favorites.size(), favorites);
+  }
+
+  private void updateSector(StockResponse response) {
+    // Update the sector list.
+    StockQuoteList sectorList = response.getSector();
+    if (sectorList != null) {
+      SectorListModel sectorListModel = treeModel.getSectorListModel();
+      sectorListModel.updateDataSize(response.getNumSector(), true);
+      sectorListModel.updateViewData(sectorList.getStartIndex(),
+          sectorList.size(), sectorList);
+    }
+  }
+}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockService.java Fri Feb 26 09:32:06 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockService.java Wed Mar 10 05:41:10 2010
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.bikeshed.sample.stocks.client;

+import com.google.gwt.bikeshed.list.shared.Range;
 import com.google.gwt.bikeshed.sample.stocks.shared.StockRequest;
 import com.google.gwt.bikeshed.sample.stocks.shared.StockResponse;
 import com.google.gwt.bikeshed.sample.stocks.shared.Transaction;
@@ -30,9 +31,9 @@
   StockResponse getStockQuotes(StockRequest request)
       throws IllegalArgumentException;

-  void addFavorite(String ticker);
-
-  void removeFavorite(String ticker);
+  StockResponse addFavorite(String ticker, Range favoritesRange);
+
+  StockResponse removeFavorite(String ticker, Range favoritesRange);

Transaction transact(Transaction transaction) throws IllegalArgumentException;
 }
=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockServiceAsync.java Fri Feb 26 09:32:06 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockServiceAsync.java Wed Mar 10 05:41:10 2010
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.bikeshed.sample.stocks.client;

+import com.google.gwt.bikeshed.list.shared.Range;
 import com.google.gwt.bikeshed.sample.stocks.shared.StockRequest;
 import com.google.gwt.bikeshed.sample.stocks.shared.StockResponse;
 import com.google.gwt.bikeshed.sample.stocks.shared.Transaction;
@@ -27,9 +28,9 @@
   void getStockQuotes(StockRequest request,
       AsyncCallback<StockResponse> callback);

-  void addFavorite(String ticker, AsyncCallback<Void> callback);
-
-  void removeFavorite(String ticker, AsyncCallback<Void> callback);
+ void addFavorite(String ticker, Range favoritesRange, AsyncCallback<StockResponse> callback);
+
+ void removeFavorite(String ticker, Range favoritesRange, AsyncCallback<StockResponse> callback);

void transact(Transaction transaction, AsyncCallback<Transaction> callback);
 }
=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/TransactionTreeViewModel.java Thu Mar 4 08:02:44 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/TransactionTreeViewModel.java Wed Mar 10 05:41:10 2010
@@ -16,13 +16,17 @@
 package com.google.gwt.bikeshed.sample.stocks.client;

 import com.google.gwt.bikeshed.cells.client.Cell;
+import com.google.gwt.bikeshed.cells.client.TextCell;
+import com.google.gwt.bikeshed.list.shared.AsyncListModel;
 import com.google.gwt.bikeshed.list.shared.ListListModel;
 import com.google.gwt.bikeshed.list.shared.ListModel;
 import com.google.gwt.bikeshed.sample.stocks.shared.StockQuote;
 import com.google.gwt.bikeshed.sample.stocks.shared.Transaction;
 import com.google.gwt.bikeshed.tree.client.TreeNode;
 import com.google.gwt.bikeshed.tree.client.TreeViewModel;
-
+import com.google.gwt.bikeshed.tree.client.TreeViewModel.DefaultNodeInfo;
+
+import java.util.List;
 import java.util.Map;

 /**
@@ -32,6 +36,24 @@
  */
 class TransactionTreeViewModel implements TreeViewModel {

+  class SectorListModel extends AsyncListModel<StockQuote> {
+
+    String sector;
+
+    public SectorListModel(final Updater updater, String sector) {
+      super(new DataSource<StockQuote>() {
+        public void requestData(AsyncListModel<StockQuote> listModel) {
+          updater.update();
+        }
+      });
+      this.sector = sector;
+    }
+
+    public String getSector() {
+      return sector;
+    }
+  }
+
   static class TransactionCell extends Cell<Transaction> {
     @Override
     public void render(Transaction value, StringBuilder sb) {
@@ -49,24 +71,46 @@
   private static final Cell<Transaction> TRANSACTION_CELL =
     new TransactionCell();

+  private SectorListModel sectorListModel;
   private ListModel<StockQuote> stockQuoteListModel;
+  private ListListModel<String> topLevelListListModel =
+    new ListListModel<String>();
private Map<String, ListListModel<Transaction>> transactionListListModelsByTicker;

- public TransactionTreeViewModel(ListModel<StockQuote> stockQuoteListModel,
+  private Updater updater;
+
+ public TransactionTreeViewModel(Updater updater, ListModel<StockQuote> stockQuoteListModel, Map<String, ListListModel<Transaction>> transactionListListModelsByTicker) {
+    this.updater = updater;
     this.stockQuoteListModel = stockQuoteListModel;
+    List<String> topLevelList = topLevelListListModel.getList();
+    topLevelList.add("Favorites");
+    topLevelList.add("Internet");
+    topLevelList.add("Energy");
+    topLevelList.add("Networking");
this.transactionListListModelsByTicker = transactionListListModelsByTicker;
   }

   @SuppressWarnings("unused")
   public <T> NodeInfo<?> getNodeInfo(T value, TreeNode<T> treeNode) {
     if (value == null) {
+ return new TreeViewModel.DefaultNodeInfo<String>(topLevelListListModel,
+          new TextCell());
+    } else if ("Favorites".equals(value)) {
return new TreeViewModel.DefaultNodeInfo<StockQuote>(stockQuoteListModel,
           STOCK_QUOTE_CELL) {
         @Override
         public Object getKey(StockQuote value) {
           return value.getTicker();
         }
+      };
+    } else if (value instanceof String) {
+      sectorListModel = new SectorListModel(updater, (String) value);
+ return new TreeViewModel.DefaultNodeInfo<StockQuote>(sectorListModel, STOCK_QUOTE_CELL) {
+        @Override
+        public Object getKey(StockQuote value) {
+          return value.getTicker();
+        }
       };
     } else if (value instanceof StockQuote) {
       String ticker = ((StockQuote) value).getTicker();
@@ -81,6 +125,10 @@

     throw new IllegalArgumentException(value.toString());
   }
+
+  public SectorListModel getSectorListModel() {
+    return sectorListModel;
+  }

   public boolean isLeaf(Object value) {
     return value instanceof Transaction;
=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/server/NasdaqStocks.java Fri Feb 26 09:32:06 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/server/NasdaqStocks.java Wed Mar 10 05:41:10 2010
@@ -182,11 +182,9 @@
       "ANGN", "Angeion Corporation",
       "ANGO", "AngioDynamics, Inc.",
       "ANIK", "Anika Therapeutics Inc.",
-      "ANLY", "Analysts International Corporation",
       "ANNB", "Annapolis Bancorp Inc.",
       "ANPI", "Angiotech Pharmaceuticals, Inc.",
       "ANSS", "ANSYS, Inc.",
-      "ANSV", "Anesiva, Inc.",
       "ANSW", "Answers Corporation",
       "ANTP", "PHAZAR CORP", "AONE", "A123 Systems, Inc.",
       "APAB", "Appalachian Bancshares, Inc. (GA)",
@@ -252,7 +250,6 @@
       "ASTE", "Astec Industries, Inc.",
       "ASTI", "Ascent Solar Technologies, Inc.",
       "ASTIZ", "Ascent Solar Technologies, Inc.",
-      "ASTM", "Aastrom Biosciences, Inc.",
       "ASUR", "Forgent Networks Inc",
       "ASYS", "Amtech Systems, Inc.",
       "ATAC", "ATC Technology Corporation",
@@ -441,7 +438,6 @@
       "CALI", "China Auto Logistics Inc.",
       "CALM", "Cal-Maine Foods, Inc.",
       "CALP", "Caliper Life Sciences Inc",
-      "CAMD", "California Micro Devices Corporation",
       "CAMP", "CalAmp Corp.",
       "CAMT", "Camtek Ltd.",
       "CAPS", "Orthologic Corp.",
@@ -715,7 +711,6 @@
       "CWBS", "Commonwealth Bankshares, Inc.",
       "CWCO", "Consolidated Water Co. Ltd.",
       "CWEI", "Clayton Williams Energy, Inc.",
-      "CWLZ", "Cowlitz Bancorporation",
       "CWST", "Casella Waste Systems, Inc.",
       "CWTR", "Coldwater Creek, Inc.",
       "CYAN", "Cyanotech Corporation",
@@ -1055,7 +1050,6 @@
       "FXCB", "Fox Chase Bancorp, Inc.",
       "FXEN", "FX Energy, Inc.",
       "GABC", "German American Bancorp, Inc.",
-      "GAI", "Global-Tech Advanced Innovations Inc.",
       "GAIA", "Gaiam, Inc.",
       "GAIN", "Gladstone Investment Corporation",
       "GAME", "Shanda Games Limited",
=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/server/StockServiceImpl.java Fri Mar 5 07:05:48 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/server/StockServiceImpl.java Wed Mar 10 05:41:10 2010
@@ -67,6 +67,9 @@

   private static final int MAX_RESULTS_TO_RETURN = 10000;

+  private static final HashMap<String,String> sectorQueries =
+    new HashMap<String,String>();
+
   static {
     int num = NasdaqStocks.SYMBOLS.length;
     for (int i = 0; i < num - 1; i += 2) {
@@ -78,13 +81,31 @@
     }
   }

+  static {
+    sectorQueries.put("INTERNET", "GOOG|YHOO|MSFT");
+    sectorQueries.put("ENERGY", "GASS|GLRP");
+    sectorQueries.put("NETWORKING", "GLBC|CSCO");
+  }
+
   /**
    * A mapping of usernames to {...@link PlayerStatus}.
    */
private Map<String, PlayerStatus> players = new HashMap<String, PlayerStatus>();
-
-  public void addFavorite(String ticker) {
-    ensurePlayer().addFavorite(ticker);
+
+  public StockResponse addFavorite(String ticker, Range favoritesRange) {
+    PlayerStatus player = ensurePlayer();
+    player.addFavorite(ticker);
+    Result favorites = query(player.getFavoritesQuery(), favoritesRange);
+    return new StockResponse(null, favorites.quotes, null,
+        0, favorites.numRows, 0, player.getCash());
+  }
+
+  public Result getSectorQuotes(String sector, Range sectorRange) {
+    String sectorQuery = sectorQueries.get(sector.toUpperCase());
+    if (sectorQuery == null) {
+      return null;
+    }
+    return query(sectorQuery, sectorRange);
   }

   public StockResponse getStockQuotes(StockRequest request)
@@ -96,17 +117,28 @@
     }
     Range searchRange = request.getSearchRange();
     Range favoritesRange = request.getFavoritesRange();
-
+    Range sectorRange = request.getSectorRange();
+
     PlayerStatus player = ensurePlayer();
     Result searchResults = query(query, searchRange);
     Result favorites = query(player.getFavoritesQuery(), favoritesRange);
-
-    return new StockResponse(searchResults.quotes, favorites.quotes,
-        searchResults.numRows, favorites.numRows, player.getCash());
+ Result sector = sectorRange != null ? getSectorQuotes(request.getSector(), sectorRange) : null;
+
+    return new StockResponse(searchResults.quotes,
+        favorites.quotes,
+        sector != null ? sector.quotes : null,
+        searchResults.numRows,
+        favorites.numRows,
+        sector != null ? sector.numRows : 0,
+        player.getCash());
   }

-  public void removeFavorite(String ticker) {
-    ensurePlayer().removeFavorite(ticker);
+ public StockResponse removeFavorite(String ticker, Range favoritesRange) {
+    PlayerStatus player = ensurePlayer();
+    player.removeFavorite(ticker);
+    Result favorites = query(player.getFavoritesQuery(), favoritesRange);
+    return new StockResponse(null, favorites.quotes, null,
+        0, favorites.numRows, 0, player.getCash());
   }

   public Transaction transact(Transaction transaction)
=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockQuoteList.java Fri Feb 26 09:32:06 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockQuoteList.java Wed Mar 10 05:41:10 2010
@@ -38,5 +38,16 @@
   public int getStartIndex() {
     return start;
   }
+
+  /**
+   * Returns the sum of stock prices times shares owned, in pennies.
+   */
+  public int getValue() {
+    int value = 0;
+    for (StockQuote q : this) {
+      value += q.getPrice() * q.getSharesOwned();
+    }
+    return value;
+  }
 }

=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockRequest.java Fri Feb 26 09:32:06 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockRequest.java Wed Mar 10 05:41:10 2010
@@ -24,15 +24,18 @@
  */
 public class StockRequest implements Serializable {

+  Range favoritesRange;
   String searchQuery;
   Range searchRange;
-  Range favoritesRange;
-
-  public StockRequest(String searchQuery, Range searchRange,
-      Range favoritesRange) {
+  String sector;
+  Range sectorRange;
+  public StockRequest(String searchQuery, String sector, Range searchRange,
+      Range favoritesRange, Range sectorRange) {
     this.searchQuery = searchQuery;
+    this.sector = sector;
     this.searchRange = searchRange;
     this.favoritesRange = favoritesRange;
+    this.sectorRange = sectorRange;
   }

   /**
@@ -52,4 +55,12 @@
   public Range getSearchRange() {
     return searchRange;
   }
-}
+
+  public String getSector() {
+    return sector;
+  }
+
+  public Range getSectorRange() {
+    return sectorRange;
+  }
+}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockResponse.java Fri Feb 26 09:32:06 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockResponse.java Wed Mar 10 05:41:10 2010
@@ -22,30 +22,33 @@
  */
 public class StockResponse implements Serializable {

-  private StockQuoteList searchResults;
-  private StockQuoteList favorites;
-  private int numSearchResults;
-  private int numFavorites;
-
   /**
    * The amount of available cash in pennies.
    */
   private int cash;
-
-  /**
-   * Used for RPC.
-   */
-  StockResponse() {
-  }
+  private StockQuoteList favorites;
+  private int numFavorites;
+  private int numSearchResults;
+  private int numSector;
+  private StockQuoteList searchResults;
+  private StockQuoteList sector;

public StockResponse(StockQuoteList searchResults, StockQuoteList favorites,
-      int numSearchResults, int numFavorites, int cash) {
+ StockQuoteList sector, int numSearchResults, int numFavorites, int numSector, int cash) {
     this.searchResults = searchResults;
     this.favorites = favorites;
+    this.sector = sector;
     this.numSearchResults = numSearchResults;
     this.numFavorites = numFavorites;
+    this.numSector = numSector;
     this.cash = cash;
   }
+
+  /**
+   * Used for RPC.
+   */
+  StockResponse() {
+  }

   public int getCash() {
     return cash;
@@ -54,6 +57,13 @@
   public StockQuoteList getFavorites() {
     return favorites;
   }
+
+  /**
+   * The sum of cash available and portfolio value.
+   */
+  public int getNetWorth() {
+    return cash + favorites.getValue();
+  }

   public int getNumFavorites() {
     return numFavorites;
@@ -62,8 +72,16 @@
   public int getNumSearchResults() {
     return numSearchResults;
   }
+
+  public int getNumSector() {
+    return numSector;
+  }

   public StockQuoteList getSearchResults() {
     return searchResults;
   }
-}
+
+  public StockQuoteList getSector() {
+    return sector;
+  }
+}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeNodeView.java Fri Mar 5 07:05:48 2010 +++ /trunk/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeNodeView.java Wed Mar 10 05:41:10 2010
@@ -27,7 +27,7 @@
 import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.dom.client.Style.Display;
 import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.UIObject;

 import java.util.ArrayList;
 import java.util.HashMap;
@@ -39,7 +39,7 @@
  *
  * @param <T> the type that this {...@link TreeNodeView} contains
  */
-public abstract class TreeNodeView<T> extends Composite implements TreeNode<T> { +public abstract class TreeNodeView<T> extends UIObject implements TreeNode<T> {

   /**
    * The element used in place of an image when a node has no children.
=======================================
--- /trunk/bikeshed/war/Stocks.html     Thu Feb 18 16:05:09 2010
+++ /trunk/bikeshed/war/Stocks.html     Wed Mar 10 05:41:10 2010
@@ -15,18 +15,5 @@
         in order for this application to display correctly.
       </div>
     </noscript>
-
-    <h1>Data Backed Widgets Sample</h1>
-    <table align="center">
-      <tr>
- <td colspan="2" style="font-weight:bold;">Enter a search query:</td>
-      </tr>
-      <tr>
-        <td id="queryFieldContainer"></td>
-      </tr>
-      <tr>
-        <td colspan="2" style="color:red;" id="errorLabelContainer"></td>
-      </tr>
-    </table>
   </body>
 </html>

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to