Fixes Issue #1082.
Updates the design on the mail sample and adds ImageBundles for
the sample's images.

Review by: bruce



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1075 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/AboutDialog.java b/samples/mail/src/com/google/gwt/sample/mail/client/AboutDialog.java
index 117e8f7..34190fb 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/AboutDialog.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/AboutDialog.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -18,11 +18,9 @@
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.DialogBox;
-import com.google.gwt.user.client.ui.DockPanel;
-import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.KeyboardListener;
+import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
 
 /**
@@ -30,43 +28,29 @@
  */
 public class AboutDialog extends DialogBox {
 
-  private static final String LOGO_IMAGE = "http://www.google.com/images/logo_sm.gif";
-
   public AboutDialog() {
     // Use this opportunity to set the dialog's caption.
     setText("About the Mail Sample");
 
-    // Create a DockPanel to contain the 'about' label and the 'OK' button.
-    DockPanel outer = new DockPanel();
-    outer.setSpacing(4);
+    // Create a VerticalPanel to contain the 'about' label and the 'OK' button.
+    VerticalPanel outer = new VerticalPanel();
 
-    outer.add(new Image(LOGO_IMAGE), DockPanel.WEST);
+    // Create the 'about' text and set a style name so we can style it with CSS.
+
+    HTML text = new HTML("This sample application demonstrates the "
+        + "construction of a complex user interface using GWT's built-in "
+        + "widgets.  Have a look at the code to see how easy it is to build "
+        + "your own apps!");
+    text.setStyleName("mail-AboutText");
+    outer.add(text);
 
     // Create the 'OK' button, along with a listener that hides the dialog
-    // when the button is clicked. Adding it to the 'south' position within
-    // the dock causes it to be placed at the bottom.
-    HorizontalPanel buttonPanel = new HorizontalPanel();
-    buttonPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
-    buttonPanel.add(new Button("Close", new ClickListener() {
+    // when the button is clicked.
+    outer.add(new Button("Close", new ClickListener() {
       public void onClick(Widget sender) {
         hide();
       }
     }));
-    outer.add(buttonPanel, DockPanel.SOUTH);
-
-    // Create the 'about' label. Placing it in the 'rest' position within the
-    // dock causes it to take up any remaining space after the 'OK' button
-    // has been laid out.
-    HTML text = new HTML(
-      "This sample application demonstrates the construction "
-        + "of a complex user interface using GWT's built-in widgets.  Have a look "
-        + "at the code to see how easy it is to build your own apps!");
-    text.setStyleName("mail-AboutText");
-    outer.add(text, DockPanel.CENTER);
-
-    // Add a bit of spacing and margin to the dock to keep the components from
-    // being placed too closely together.
-    outer.setSpacing(8);
 
     setWidget(outer);
   }
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/Contacts.java b/samples/mail/src/com/google/gwt/sample/mail/client/Contacts.java
index 1c6e407..dd7ab31 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/Contacts.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/Contacts.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -15,13 +15,15 @@
  */
 package com.google.gwt.sample.mail.client;
 
+import com.google.gwt.user.client.ImageBundle;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
 import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.SimplePanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
 
@@ -31,12 +33,21 @@
 public class Contacts extends Composite {
 
   /**
+   * An image bundle for this widget and an example of the use of @gwt.resource.
+   */
+  public interface Images extends ImageBundle {
+    /**
+     * @gwt.resource default_photo.jpg
+     */
+    AbstractImagePrototype defaultPhoto();
+  }
+
+  /**
    * Simple data structure representing a contact.
    */
   private class Contact {
     public String email;
     public String name;
-    public String photo = "default_photo.jpg";
 
     public Contact(String name, String email) {
       this.name = name;
@@ -62,7 +73,7 @@
 
       HorizontalPanel hp = new HorizontalPanel();
       hp.setSpacing(4);
-      hp.add(new Image(contact.photo));
+      hp.add(images.defaultPhoto().createImage());
       hp.add(inner);
 
       add(hp);
@@ -83,14 +94,19 @@
       new Contact("John von Neumann", "john@example.com")};
 
   private VerticalPanel panel = new VerticalPanel();
+  private final Images images;
 
-  public Contacts() {
+  public Contacts(Images images) {
+    SimplePanel outer = new SimplePanel();
+    outer.setWidget(panel);
+
+    this.images = images;
     // Add all the contacts to the list.
     for (int i = 0; i < contacts.length; ++i) {
       addContact(contacts[i]);
     }
 
-    initWidget(panel);
+    initWidget(outer);
     setStyleName("mail-Contacts");
   }
 
@@ -103,8 +119,8 @@
     link.addClickListener(new ClickListener() {
       public void onClick(Widget sender) {
         ContactPopup popup = new ContactPopup(contact);
-        int left = link.getAbsoluteLeft() + 32;
-        int top = link.getAbsoluteTop() + 8;
+        int left = link.getAbsoluteLeft() + 14;
+        int top = link.getAbsoluteTop() + 14;
         popup.setPopupPosition(left, top);
         popup.show();
       }
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/Mail.java b/samples/mail/src/com/google/gwt/sample/mail/client/Mail.java
index 0ccf3de..807ad20 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/Mail.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/Mail.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -16,6 +16,7 @@
 package com.google.gwt.sample.mail.client;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.core.client.GWT;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Window;
@@ -34,18 +35,30 @@
   private static Mail singleton;
 
   /**
+   * Instantiate an application-level image bundle. This object will provide
+   * programmatic access to all the images needed by widgets.
+   */
+  private static final Images images = (Images) GWT.create(Images.class);
+
+  /**
+   * An aggragate image bundle that pulls together all the images for this
+   * application into a single bundle.
+   */
+  public interface Images extends Shortcuts.Images, TopPanel.Images {
+  }
+
+  /**
    * Gets the singleton Mail instance.
    */
   public static Mail get() {
     return singleton;
   }
 
-  private TopPanel topPanel = new TopPanel();
+  private TopPanel topPanel = new TopPanel(images);
   private VerticalPanel rightPanel = new VerticalPanel();
   private MailList mailList;
   private MailDetail mailDetail = new MailDetail();
-
-  private Shortcuts shortcuts = new Shortcuts();
+  private Shortcuts shortcuts = new Shortcuts(images);
 
   /**
    * Displays the specified item.
@@ -102,11 +115,13 @@
     // Call the window resized handler to get the initial sizes setup. Doing
     // this in a deferred command causes it to occur after all widgets' sizes
     // have been computed by the browser.
-    DeferredCommand.add(new Command() {
+    DeferredCommand.addCommand(new Command() {
       public void execute() {
         onWindowResized(Window.getClientWidth(), Window.getClientHeight());
       }
     });
+
+    onWindowResized(Window.getClientWidth(), Window.getClientHeight());
   }
 
   public void onWindowResized(int width, int height) {
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/MailDetail.java b/samples/mail/src/com/google/gwt/sample/mail/client/MailDetail.java
index 5e11d87..964cc3c 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/MailDetail.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/MailDetail.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/MailItem.java b/samples/mail/src/com/google/gwt/sample/mail/client/MailItem.java
index f67b7df..a3a8d88 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/MailItem.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/MailItem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/MailItems.java b/samples/mail/src/com/google/gwt/sample/mail/client/MailItems.java
index 55fa53c..e38a8f0 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/MailItems.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/MailItems.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/MailList.java b/samples/mail/src/com/google/gwt/sample/mail/client/MailList.java
index 6924acb..7b10bc8 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/MailList.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/MailList.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -33,9 +33,9 @@
 
   private HTML countLabel = new HTML();
   private HTML newerButton = new HTML("<a href='javascript:;'>&lt; newer</a>",
-    true);
+      true);
   private HTML olderButton = new HTML("<a href='javascript:;'>older &gt;</a>",
-    true);
+      true);
   private int startIndex, selectedRow = -1;
   private FlexTable table = new FlexTable();
   private HorizontalPanel navBar = new HorizontalPanel();
@@ -43,7 +43,7 @@
   public MailList() {
     // Setup the table.
     table.setCellSpacing(0);
-    table.setCellPadding(2);
+    table.setCellPadding(0);
     table.setWidth("100%");
 
     // Hook up events.
@@ -53,8 +53,7 @@
 
     // Create the 'navigation' bar at the upper-right.
     HorizontalPanel innerNavBar = new HorizontalPanel();
-    innerNavBar.setStyleName("mail-ListNavBar");
-    innerNavBar.setSpacing(8);
+    navBar.setStyleName("mail-ListNavBar");
     innerNavBar.add(newerButton);
     innerNavBar.add(countLabel);
     innerNavBar.add(olderButton);
@@ -107,9 +106,9 @@
    */
   private void initTable() {
     // Create the header row.
-    table.setText(0, 0, "sender");
-    table.setText(0, 1, "email");
-    table.setText(0, 2, "subject");
+    table.setText(0, 0, "Sender");
+    table.setText(0, 1, "Email");
+    table.setText(0, 2, "Subject");
     table.setWidget(0, 3, navBar);
     table.getRowFormatter().setStyleName(0, "mail-ListHeader");
 
@@ -137,7 +136,7 @@
     if (item == null) {
       return;
     }
-    
+
     styleRow(selectedRow, false);
     styleRow(row, true);
 
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/Mailboxes.java b/samples/mail/src/com/google/gwt/sample/mail/client/Mailboxes.java
index aba1087..d6e6279 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/Mailboxes.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/Mailboxes.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -15,8 +15,11 @@
  */
 package com.google.gwt.sample.mail.client;
 
+import com.google.gwt.user.client.ImageBundle;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.Tree;
+import com.google.gwt.user.client.ui.TreeImages;
 import com.google.gwt.user.client.ui.TreeItem;
 
 /**
@@ -24,17 +27,42 @@
  */
 public class Mailboxes extends Composite {
 
-  private Tree tree = new Tree();
+  /**
+   * Specifies the images that will be bundled for this Composite and specify
+   * that tree's images should also be included in the same bundle.
+   */
+  public interface Images extends ImageBundle, TreeImages {
+    AbstractImagePrototype drafts();
 
-  public Mailboxes() {
-    TreeItem root = new TreeItem(imageItemHTML("home.gif", "foo@example.com"));
+    AbstractImagePrototype home();
+
+    AbstractImagePrototype inbox();
+
+    AbstractImagePrototype sent();
+
+    AbstractImagePrototype templates();
+
+    AbstractImagePrototype trash();
+  }
+
+  private Tree tree;
+
+  /**
+   * Constructs a new mailboxes widget with a bundle of images.
+   * 
+   * @param images a bundle that provides the images for this widget
+   */
+  public Mailboxes(Images images) {
+    tree = new Tree(images);
+    TreeItem root = new TreeItem(
+        imageItemHTML(images.home(), "foo@example.com"));
     tree.addItem(root);
 
-    addImageItem(root, "Inbox");
-    addImageItem(root, "Drafts");
-    addImageItem(root, "Templates");
-    addImageItem(root, "Sent");
-    addImageItem(root, "Trash");
+    addImageItem(root, "Inbox", images.inbox());
+    addImageItem(root, "Drafts", images.drafts());
+    addImageItem(root, "Templates", images.templates());
+    addImageItem(root, "Sent", images.sent());
+    addImageItem(root, "Trash", images.trash());
 
     root.setState(true);
     initWidget(tree);
@@ -47,8 +75,9 @@
    * @param root the tree item to which the new item will be added.
    * @param title the text associated with this item.
    */
-  private TreeItem addImageItem(TreeItem root, String title) {
-    TreeItem item = new TreeItem(imageItemHTML(title + ".gif", title));
+  private TreeItem addImageItem(TreeItem root, String title,
+      AbstractImagePrototype imageProto) {
+    TreeItem item = new TreeItem(imageItemHTML(imageProto, title));
     root.addItem(item);
     return item;
   }
@@ -60,8 +89,7 @@
    * @param title the title of the item
    * @return the resultant HTML
    */
-  private String imageItemHTML(String imageUrl, String title) {
-    return "<span><img style='margin-right:4px' src='" + imageUrl.toLowerCase()
-        + "'>" + title + "</span>";
+  private String imageItemHTML(AbstractImagePrototype imageProto, String title) {
+    return "<span>" + imageProto.getHTML() + title + "</span>";
   }
 }
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/Shortcuts.java b/samples/mail/src/com/google/gwt/sample/mail/client/Shortcuts.java
index e88151a..d0eadd4 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/Shortcuts.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/Shortcuts.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -15,8 +15,13 @@
  */
 package com.google.gwt.sample.mail.client;
 
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.StackPanel;
+import com.google.gwt.user.client.ui.Widget;
 
 /**
  * A composite that contains the shortcut stack panel on the left side. The
@@ -27,31 +32,113 @@
  */
 public class Shortcuts extends Composite {
 
-  private StackPanel stackPanel = new StackPanel();
+  /**
+   * An image bundle specifying the images for this Widget and aggragating
+   * images needed in child widgets.
+   */
+  public interface Images extends Contacts.Images, Mailboxes.Images {
+    AbstractImagePrototype contactsgroup();
 
-  public Shortcuts() {
+    AbstractImagePrototype leftCorner();
+
+    AbstractImagePrototype mailgroup();
+
+    AbstractImagePrototype rightCorner();
+
+    AbstractImagePrototype tasksgroup();
+  }
+  
+  private int nextHeaderIndex = 0;
+  
+  private StackPanel stackPanel = new StackPanel() {
+    public void onBrowserEvent(Event event) {
+      int oldIndex = getSelectedIndex();
+      super.onBrowserEvent(event);
+      int newIndex = getSelectedIndex();
+      if (oldIndex != newIndex) {
+        updateSelectedStyles(oldIndex, newIndex);
+      }
+    }
+  };
+
+  /**
+   * Constructs a new shortcuts widget using the specified images.
+   * 
+   * @param images a bundle that provides the images for this widget
+   */
+  public Shortcuts(Images images) {
     // Create the groups within the stack panel.
-    stackPanel.add(new Mailboxes(), createHeaderHTML("mailgroup.gif", "Mail"), true);
-    stackPanel.add(new Tasks(), createHeaderHTML("tasksgroup.gif", "Tasks"), true);
-    stackPanel.add(new Contacts(), createHeaderHTML("contactsgroup.gif", "Contacts"), true);
-
-    // Show the mailboxes group by default.
-    stackPanel.showStack(0);
-
+    add(images, new Mailboxes(images), images.mailgroup(), "Mail");
+    add(images, new Tasks(), images.tasksgroup(), "Tasks");
+    add(images, new Contacts(images), images.contactsgroup(), "Contacts");
+    
     initWidget(stackPanel);
   }
+  
+  protected void onLoad() {
+    // Show the mailboxes group by default.
+    stackPanel.showStack(0);
+    updateSelectedStyles(-1, 0);
+  }
 
+  private void add(Images images, Widget widget, AbstractImagePrototype imageProto,
+      String caption) {
+    widget.addStyleName("mail-StackContent");
+    stackPanel.add(widget, createHeaderHTML(images, imageProto, caption), true);
+  }
+
+  private String computeHeaderId(int index) {
+    return "header-" + this.hashCode() + "-" + index;
+  }
+  
   /**
    * Creates an HTML fragment that places an image & caption together, for use
    * in a group header.
    * 
-   * @param imageUrl the url of the icon image to be used
+   * @param imageProto an image prototype for an image
    * @param caption the group caption
    * @return the header HTML fragment
    */
-  private String createHeaderHTML(String imageUrl, String caption) {
-    return "<table align='left'><tr>" + "<td><img src='" + imageUrl + "'></td>"
-      + "<td style='vertical-align:middle'><b style='white-space:nowrap'>"
-      + caption + "</b></td>" + "</tr></table>";
+  private String createHeaderHTML(Images images,
+      AbstractImagePrototype imageProto, String caption) {
+    
+    boolean isTop = (nextHeaderIndex == 0);
+    String cssId = computeHeaderId(nextHeaderIndex);
+    nextHeaderIndex++;
+    
+    String captionHTML = "<table class='caption' cellpadding='0' cellspacing='0'>"
+        + "<tr><td class='lcaption'>" + imageProto.getHTML()
+        + "</td><td class='rcaption'><b style='white-space:nowrap'>" + caption 
+        + "</b></td></tr></table>";
+    
+    return "<table id='" + cssId + "' align='left' cellpadding='0' cellspacing='0'"
+        + (isTop ? " class='is-top'" : "" ) + "><tbody>"
+        + "<tr><td class='box-00'>" + images.leftCorner().getHTML() + "</td>"
+        + "<td class='box-10'>&nbsp;</td>"
+        + "<td class='box-20'>" + images.rightCorner().getHTML() + "</td>"        
+        + "</tr><tr>"
+        + "<td class='box-01'>&nbsp;</td>"
+        + "<td class='box-11'>" + captionHTML + "</td>"
+        + "<td class='box-21'>&nbsp;</td>"        
+        + "</tr></tbody></table>";
+  }
+  
+  /**
+   * Example of using the DOM class to do CSS class name tricks that have
+   * become common to AJAX apps. In this case we add CSS class name for the
+   * stack panel item that is below the selected item.
+   */
+  private void updateSelectedStyles(int oldIndex, int newIndex) {
+    oldIndex++;
+    if (oldIndex > 0 && oldIndex < stackPanel.getWidgetCount()) {
+      Element elem = DOM.getElementById(computeHeaderId(oldIndex));
+      DOM.setElementProperty(elem, "className", "");
+    }
+    
+    newIndex++;
+    if (newIndex > 0 && newIndex < stackPanel.getWidgetCount()) {
+      Element elem = DOM.getElementById(computeHeaderId(newIndex));
+      DOM.setElementProperty(elem, "className", "is-beneath-selected");
+    }
   }
 }
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/Tasks.java b/samples/mail/src/com/google/gwt/sample/mail/client/Tasks.java
index ec5aef0..b8e79d4 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/Tasks.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/Tasks.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -17,6 +17,7 @@
 
 import com.google.gwt.user.client.ui.CheckBox;
 import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.SimplePanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
 
 /**
@@ -25,13 +26,15 @@
 public class Tasks extends Composite {
 
   public Tasks() {
-    VerticalPanel panel = new VerticalPanel();
-    panel.add(new CheckBox("Get groceries"));
-    panel.add(new CheckBox("Walk the dog"));
-    panel.add(new CheckBox("Start Web 2.0 company"));
-    panel.add(new CheckBox("Write cool app in GWT"));
-    panel.add(new CheckBox("Get funding"));
-    panel.add(new CheckBox("Take a vacation"));
+    SimplePanel panel = new SimplePanel();
+    VerticalPanel list = new VerticalPanel();
+    panel.setWidget(list);
+    list.add(new CheckBox("Get groceries"));
+    list.add(new CheckBox("Walk the dog"));
+    list.add(new CheckBox("Start Web 2.0 company"));
+    list.add(new CheckBox("Write cool app in GWT"));
+    list.add(new CheckBox("Get funding"));
+    list.add(new CheckBox("Take a vacation"));
     initWidget(panel);
     setStyleName("mail-Tasks");
   }
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/TopPanel.java b/samples/mail/src/com/google/gwt/sample/mail/client/TopPanel.java
index eb301dc..569d34d 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/TopPanel.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/TopPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -15,11 +15,14 @@
  */
 package com.google.gwt.sample.mail.client;
 
+import com.google.gwt.user.client.ImageBundle;
 import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
 import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
 
@@ -28,10 +31,17 @@
  */
 public class TopPanel extends Composite implements ClickListener {
 
+  /**
+   * An image bundle for this widgets images.
+   */
+  public interface Images extends ImageBundle {
+    AbstractImagePrototype logo();
+  }
+
   private HTML signOutLink = new HTML("<a href='javascript:;'>Sign Out</a>");
   private HTML aboutLink = new HTML("<a href='javascript:;'>About</a>");
 
-  public TopPanel() {
+  public TopPanel(Images images) {
     HorizontalPanel outer = new HorizontalPanel();
     VerticalPanel inner = new VerticalPanel();
 
@@ -43,6 +53,10 @@
     links.add(signOutLink);
     links.add(aboutLink);
 
+    final Image logo = images.logo().createImage();
+    outer.add(logo);
+    outer.setCellHorizontalAlignment(logo, HorizontalPanel.ALIGN_LEFT);
+
     outer.add(inner);
     inner.add(new HTML("<b>Welcome back, foo@example.com</b>"));
     inner.add(links);
@@ -51,7 +65,7 @@
     aboutLink.addClickListener(this);
 
     initWidget(outer);
-    inner.setStyleName("mail-TopPanel");
+    setStyleName("mail-TopPanel");
     links.setStyleName("mail-TopPanelLinks");
   }
 
@@ -63,13 +77,8 @@
       // Note that showing a dialog box does not block -- execution continues
       // normally, and the dialog fires an event when it is closed.
       AboutDialog dlg = new AboutDialog();
-
-      // Position it roughly in the middle of the screen.
-      int left = (Window.getClientWidth() - 512) / 2;
-      int top = (Window.getClientHeight() - 256) / 2;
-      dlg.setPopupPosition(left, top);
-
       dlg.show();
+      dlg.center();
     }
   }
 }
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/contactsgroup.gif b/samples/mail/src/com/google/gwt/sample/mail/client/contactsgroup.gif
similarity index 100%
rename from samples/mail/src/com/google/gwt/sample/mail/public/contactsgroup.gif
rename to samples/mail/src/com/google/gwt/sample/mail/client/contactsgroup.gif
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/default_photo.jpg b/samples/mail/src/com/google/gwt/sample/mail/client/default_photo.jpg
similarity index 100%
rename from samples/mail/src/com/google/gwt/sample/mail/public/default_photo.jpg
rename to samples/mail/src/com/google/gwt/sample/mail/client/default_photo.jpg
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/drafts.gif b/samples/mail/src/com/google/gwt/sample/mail/client/drafts.gif
similarity index 100%
rename from samples/mail/src/com/google/gwt/sample/mail/public/drafts.gif
rename to samples/mail/src/com/google/gwt/sample/mail/client/drafts.gif
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/home.gif b/samples/mail/src/com/google/gwt/sample/mail/client/home.gif
similarity index 100%
rename from samples/mail/src/com/google/gwt/sample/mail/public/home.gif
rename to samples/mail/src/com/google/gwt/sample/mail/client/home.gif
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/inbox.gif b/samples/mail/src/com/google/gwt/sample/mail/client/inbox.gif
similarity index 100%
rename from samples/mail/src/com/google/gwt/sample/mail/public/inbox.gif
rename to samples/mail/src/com/google/gwt/sample/mail/client/inbox.gif
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/leftCorner.png b/samples/mail/src/com/google/gwt/sample/mail/client/leftCorner.png
new file mode 100644
index 0000000..578205e
--- /dev/null
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/leftCorner.png
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/logo.png b/samples/mail/src/com/google/gwt/sample/mail/client/logo.png
new file mode 100644
index 0000000..a3123b2
--- /dev/null
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/logo.png
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/mailgroup.gif b/samples/mail/src/com/google/gwt/sample/mail/client/mailgroup.gif
similarity index 100%
rename from samples/mail/src/com/google/gwt/sample/mail/public/mailgroup.gif
rename to samples/mail/src/com/google/gwt/sample/mail/client/mailgroup.gif
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/rightCorner.png b/samples/mail/src/com/google/gwt/sample/mail/client/rightCorner.png
new file mode 100644
index 0000000..742f4cd
--- /dev/null
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/rightCorner.png
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/sent.gif b/samples/mail/src/com/google/gwt/sample/mail/client/sent.gif
similarity index 100%
rename from samples/mail/src/com/google/gwt/sample/mail/public/sent.gif
rename to samples/mail/src/com/google/gwt/sample/mail/client/sent.gif
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/tasksgroup.gif b/samples/mail/src/com/google/gwt/sample/mail/client/tasksgroup.gif
similarity index 100%
rename from samples/mail/src/com/google/gwt/sample/mail/public/tasksgroup.gif
rename to samples/mail/src/com/google/gwt/sample/mail/client/tasksgroup.gif
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/templates.gif b/samples/mail/src/com/google/gwt/sample/mail/client/templates.gif
similarity index 100%
rename from samples/mail/src/com/google/gwt/sample/mail/public/templates.gif
rename to samples/mail/src/com/google/gwt/sample/mail/client/templates.gif
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/trash.gif b/samples/mail/src/com/google/gwt/sample/mail/client/trash.gif
similarity index 100%
rename from samples/mail/src/com/google/gwt/sample/mail/public/trash.gif
rename to samples/mail/src/com/google/gwt/sample/mail/client/trash.gif
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/Mail.css b/samples/mail/src/com/google/gwt/sample/mail/public/Mail.css
index 54ee939..224473be 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/public/Mail.css
+++ b/samples/mail/src/com/google/gwt/sample/mail/public/Mail.css
@@ -1,36 +1,51 @@
-body { 
-	background-color: white;
+body, html {
+  height: 100%;
+}
+body {
+	background: #fff;
 	color: black;
-	font-family: Arial, sans-serif;
+	font-family: Helvetica, Arial, sans-serif;
 	font-size: small;
 	margin: 8px;
 	margin-top: 3px;
 }
 
 a {	
-	color: darkblue;
+	color: #000;
 }
 
-a:visited {	
-	color: darkblue; 
+a:visited {
+	color: #000; 
 }
 
 .gwt-DialogBox {
-	border: 2px solid #AAAAAA;
 	background-color: white;
+	border-left: 1px solid #666;
+	border-right: 1px solid #666;
+	border-bottom: 1px solid #666;
 }
 
 .gwt-DialogBox .Caption {
-	background-image: url(gray_gradient.gif);
-	background-repeat: repeat-x;
-	padding: 4px;
-	padding-bottom: 8px;
+	background: url(gradient.gif) repeat-x top left;
+	background-color: #f00;
 	font-weight: bold;
 	cursor: default;
+	padding: 5px 10px;
+	border-bottom: 1px solid #666;
+	border-top: 1px solid #666;
+	text-align: left;
+}
+
+.gwt-DialogBox td {
+	text-align: right;
+}
+
+.gwt-DialogBox .gwt-Button {
+	margin: 10px;
 }
 
 .gwt-MenuBar {
-	background-color: #C3D9FF;
+	background: #c3d9ff;
 	cursor: default;
 }
 
@@ -41,12 +56,14 @@
 }
 
 .gwt-MenuItem-selected {
-	background-color: #E8EEF7;
+	background: #e8eef7;
 }
 
 .gwt-Tree {
-	margin-top: 1em;
-	margin-bottom: 1em;
+}
+
+.gwt-Tree .gwt-TreeItem span * {
+	margin: 0 4px;
 }
 
 .gwt-Tree .gwt-TreeItem {
@@ -54,32 +71,100 @@
 	cursor: default;
 }
 
-.gwt-Tree .gwt-TreeItem-selected {
-	background-color: #C3D9FF;
+.gwt-Tree .gwt-TreeItem span {
+	padding: 2px 0;
+}
+
+.gwt-Tree .gwt-TreeItem-selected span {
+	background: #ccc;
 }
 
 .gwt-StackPanel {
-	background-color: white;
-	border: 1px solid #AAAAAA;
+	background: #fff;
 	width: 15em;
+	border-bottom: 1px solid #666;
+}
+
+.gwt-StackPanel .gwt-StackPanelItem .left {
+	width: 20px;
+	padding: 4px;
+	background: url(lcorner.gif) no-repeat top left;
 }
 
 .gwt-StackPanel .gwt-StackPanelItem {
-	background-image: url(gray_gradient.gif);
-	background-repeat: repeat-x;
-	background-color: #EEEEEE;
 	cursor: pointer;
 	cursor: hand;
 }
 
 .gwt-StackPanel .gwt-StackPanelItem-selected {
+	border-bottom: 1px solid #666;
 }
 
-/*----------------------------------------------------------------------------*/
+.gwt-StackPanel .lcaption {
+	width: 32px;
+	padding: 0 0 4px 5px;
+}
+
+.gwt-StackPanel .rcaption {
+	padding: 0 0 4px 5px;
+}	
+
+.gwt-StackPanel .box-20 {
+  text-align: right;
+}
+
+.box-00, .box-20 {
+  width: 4px;
+  background-color: #b6edbc;
+}
+
+.is-top .box-00, .is-top .box-20,
+.is-beneath-selected .box-00, .is-beneath-selected .box-20 {
+	background-color: #fff;
+}
+
+.box-10 {
+	font-size: 2px;
+	border-top: 1px solid #666;
+	background-color: #deefe1;
+}
+
+.box-01, .box-11, .box-21 {
+	background: url(gradient.gif) repeat-x top left;
+}
+
+.box-01, .box-00 {
+	font-size: 2px;
+  border-left: 1px solid #666;
+}
+
+.box-21, .box-20 {
+	font-size: 2px;
+  border-right: 1px solid #666;
+}
+
+.is-top .box-00, .is-top .box-20 {
+	border-right: none;
+	border-left: none;
+}
+
+.gwt-StackPanel .gwt-StackPanelItem table {
+  width: 100%;
+}
+
 .mail-TopPanel {
+	height: 60px;
+}
+
+.mail-TopPanel table {
 	font-size: 80%;
 }
 
+.mail-TopPanel .gwt-Image {
+	margin-left: 10px;
+	position: absolute;
+}
+
 .mail-TopPanelLinks {
 	font-size: 80%;
 }
@@ -87,42 +172,78 @@
 .mail-AboutText {
 	width: 24em;
 	font-size: 80%;
+	padding: 10px;
+	text-align: left;
 }
 
-.mail-Contacts {
-	margin: 0.5em;
+.mail-Contacts td, .mail-Tasks td {
+	padding: 4px 0 0 0;
+}
+
+.mail-Contacts table {
 	font-size: 80%;
 }
 
-.mail-Tasks {
-	margin: 0.5em;
+.mail-Tasks table {
 	font-size: 80%;
 }
 
 .mail-List {
-	border: 1px solid #AAAAAA;
-	background-color: white;
+	border-left: 1px solid #666;
+	border-right: 1px solid #666;
+	border-bottom: 1px solid #666;
 	font-size: 80%;
 	cursor: pointer;
 	cursor: hand;
 }
 
+.mail-List td {
+  border-top: 1px solid #fff;
+  border-bottom: 1px solid #fff;
+  padding: 2px 0 2px 10px;
+}
+
+.mail-ListHeader td {
+	border-top: none;
+}
+
 .mail-ListHeader {
-	background-image: url(gray_gradient.gif);
-	background-repeat: repeat-x;
+	background: #c1eec8 url(gradient.gif) repeat-x 0px 0px;
 	font-weight: bold;
 }
 
-.mail-ListNavBar {
+.mail-ListHeader .mail-ListNavBar .gwt-HTML {
+	font-weight: bold;
+}
+
+.mail-ListHeader td {
+	padding: 2px 0 2px 10px;
+	border-top: 1px solid #666;
+	border-bottom: 1px solid #666;
+}
+
+.mail-ListNavBar table {
 	font-size: 80%;
 }
 
-.mail-SelectedRow {
-	background-image: url(blue_gradient.gif);
-	background-repeat: repeat-x;
+.mail-ListNavBar td {
+	border: none;
 }
 
-.mail-Toolbar {
+.mail-ListNavBar a {
+	margin: 0 8px;
+}
+
+.mail-SelectedRow td {
+	border-bottom: 1px solid #666;
+	border-top: 1px solid #666;
+}
+
+.mail-SelectedRow {
+	background: #eee;
+}
+
+.mail-Toolbar .gwt-Image {
 }
 
 .mail-ToolButton {
@@ -131,15 +252,18 @@
 }
 
 .mail-Detail {
-	border: 1px solid #AAAAAA;
+	border: 1px solid #666;
 	margin-top: 4px;
 }
 
 .mail-DetailHeader {
-	background-image: url(gray_gradient.gif);
-	background-repeat: repeat-x;
-	border-bottom: 1px solid #AAAAAA;
-	padding: 4px;
+	background: #eee;
+	border-bottom: 1px solid #666;
+	padding: 6px 4px;
+}
+
+.mail-DetailHeader td {
+	padding: 0;
 }
 
 .mail-DetailInner {
@@ -148,27 +272,29 @@
 }
 
 .mail-DetailSubject {
-	font-size: 80%;
+	padding: 2px 10px;
+	font-weight: bold;
 }
 
 .mail-DetailSender {
-	font-weight: bold;
 	font-size: 80%;
+	padding: 2px 10px;
 }
 
 .mail-DetailRecipient {
-	font-style: italic;
 	font-size: 80%;
+	padding: 2px 10px;
 }
 
 .mail-DetailBody {
-	padding: 4px;
+	line-height: 150%;
+	padding: 20px 40px 20px 10px;
+	font-family: 'Times New Roman', Times, serif;
 }
 
 .mail-ContactPopup {
-	background-image: url(gray_gradient.gif);
-	background-repeat: repeat-x;
-	border: 1px solid #AAAAAA;
+	background: #fff;
+	border: 1px solid #666;
 	padding: 4px;
 }
 
@@ -181,3 +307,14 @@
 	font-size: 80%;
 	font-style: italic;
 }
+
+.mail-StackContent {
+	height: 100%;
+	padding: 0 0.5em;
+	border-left: 1px solid #666;
+	border-right: 1px solid #666;
+}
+
+.mail-Contacts {
+	border-bottom: none;
+}
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/Mail.html b/samples/mail/src/com/google/gwt/sample/mail/public/Mail.html
index 468557b..4e95191 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/public/Mail.html
+++ b/samples/mail/src/com/google/gwt/sample/mail/public/Mail.html
@@ -2,7 +2,7 @@
 	<head>
 		<title>Mail App</title>
 	</head>
-	<body style='background-color: #EEEEEE'>
+	<body>
 		<script language='javascript' src='com.google.gwt.sample.mail.Mail.nocache.js'></script>
 	</body>
 </html>
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/blue_gradient.gif b/samples/mail/src/com/google/gwt/sample/mail/public/blue_gradient.gif
deleted file mode 100644
index 7968fa7..0000000
--- a/samples/mail/src/com/google/gwt/sample/mail/public/blue_gradient.gif
+++ /dev/null
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/gradient.gif b/samples/mail/src/com/google/gwt/sample/mail/public/gradient.gif
new file mode 100644
index 0000000..3e0ae44
--- /dev/null
+++ b/samples/mail/src/com/google/gwt/sample/mail/public/gradient.gif
Binary files differ
diff --git a/samples/mail/src/com/google/gwt/sample/mail/public/gray_gradient.gif b/samples/mail/src/com/google/gwt/sample/mail/public/gray_gradient.gif
deleted file mode 100644
index b7f0c54..0000000
--- a/samples/mail/src/com/google/gwt/sample/mail/public/gray_gradient.gif
+++ /dev/null
Binary files differ