Add multiplayer status messages to stock sample


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7722 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/bikeshed/src/com/google/gwt/bikeshed/list/shared/AbstractListModel.java b/bikeshed/src/com/google/gwt/bikeshed/list/shared/AbstractListModel.java
index f46dba0..7152c27 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/list/shared/AbstractListModel.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/shared/AbstractListModel.java
@@ -151,6 +151,10 @@
   protected void updateViewData(int start, int length, List<T> values) {
     int end = start + length;
     for (DefaultListRegistration reg : registrations) {
+      // Inform the views if there is no data
+      if (values.size() == 0) {
+        reg.getHandler().onSizeChanged(new SizeChangeEvent(0, true));
+      }
       int curStart = reg.getStart();
       int curLength = reg.getLength();
       int curEnd = curStart + curLength;
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/PlayerScoresWidget.java b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/PlayerScoresWidget.java
index a429f2f..14a0067 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/PlayerScoresWidget.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/PlayerScoresWidget.java
@@ -26,6 +26,8 @@
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.Widget;
 
+import java.util.List;
+
 /**
  * Widget to display player scores.
  */
@@ -49,6 +51,14 @@
       sb.append(StockSample.getFormattedPrice(value.getNetWorth()));
       sb.append("<br><b>Cash: </b>");
       sb.append(StockSample.getFormattedPrice(value.getCash()));
+      
+      List<String> status = value.getStatus();
+      if (status != null) {
+        for (String s : status) {
+          sb.append("<br>");
+          sb.append(s);
+        }
+      }
       sb.append("</div>");
     }
   }
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/PlayerScoresWidget.ui.xml b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/PlayerScoresWidget.ui.xml
index 880366e..2ef659a 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/PlayerScoresWidget.ui.xml
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/PlayerScoresWidget.ui.xml
@@ -9,7 +9,7 @@
 
   <g:DockLayoutPanel unit='EM'>
     <g:north size='2'>
-      <g:Label styleName='{common.header}'>Everyone Else</g:Label>
+      <g:Label styleName='{common.header}'>Player Status</g:Label>
     </g:north>
 
     <g:center>
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java
index a7d8e19..619feff 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java
@@ -187,12 +187,7 @@
     // Update the favorites list.
     updateFavorites(response);
     updateSector(response);
-
-    // Update the player scores.
-    List<PlayerInfo> playerScores = response.getPlayers();
-    int numPlayers = playerScores.size();
-    playerScoresListModel.updateDataSize(numPlayers, true);
-    playerScoresListModel.updateViewData(0, numPlayers, playerScores);
+    updatePlayerScores(response);
 
     // Update available cash.
     int cash = response.getCash();
@@ -226,6 +221,7 @@
 
             public void onSuccess(StockResponse response) {
               updateFavorites(response);
+              updatePlayerScores(response);
             }
           });
     } else {
@@ -237,6 +233,7 @@
 
             public void onSuccess(StockResponse response) {
               updateFavorites(response);
+              updatePlayerScores(response);
             }
           });
     }
@@ -317,27 +314,6 @@
     });
   }
 
-  public void updateFavorites(StockResponse response) {
-    // Update the favorites list.
-    StockQuoteList favorites = response.getFavorites();
-    favoritesListModel.updateDataSize(response.getNumFavorites(), true);
-    favoritesListModel.updateViewData(favorites.getStartIndex(),
-        favorites.size(), favorites);
-  }
-
-  public void updateSector(StockResponse response) {
-    // Update the sector list.
-    StockQuoteList sectorList = response.getSector();
-    if (sectorList != null) {
-      SectorListModel sectorListModel = treeModel.getSectorListModel(getSectorName());
-      if (sectorListModel != null) {
-        sectorListModel.updateDataSize(response.getNumSector(), true);
-        sectorListModel.updateViewData(sectorList.getStartIndex(),
-            sectorList.size(), sectorList);
-      }
-    }
-  }
-
   @UiFactory
   FavoritesWidget createFavoritesWidget() {
     return new FavoritesWidget(favoritesListModel);
@@ -393,4 +369,33 @@
     Window.alert(displayMessage);
     return true;
   }
+
+  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 updatePlayerScores(StockResponse response) {
+    // Update the player scores.
+    List<PlayerInfo> playerScores = response.getPlayers();
+    int numPlayers = playerScores.size();
+    playerScoresListModel.updateDataSize(numPlayers, true);
+    playerScoresListModel.updateViewData(0, numPlayers, playerScores);
+  }
+
+  private void updateSector(StockResponse response) {
+    // Update the sector list.
+    StockQuoteList sectorList = response.getSector();
+    if (sectorList != null) {
+      SectorListModel sectorListModel = treeModel.getSectorListModel(getSectorName());
+      if (sectorListModel != null) {
+        sectorListModel.updateDataSize(response.getNumSector(), true);
+        sectorListModel.updateViewData(sectorList.getStartIndex(),
+            sectorList.size(), sectorList);
+      }
+    }
+  }
 }
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/TransactionTreeViewModel.java b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/TransactionTreeViewModel.java
index 5bb44db..4983262 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/TransactionTreeViewModel.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/TransactionTreeViewModel.java
@@ -93,7 +93,6 @@
     this.transactionListListModelsByTicker = transactionListListModelsByTicker;
   }
   
-  @SuppressWarnings("unused")
   public <T> NodeInfo<?> getNodeInfo(T value, final TreeNode<T> treeNode) {
     if (value == null) {
       return new TreeViewModel.DefaultNodeInfo<String>(topLevelListListModel,
@@ -155,8 +154,12 @@
     return sectorListModels.get(value);
   }
 
-  public boolean isLeaf(Object value) {
-    return value instanceof Transaction ||
-      "Buy".equals(value) || "Sell".equals(value);
+  public boolean isLeaf(Object value, final TreeNode<?> parentNode) {
+    if (value instanceof Transaction ||
+      "Buy".equals(value) || "Sell".equals(value)) {
+      return true;
+    }
+    
+    return false;
   }
 }
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/server/StockServiceImpl.java b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/server/StockServiceImpl.java
index 17e09c2..b75dba1 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/server/StockServiceImpl.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/server/StockServiceImpl.java
@@ -147,7 +147,7 @@
       return null;
     }
   }
-
+  
   /**
    * A mapping of usernames to {@link PlayerStatus}.
    */
@@ -158,6 +158,7 @@
     PlayerStatus player = ensurePlayer();
     player.addFavorite(ticker);
     Result favorites = queryFavorites(favoritesRange);
+    player.addStatus(player.getDisplayName() + " added " + ticker + " to favorites");
     return createStockResponse(player, null, favorites, null, null);
   }
 
@@ -197,6 +198,7 @@
     PlayerStatus player = ensurePlayer();
     player.removeFavorite(ticker);
     Result favorites = queryFavorites(favoritesRange);
+    player.addStatus(player.getDisplayName() + " removed " + ticker + " from favorites");
     return createStockResponse(player, null, favorites, null, null);
   }
 
@@ -217,10 +219,16 @@
     // Perform the transaction with the user.
     int quantity = transaction.getQuantity();
     int price = quote.getPrice();
+    
+    PlayerStatus player = ensurePlayer();
     if (transaction.isBuy()) {
-      ensurePlayer().buy(ticker, quantity, price);
+      player.buy(ticker, quantity, price);
+      player.addStatus(player.getDisplayName() + " bought " + quantity +
+          " share" + ((quantity == 1) ? "" : "s") + " of " + ticker);
     } else {
-      ensurePlayer().sell(ticker, quantity, price);
+      player.sell(ticker, quantity, price);
+      player.addStatus(player.getDisplayName() + " sold " + quantity +
+          " share" + ((quantity == 1) ? "" : "s") + " of " + ticker);
     }
 
     return new Transaction(transaction.isBuy(), ticker, quantity, price);
@@ -253,11 +261,11 @@
     player.setStockValue(favorites.quotes.getValue());
 
     // Create a stock response.
-    List<PlayerInfo> playerScores = new ArrayList<PlayerInfo>();
+    List<PlayerInfo> playerInfo = new ArrayList<PlayerInfo>();
     for (PlayerStatus curPlayer : players.values()) {
-      playerScores.add(curPlayer.copy());
+      playerInfo.add(curPlayer.copy());
     }
-    Collections.sort(playerScores, new Comparator<PlayerInfo>() {
+    Collections.sort(playerInfo, new Comparator<PlayerInfo>() {
       public int compare(PlayerInfo o1, PlayerInfo o2) {
         // Reverse sort so top player is first.
         return o2.getNetWorth() - o1.getNetWorth();
@@ -266,7 +274,7 @@
     StockResponse response = new StockResponse(player.copy(),
         searchResults.quotes, favorites.quotes, sectorName != null ? sectorName
             : null, sectorResults.quotes, searchResults.numRows,
-        favorites.numRows, sectorResults.numRows, playerScores);
+        favorites.numRows, sectorResults.numRows, playerInfo);
 
     return response;
   }
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/PlayerInfo.java b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/PlayerInfo.java
index 302e898..4738bc9 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/PlayerInfo.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/PlayerInfo.java
@@ -16,11 +16,15 @@
 package com.google.gwt.bikeshed.sample.stocks.shared;
 
 import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Information about a single player.
  */
 public class PlayerInfo implements Serializable {
+  
+  private static final int MAX_STATUS = 5;
 
   /**
    * The initial amount of cash that the player starts with, in cents.
@@ -37,6 +41,8 @@
    */
   private String name;
 
+  private LinkedList<String> status;
+  
   /**
    * The net worth of the player in cents.
    */
@@ -51,11 +57,22 @@
    */
   PlayerInfo() {
   }
+  
+  public void addStatus(String message) {
+    if (status == null) {
+      status = new LinkedList<String>();
+    }
+    status.add(message);
+    if (status.size() > MAX_STATUS) {
+      status.removeFirst();
+    }
+  }
 
   public PlayerInfo copy() {
     PlayerInfo copy = new PlayerInfo(name);
     copy.setCash(cash);
     copy.setStockValue(stockValue);
+    copy.setStatus(status);
     return copy;
   }
 
@@ -100,6 +117,10 @@
     return cash + stockValue;
   }
 
+  public List<String> getStatus() {
+    return status;
+  }
+  
   /**
    * Get the value of this player's stock.
    * 
@@ -126,4 +147,8 @@
   protected void setStockValue(int value) {
     this.stockValue = value;
   }
+
+  private void setStatus(List<String> status) {
+    this.status = status == null ? null : new LinkedList<String>(status);
+  }
 }
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockResponse.java b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockResponse.java
index 0a6bed1..3ba1446 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockResponse.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/shared/StockResponse.java
@@ -34,12 +34,12 @@
   private StockQuoteList sector;
   private String sectorName;
   private PlayerInfo player;
-  private List<PlayerInfo> players;
+  private List<PlayerInfo> playerInfo;
 
   public StockResponse(PlayerInfo player, StockQuoteList searchResults,
       StockQuoteList favorites, String sectorName, StockQuoteList sector,
       int numSearchResults, int numFavorites, int numSector,
-      List<PlayerInfo> players) {
+      List<PlayerInfo> playerInfo) {
     this.player = player;
     this.searchResults = searchResults;
     this.favorites = favorites;
@@ -48,7 +48,7 @@
     this.numSearchResults = numSearchResults;
     this.numFavorites = numFavorites;
     this.numSector = numSector;
-    this.players = players;
+    this.playerInfo = playerInfo;
   }
 
   /**
@@ -90,7 +90,7 @@
    * @return the ordered list of all players
    */
   public List<PlayerInfo> getPlayers() {
-    return players;
+    return playerInfo;
   }
 
   public StockQuoteList getSearchResults() {
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/tree/client/MyTreeViewModel.java b/bikeshed/src/com/google/gwt/bikeshed/sample/tree/client/MyTreeViewModel.java
index c0aaba5..a4ed1da 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/sample/tree/client/MyTreeViewModel.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/tree/client/MyTreeViewModel.java
@@ -103,7 +103,7 @@
     throw new IllegalArgumentException("Unsupported object type: " + type);
   }
 
-  public boolean isLeaf(Object value) {
+  public boolean isLeaf(Object value, TreeNode<?> parentNode) {
     return value instanceof Integer;
   }
 
diff --git a/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeNodeView.java b/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeNodeView.java
index 0e24b53..7c871f8 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeNodeView.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeNodeView.java
@@ -88,7 +88,7 @@
       sb.append("px;\">");
       if (savedViews.get(idx) != null) {
         sb.append(tree.getOpenImageHtml(imageLeft));
-      } else if (model.isLeaf(childValue)) {
+      } else if (model.isLeaf(childValue, this)) {
         sb.append(LEAF_IMAGE);
       } else {
         sb.append(tree.getClosedImageHtml(imageLeft));
diff --git a/bikeshed/src/com/google/gwt/bikeshed/tree/client/StandardTreeNodeView.java b/bikeshed/src/com/google/gwt/bikeshed/tree/client/StandardTreeNodeView.java
index f7a53c4..7fa56eb 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/tree/client/StandardTreeNodeView.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/tree/client/StandardTreeNodeView.java
@@ -73,7 +73,7 @@
       sb.append("px;\">");
       if (savedViews.get(idx) != null) {
         sb.append(tree.getOpenImageHtml(0));
-      } else if (model.isLeaf(childValue)) {
+      } else if (model.isLeaf(childValue, this)) {
         sb.append(LEAF_IMAGE);
       } else {
         sb.append(tree.getClosedImageHtml(0));
diff --git a/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeNodeView.java b/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeNodeView.java
index 98833de..4502c97 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeNodeView.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeNodeView.java
@@ -425,6 +425,10 @@
       }
 
       public void onSizeChanged(SizeChangeEvent event) {
+        if (event.getSize() == 0 && event.isExact()) {
+          // Close the node
+          setState(false, false);
+        }
       }
     });
     listReg.setRangeOfInterest(0, 100);
diff --git a/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeViewModel.java b/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeViewModel.java
index 14f1656..b0ca0ed 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeViewModel.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/tree/client/TreeViewModel.java
@@ -128,7 +128,9 @@
    * Check if the value is known to be a leaf node.
    * 
    * @param value the value at the node
-   * @return true if the node is known to be a leaf node, false if not
+   * @param treeNode the {@link TreeNode} that contains the value
+   *
+   * @return true if the node is known to be a leaf node, false otherwise
    */
-  boolean isLeaf(Object value);
+  boolean isLeaf(Object value, TreeNode<?> treeNode);
 }