Add convenience classes and method to simplify demo code.

Review at http://gwt-code-reviews.appspot.com/299801

Review by: jgw@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7846 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/bikeshed/src/com/google/gwt/bikeshed/cells/client/TextCell.java b/bikeshed/src/com/google/gwt/bikeshed/cells/client/TextCell.java
index aff70e4..f4839e5 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/cells/client/TextCell.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/cells/client/TextCell.java
@@ -20,6 +20,18 @@
  */
 public class TextCell extends Cell<String, Void> {
 
+  private static TextCell instance;
+
+  public static TextCell getInstance() {
+    if (instance == null) {
+      instance = new TextCell();
+    }
+    return instance;
+  }
+
+  private TextCell() {
+  }
+
   @Override
   public void render(String value, Void viewData, StringBuilder sb) {
     if (value != null) {
diff --git a/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java b/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java
index cf8be6a..599c9ec 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java
@@ -110,6 +110,10 @@
     addColumn(col, header, null);
   }
 
+  public void addColumn(Column<T, ?, ?> col, String headerString) {
+    addColumn(col, new TextHeader(headerString), null);
+  }
+
   // TODO: remove(Column)
   public void addColumn(Column<T, ?, ?> col, Header<?> header, Header<?> footer) {
     headers.add(header);
diff --git a/bikeshed/src/com/google/gwt/bikeshed/list/client/SimpleColumn.java b/bikeshed/src/com/google/gwt/bikeshed/list/client/SimpleColumn.java
new file mode 100644
index 0000000..9ba3632
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/client/SimpleColumn.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.bikeshed.list.client;
+
+import com.google.gwt.bikeshed.cells.client.Cell;
+
+/**
+ * A column that does not make use of view data.
+ *
+ * @param <T> the row type
+ * @param <C> the column type
+ */
+public abstract class SimpleColumn<T, C>  extends Column<T, C, Void> {
+
+  public SimpleColumn(Cell<C, Void> cell, HasKey<T> hasKey) {
+    super(cell, hasKey);
+  }
+
+  public SimpleColumn(Cell<C, Void> cell) {
+    super(cell);
+  }
+}
diff --git a/bikeshed/src/com/google/gwt/bikeshed/list/client/TextColumn.java b/bikeshed/src/com/google/gwt/bikeshed/list/client/TextColumn.java
new file mode 100644
index 0000000..f053998
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/client/TextColumn.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.bikeshed.list.client;
+
+import com.google.gwt.bikeshed.cells.client.TextCell;
+
+/**
+ * A column that displays its contents with a {@link TextCell} and does not make
+ * use of view data.
+
+ * @param <T> the row type
+ */
+public abstract class TextColumn<T> extends Column<T, String, Void> {
+
+  public TextColumn(HasKey<T> hasKey) {
+    super(TextCell.getInstance(), hasKey);
+  }
+
+  public TextColumn() {
+    super(TextCell.getInstance());
+  }
+}
diff --git a/bikeshed/src/com/google/gwt/bikeshed/list/client/TextHeader.java b/bikeshed/src/com/google/gwt/bikeshed/list/client/TextHeader.java
index 05ab116..8dadbf9 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/list/client/TextHeader.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/client/TextHeader.java
@@ -23,7 +23,7 @@
 public class TextHeader extends Header<String> {
 
   public TextHeader(String text) {
-    super(new TextCell());
+    super(TextCell.getInstance());
     setValue(text);
   }
 }
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/mail/client/MailSample.java b/bikeshed/src/com/google/gwt/sample/bikeshed/mail/client/MailSample.java
index d85f87c..8e90367 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/mail/client/MailSample.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/mail/client/MailSample.java
@@ -17,10 +17,9 @@
 
 import com.google.gwt.bikeshed.cells.client.CheckboxCell;
 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.Header;
 import com.google.gwt.bikeshed.list.client.PagingTableListView;
+import com.google.gwt.bikeshed.list.client.SimpleColumn;
+import com.google.gwt.bikeshed.list.client.TextColumn;
 import com.google.gwt.bikeshed.list.shared.ListListModel;
 import com.google.gwt.bikeshed.list.shared.SelectionModel.DefaultSelectionModel;
 import com.google.gwt.core.client.EntryPoint;
@@ -43,7 +42,7 @@
 /**
  * A demo of selection features.
  */
-public class MailSample implements EntryPoint {
+public class MailSample implements EntryPoint, ClickHandler {
 
   class MailSelectionModel extends DefaultSelectionModel<Message> {
     private static final int ALL = 0;
@@ -53,6 +52,7 @@
     private static final int SUBJECT = 4;
     private static final int UNREAD = 5;
 
+    // Use a TreeMap in order to get sorted diagnostic output
     private Map<Integer, Boolean> exceptions = new TreeMap<Integer, Boolean>();
 
     private String search;
@@ -65,11 +65,12 @@
       if (exception != null) {
         return exception.booleanValue();
       }
+      // If not in exceptions, return the default
       return isDefaultSelected(object);
     }
 
     public void setSearch(String search) {
-      this.search = search.toLowerCase();
+      this.search = canonicalize(search);
       updateListeners();
     }
     
@@ -161,6 +162,10 @@
       }      
     }
 
+    private String canonicalize(String input) {
+      return input.toUpperCase();
+    }
+
     private boolean isDefaultSelected(Message object) {
       switch (type) {
         case NONE:
@@ -175,12 +180,12 @@
           if (search == null || search.length() == 0) {
             return false;
           }
-          return object.getSender().toLowerCase().contains(search);
+          return canonicalize(object.getSender()).contains(search);
         case SUBJECT:
           if (search == null || search.length() == 0) {
             return false;
           }
-          return object.getSubject().toLowerCase().contains(search);
+          return canonicalize(object.getSubject()).contains(search);
         default:
           throw new IllegalStateException("type = " + type);
       }
@@ -253,11 +258,41 @@
       "Rolex Watches", "Re: Re: yo bud", "Important notice"
   };
 
+  private Button allButton = new Button("Select All");
+  private Button allOnPageButton = new Button("Select All On This Page");
+  private Button noneButton = new Button("Select None");
+  private Button readButton = new Button("Select Read");
   private Label selectionLabel = new Label();
+  private MailSelectionModel selectionModel = new MailSelectionModel();
+  private Button senderButton = new Button("Search Senders");
+  private Button subjectButton = new Button("Search Subject");
+
+  private PagingTableListView<Message> table;
+
+  private Button unreadButton = new Button("Select Unread");
+
+  // Handle events for all buttons here in order to avoid creating multiple
+  // ClickHandlers
+  public void onClick(ClickEvent event) {
+    Button source = (Button) event.getSource();
+    if (source == noneButton) {
+      selectionModel.setType(MailSelectionModel.NONE);
+    } else if (source == allOnPageButton) {
+      selectionModel.setSelected(table.getDisplayedItems(), true);
+    } else if (source == allButton) {
+      selectionModel.setType(MailSelectionModel.ALL);
+    } else if (source == readButton) {
+      selectionModel.setType(MailSelectionModel.READ);
+    } else if (source == unreadButton) {
+      selectionModel.setType(MailSelectionModel.UNREAD);
+    } else if (source == senderButton) {
+      selectionModel.setType(MailSelectionModel.SENDER);
+    } else if (source == subjectButton) {
+      selectionModel.setType(MailSelectionModel.SUBJECT);
+    }
+  }
 
   public void onModuleLoad() {
-    TextCell textCell = new TextCell();
-
     ListListModel<Message> listModel = new ListListModel<Message>();
     List<Message> messages = listModel.getList();
     Random rand = new Random();
@@ -269,61 +304,48 @@
       messages.add(message);
     }
 
-    final MailSelectionModel selectionModel = new MailSelectionModel();
+    table = new PagingTableListView<Message>(listModel, 10);
+    table.setSelectionModel(selectionModel);
 
-    final PagingTableListView<Message> table = new PagingTableListView<Message>(
-        listModel, 10);
-
-    Column<Message, Boolean, Void> selectedColumn = new Column<Message, Boolean, Void>(
+    // The state of the checkbox is taken from the selection model
+    SimpleColumn<Message, Boolean> selectedColumn = new SimpleColumn<Message, Boolean>(
         new CheckboxCell()) {
       @Override
       public Boolean getValue(Message object) {
         return selectionModel.isSelected(object);
       }
     };
+    // Update the selection model when the checkbox is changed manually
     selectedColumn.setFieldUpdater(new FieldUpdater<Message, Boolean, Void>() {
       public void update(int index, Message object, Boolean value, Void viewData) {
         selectionModel.setSelected(object, value);
       }
     });
-    Header<String> selectedHeader = new Header<String>(textCell);
-    selectedHeader.setValue("Selected");
-    table.addColumn(selectedColumn, selectedHeader);
+    table.addColumn(selectedColumn, "Selected");
 
-    Column<Message, String, Void> isReadColumn = new Column<Message, String, Void>(
-        textCell) {
+    TextColumn<Message> isReadColumn = new TextColumn<Message>() {
       @Override
       public String getValue(Message object) {
         return object.isRead ? "read" : "unread";
       }
     };
-    Header<String> isReadHeader = new Header<String>(textCell);
-    isReadHeader.setValue("Read");
-    table.addColumn(isReadColumn, isReadHeader);
+    table.addColumn(isReadColumn, "Read");
 
-    Column<Message, String, Void> senderColumn = new Column<Message, String, Void>(
-        new TextCell()) {
+    TextColumn<Message> senderColumn = new TextColumn<Message>() {
       @Override
       public String getValue(Message object) {
         return object.getSender();
       }
     };
-    Header<String> senderHeader = new Header<String>(textCell);
-    senderHeader.setValue("Sender");
-    table.addColumn(senderColumn, senderHeader);
+    table.addColumn(senderColumn, "Sender");
 
-    Column<Message, String, Void> subjectColumn = new Column<Message, String, Void>(
-        textCell) {
+    TextColumn<Message> subjectColumn = new TextColumn<Message>() {
       @Override
       public String getValue(Message object) {
         return object.getSubject();
       }
     };
-    Header<String> subjectHeader = new Header<String>(textCell);
-    subjectHeader.setValue("Subject");
-    table.addColumn(subjectColumn, subjectHeader);
-
-    table.setSelectionModel(selectionModel);
+    table.addColumn(subjectColumn, "Subject");
     
     Label searchLabel = new Label("Search Sender or Subject:");
     final TextBox searchBox = new TextBox();
@@ -333,55 +355,13 @@
       }
     });
 
-    Button noneButton = new Button("Select None");
-    Button allOnPageButton = new Button("Select All On This Page");
-    Button allButton = new Button("Select All");
-    Button readButton = new Button("Select Read");
-    Button unreadButton = new Button("Select Unread");
-    Button senderButton = new Button("Search Senders");
-    Button subjectButton = new Button("Search Subject");
-
-    noneButton.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        selectionModel.setType(MailSelectionModel.NONE);
-      }
-    });
-
-    allOnPageButton.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        selectionModel.setSelected(table.getDisplayedItems(), true);
-      }
-    });
-
-    allButton.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        selectionModel.setType(MailSelectionModel.ALL);
-      }
-    });
-
-    readButton.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        selectionModel.setType(MailSelectionModel.READ);
-      }
-    });
-
-    unreadButton.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        selectionModel.setType(MailSelectionModel.UNREAD);
-      }
-    });
-    
-    senderButton.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        selectionModel.setType(MailSelectionModel.SENDER);
-      }
-    });
-    
-    subjectButton.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        selectionModel.setType(MailSelectionModel.SUBJECT);
-      }
-    });
+    noneButton.addClickHandler(this);
+    allOnPageButton.addClickHandler(this);
+    allButton.addClickHandler(this);
+    readButton.addClickHandler(this);
+    unreadButton.addClickHandler(this);
+    senderButton.addClickHandler(this);
+    subjectButton.addClickHandler(this);
     
     HorizontalPanel panel = new HorizontalPanel();
     panel.add(searchLabel);
@@ -398,6 +378,7 @@
     RootPanel.get().add(unreadButton);
     RootPanel.get().add(subjectButton);
     RootPanel.get().add(senderButton);
+    RootPanel.get().add(new HTML("<hr>"));
     RootPanel.get().add(selectionLabel);
   }
 }
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/simplecelllist/client/SimpleCellListSample.java b/bikeshed/src/com/google/gwt/sample/bikeshed/simplecelllist/client/SimpleCellListSample.java
index 4fb0590..6f5bd0f 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/simplecelllist/client/SimpleCellListSample.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/simplecelllist/client/SimpleCellListSample.java
@@ -36,7 +36,8 @@
       list.add("" + (i * 1000));
     }
 
-    SimpleCellList<String> simpleCellList = new SimpleCellList<String>(listModel, new TextCell(), 10, 5);
+    SimpleCellList<String> simpleCellList =
+      new SimpleCellList<String>(listModel, TextCell.getInstance(), 10, 5);
 
     RootPanel.get().add(simpleCellList);
 
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/Columns.java b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/Columns.java
index ae4ed2d..ad5ca05 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/Columns.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/Columns.java
@@ -20,7 +20,7 @@
 import com.google.gwt.bikeshed.cells.client.CurrencyCell;
 import com.google.gwt.bikeshed.cells.client.ProfitLossCell;
 import com.google.gwt.bikeshed.cells.client.TextCell;
-import com.google.gwt.bikeshed.list.client.Column;
+import com.google.gwt.bikeshed.list.client.SimpleColumn;
 import com.google.gwt.sample.bikeshed.stocks.shared.StockQuote;
 import com.google.gwt.sample.bikeshed.stocks.shared.Transaction;
 
@@ -29,7 +29,7 @@
  */
 public class Columns {
 
-  static Column<StockQuote, String, Void> buyColumn = new Column<StockQuote, String, Void>(
+  static SimpleColumn<StockQuote, String> buyColumn = new SimpleColumn<StockQuote, String>(
       new ButtonCell()) {
     @Override
     public String getValue(StockQuote object) {
@@ -37,7 +37,7 @@
     }
   };
 
-  static Column<StockQuote, String, Void> changeColumn = new Column<StockQuote, String, Void>(
+  static SimpleColumn<StockQuote, String> changeColumn = new SimpleColumn<StockQuote, String>(
       new ChangeCell()) {
     @Override
     public String getValue(StockQuote object) {
@@ -45,7 +45,7 @@
     }
   };
 
-  static Column<StockQuote, Integer, Void> dollarsColumn = new Column<StockQuote, Integer, Void>(
+  static SimpleColumn<StockQuote, Integer> dollarsColumn = new SimpleColumn<StockQuote, Integer>(
       new CurrencyCell()) {
     @Override
     public Integer getValue(StockQuote object) {
@@ -53,7 +53,7 @@
     }
   };
 
-  static Column<StockQuote, Boolean, Void> favoriteColumn = new Column<StockQuote, Boolean, Void>(
+  static SimpleColumn<StockQuote, Boolean> favoriteColumn = new SimpleColumn<StockQuote, Boolean>(
       new CheckboxCell()) {
     @Override
     public Boolean getValue(StockQuote object) {
@@ -64,7 +64,7 @@
   // TODO - use an ellipsis cell
   static HighlightingTextCell nameCell = new HighlightingTextCell();
 
-  static Column<StockQuote, String, Void> nameColumn = new Column<StockQuote, String, Void>(
+  static SimpleColumn<StockQuote, String> nameColumn = new SimpleColumn<StockQuote, String>(
       nameCell) {
     @Override
     public String getValue(StockQuote object) {
@@ -72,7 +72,7 @@
     }
   };
 
-  static Column<StockQuote, Integer, Void> priceColumn = new Column<StockQuote, Integer, Void>(
+  static SimpleColumn<StockQuote, Integer> priceColumn = new SimpleColumn<StockQuote, Integer>(
       new CurrencyCell()) {
     @Override
     public Integer getValue(StockQuote object) {
@@ -80,7 +80,7 @@
     }
   };
 
-  static Column<StockQuote, Integer, Void> profitLossColumn = new Column<StockQuote, Integer, Void>(
+  static SimpleColumn<StockQuote, Integer> profitLossColumn = new SimpleColumn<StockQuote, Integer>(
       new ProfitLossCell()) {
     @Override
     public Integer getValue(StockQuote object) {
@@ -88,7 +88,7 @@
     }
   };
 
-  static Column<StockQuote, String, Void> sellColumn = new Column<StockQuote, String, Void>(
+  static SimpleColumn<StockQuote, String> sellColumn = new SimpleColumn<StockQuote, String>(
       new ButtonCell()) {
     @Override
     public String getValue(StockQuote object) {
@@ -96,16 +96,18 @@
     }
   };
 
-  static Column<StockQuote, String, Void> sharesColumn = new Column<StockQuote, String, Void>(
-      new TextCell()) {
+  static TextCell textCell = TextCell.getInstance();
+
+  static SimpleColumn<StockQuote, String> sharesColumn =
+    new SimpleColumn<StockQuote, String>(textCell) {
     @Override
     public String getValue(StockQuote object) {
       return "" + object.getSharesOwned();
     }
   };
 
-  static Column<Transaction, String, Void> subtotalColumn = new Column<Transaction, String, Void>(
-      new TextCell()) {
+  static SimpleColumn<Transaction, String> subtotalColumn =
+    new SimpleColumn<Transaction, String>(textCell) {
     @Override
     public String getValue(Transaction object) {
       int price = object.getActualPrice() * object.getQuantity();
@@ -114,16 +116,16 @@
     }
   };
 
-  static Column<StockQuote, String, Void> tickerColumn = new Column<StockQuote, String, Void>(
-      new TextCell()) {
+  static SimpleColumn<StockQuote, String> tickerColumn =
+    new SimpleColumn<StockQuote, String>(textCell) {
     @Override
     public String getValue(StockQuote object) {
       return object.getTicker();
     }
   };
 
-  static Column<Transaction, String, Void> transactionColumn = new Column<Transaction, String, Void>(
-      new TextCell()) {
+  static SimpleColumn<Transaction, String> transactionColumn =
+    new SimpleColumn<Transaction, String>(textCell) {
     @Override
     public String getValue(Transaction object) {
       return object.toString();
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/FavoritesWidget.java b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/FavoritesWidget.java
index 5253d60..7ef9774 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/FavoritesWidget.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/FavoritesWidget.java
@@ -16,7 +16,6 @@
 package com.google.gwt.sample.bikeshed.stocks.client;
 
 import com.google.gwt.bikeshed.list.client.PagingTableListView;
-import com.google.gwt.bikeshed.list.client.TextHeader;
 import com.google.gwt.bikeshed.list.shared.ListModel;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.sample.bikeshed.stocks.shared.StockQuote;
@@ -42,12 +41,12 @@
     this.model = model;
     initWidget(binder.createAndBindUi(this));
 
-    listView.addColumn(Columns.tickerColumn, new TextHeader("ticker"));
-    listView.addColumn(Columns.priceColumn, new TextHeader("price"));
-    listView.addColumn(Columns.changeColumn, new TextHeader("change"));
-    listView.addColumn(Columns.sharesColumn, new TextHeader("shares"));
-    listView.addColumn(Columns.dollarsColumn, new TextHeader("value"));
-    listView.addColumn(Columns.profitLossColumn, new TextHeader("profit/loss"));
+    listView.addColumn(Columns.tickerColumn, "ticker");
+    listView.addColumn(Columns.priceColumn, "price");
+    listView.addColumn(Columns.changeColumn, "change");
+    listView.addColumn(Columns.sharesColumn, "shares");
+    listView.addColumn(Columns.dollarsColumn, "value");
+    listView.addColumn(Columns.profitLossColumn, "profit/loss");
     listView.addColumn(Columns.buyColumn);
     listView.addColumn(Columns.sellColumn);
   }
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StockQueryWidget.java b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StockQueryWidget.java
index 1a6ef7a..c404c8c 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StockQueryWidget.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StockQueryWidget.java
@@ -16,7 +16,6 @@
 package com.google.gwt.sample.bikeshed.stocks.client;
 
 import com.google.gwt.bikeshed.list.client.PagingTableListView;
-import com.google.gwt.bikeshed.list.client.TextHeader;
 import com.google.gwt.bikeshed.list.shared.ListModel;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.KeyUpEvent;
@@ -48,10 +47,10 @@
     initWidget(binder.createAndBindUi(this));
 
     listView.addColumn(Columns.favoriteColumn);
-    listView.addColumn(Columns.tickerColumn, new TextHeader("ticker"));
-    listView.addColumn(Columns.nameColumn, new TextHeader("name"));
-    listView.addColumn(Columns.changeColumn, new TextHeader("change"));
-    listView.addColumn(Columns.priceColumn, new TextHeader("price"));
+    listView.addColumn(Columns.tickerColumn, "ticker");
+    listView.addColumn(Columns.nameColumn, "name");
+    listView.addColumn(Columns.changeColumn, "change");
+    listView.addColumn(Columns.priceColumn, "price");
     listView.addColumn(Columns.buyColumn);
 
     // Focus the cursor on the name field when the app loads
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksMobile.java b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksMobile.java
index 00e5394..2242c84 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksMobile.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksMobile.java
@@ -16,7 +16,6 @@
 package com.google.gwt.sample.bikeshed.stocks.client;
 
 import com.google.gwt.bikeshed.list.client.PagingTableListView;
-import com.google.gwt.bikeshed.list.client.TextHeader;
 import com.google.gwt.bikeshed.list.shared.AsyncListModel;
 import com.google.gwt.bikeshed.list.shared.Range;
 import com.google.gwt.core.client.GWT;
@@ -122,12 +121,12 @@
     PagingTableListView<StockQuote> favorite = new PagingTableListView<StockQuote>(
         favoritesListModel, 10);
 
-    favorite.addColumn(Columns.tickerColumn, new TextHeader("ticker"));
-    favorite.addColumn(Columns.priceColumn, new TextHeader("price"));
-    favorite.addColumn(Columns.changeColumn, new TextHeader("change"));
-    favorite.addColumn(Columns.sharesColumn, new TextHeader("shares"));
-    favorite.addColumn(Columns.dollarsColumn, new TextHeader("value"));
-    favorite.addColumn(Columns.profitLossColumn, new TextHeader("profit/loss"));
+    favorite.addColumn(Columns.tickerColumn, "ticker");
+    favorite.addColumn(Columns.priceColumn, "price");
+    favorite.addColumn(Columns.changeColumn, "change");
+    favorite.addColumn(Columns.sharesColumn, "shares");
+    favorite.addColumn(Columns.dollarsColumn, "value");
+    favorite.addColumn(Columns.profitLossColumn, "profit/loss");
 
     return favorite;
   }
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/TransactionTreeViewModel.java b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/TransactionTreeViewModel.java
index 26420b5..80fa0d5 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/TransactionTreeViewModel.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/TransactionTreeViewModel.java
@@ -96,7 +96,7 @@
   public <T> NodeInfo<?> getNodeInfo(T value, final TreeNode<T> treeNode) {
     if (value == null) {
       return new TreeViewModel.DefaultNodeInfo<String>(topLevelListListModel,
-          new TextCell());
+          TextCell.getInstance());
     } else if ("Favorites".equals(value)) {
       return new TreeViewModel.DefaultNodeInfo<StockQuote>(stockQuoteListModel,
           STOCK_QUOTE_CELL) {
@@ -144,7 +144,7 @@
       List<String> list = listModel.getList();
       list.add("Actions");
       list.add("History");
-      return new TreeViewModel.DefaultNodeInfo<String>(listModel, new TextCell());
+      return new TreeViewModel.DefaultNodeInfo<String>(listModel, TextCell.getInstance());
     }
 
     throw new IllegalArgumentException(value.toString());
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/validation/client/Validation.java b/bikeshed/src/com/google/gwt/sample/bikeshed/validation/client/Validation.java
index 2dabbdb..2635a48 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/validation/client/Validation.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/validation/client/Validation.java
@@ -16,10 +16,10 @@
 package com.google.gwt.sample.bikeshed.validation.client;
 
 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.HasKey;
 import com.google.gwt.bikeshed.list.client.PagingTableListView;
+import com.google.gwt.bikeshed.list.client.TextColumn;
 import com.google.gwt.bikeshed.list.shared.ListListModel;
 import com.google.gwt.core.client.EntryPoint;
 import com.google.gwt.user.client.Timer;
@@ -83,8 +83,7 @@
 
     PagingTableListView<Address> table = new PagingTableListView<Address>(
         listModel, 10);
-    Column<Address, String, Void> stateColumn = new Column<Address, String, Void>(
-        new TextCell()) {
+    TextColumn<Address> stateColumn = new TextColumn<Address>() {
       @Override
       public String getValue(Address object) {
         return object.state;
@@ -131,8 +130,7 @@
       }
     });
 
-    Column<Address, String, Void> messageColumn = new Column<Address, String, Void>(
-        new TextCell()) {
+    TextColumn<Address> messageColumn = new TextColumn<Address>() {
       @Override
       public String getValue(Address object) {
         return object.zipInvalid ? "Please fix the zip code" : "";
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/client/TableEntityListView.java b/bikeshed/src/com/google/gwt/sample/expenses/client/TableEntityListView.java
index a0d6356..2e5088d 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/client/TableEntityListView.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/client/TableEntityListView.java
@@ -15,10 +15,9 @@
  */
 package com.google.gwt.sample.expenses.client;
 
-import com.google.gwt.bikeshed.cells.client.TextCell;
-import com.google.gwt.bikeshed.list.client.Column;
-import com.google.gwt.bikeshed.list.client.Header;
 import com.google.gwt.bikeshed.list.client.PagingTableListView;
+import com.google.gwt.bikeshed.list.client.SimpleColumn;
+import com.google.gwt.bikeshed.list.client.TextColumn;
 import com.google.gwt.bikeshed.list.shared.ListListModel;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.HeadingElement;
@@ -43,8 +42,6 @@
 
    @UiField SimplePanel body;
    @UiField HeadingElement heading;
-   
-   private final TextCell textCell = new TextCell();
 
   public TableEntityListView() {
     initWidget(BINDER.createAndBindUi(this));
@@ -61,40 +58,33 @@
     
     PagingTableListView<Row> table = new PagingTableListView<Row>(model, 100);
     
-    Column<Row, Command, Void> showColumn =
-      new Column<Row, Command, Void>(new CommandCell("Show")) {
+    SimpleColumn<Row, Command> showColumn =
+      new SimpleColumn<Row, Command>(new CommandCell("Show")) {
       @Override
       public Command getValue(Row object) {
         return object.getShowDetailsCommand();
       }
     };
-    Header<String> showHeader = new Header<String>(textCell);
-    showHeader.setValue("Show");
-    table.addColumn(showColumn, showHeader);
+    table.addColumn(showColumn, "Show");
     
-    Column<Row, Command, Void> editColumn =
-      new Column<Row, Command, Void>(new CommandCell("Edit")) {
+    SimpleColumn<Row, Command> editColumn =
+      new SimpleColumn<Row, Command>(new CommandCell("Edit")) {
       @Override
       public Command getValue(Row object) {
         return object.getShowDetailsCommand();
       }
     };
-    Header<String> editHeader = new Header<String>(textCell);
-    editHeader.setValue("Show");
-    table.addColumn(editColumn, editHeader);
+    table.addColumn(editColumn, "Edit");
 
     for (int i = 0; i < columnNames.size(); i++) {
       final int index = i;
-      Column<Row, String, Void> column =
-        new Column<Row, String, Void>(textCell) {
+      TextColumn<Row> column = new TextColumn<Row>() {
         @Override
         public String getValue(Row object) {
           return object.getValues().get(index);
         }
       };
-      Header<String> header = new Header<String>(textCell);
-      header.setValue(columnNames.get(i));
-      table.addColumn(column, header);
+      table.addColumn(column, columnNames.get(index));
     }
     
     body.setWidget(table);