Revision: 7980
Author: r...@google.com
Date: Mon Apr 26 09:03:43 2010
Log: Add paging/scrolling for tables

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

Review by: jlaba...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=7980

Added:
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingListView.java /branches/2.1/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/client/ScrollbarPager.java /branches/2.1/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/client/SimplePager.java
Modified:
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/cells/client/ClickableTextCell.java /branches/2.1/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java /branches/2.1/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/client/EditableTableRecipe.java /branches/2.1/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/client/MailRecipe.java

=======================================
--- /dev/null
+++ /branches/2.1/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingListView.java Mon Apr 26 09:03:43 2010
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+/**
+ * A list view that displays data in 'pages'.
+ *
+ * @param <T> the data type of each row
+ */
+public interface PagingListView<T> extends ListView<T> {
+
+  /**
+ * A pager delegate, implemented by classes that depend on the start index,
+   * number of visible rows, or data size of a view.
+   *
+   * @param <T> the data type of each row
+   */
+  public interface Pager<T> {
+    void onRangeOrSizeChanged(PagingListView<T> listView);
+  }
+
+  int getDataSize();
+
+  int getPageSize();
+
+  int getPageStart();
+
+  void setPager(Pager<T> pager);
+
+  void setPageSize(int pageSize);
+
+  void setPageStart(int pageStart);
+}
=======================================
--- /dev/null
+++ /branches/2.1/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/client/ScrollbarPager.java Mon Apr 26 09:03:43 2010
@@ -0,0 +1,102 @@
+/*
+ * 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.sample.bikeshed.cookbook.client;
+
+import com.google.gwt.bikeshed.list.client.PagingListView;
+import com.google.gwt.bikeshed.list.client.PagingTableListView;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.event.dom.client.ScrollEvent;
+import com.google.gwt.event.dom.client.ScrollHandler;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.ScrollPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+
+/**
+ * A pager for controlling a PagingListView that uses a native scrollbar.
+ *
+ * @param <T> the type of the PagingListView being controlled
+ */
+public class ScrollbarPager<T> extends Composite implements PagingListView.Pager<T> {
+
+  private int dataSize;
+  private int height;
+
+  /**
+   * Number of units advanced by clicking the down arrow on the scrollbar.
+   */
+  private int jump;
+  private int pageSize;
+  private ScrollPanel panel;
+  private PagingTableListView<T> view;
+  private int spaceAbove;
+  private HTML spacer;
+
+  public ScrollbarPager(PagingTableListView<T> view) {
+    this.jump = getScrollPageAmount();
+    this.panel = new ScrollPanel();
+    this.height = view.getBodyHeight();
+    this.spaceAbove = view.getHeaderHeight();
+
+    panel.setSize("50px", "" + height + "px");
+    DOM.setStyleAttribute(panel.getElement(), "overflow", "auto");
+
+    VerticalPanel p = new VerticalPanel();
+    p.add(spacer = new HTML("<div style='height: " + spaceAbove + "px;'"));
+    p.add(panel);
+
+    initWidget(p);
+
+    panel.addScrollHandler(new ScrollHandler() {
+      public void onScroll(ScrollEvent event) {
+        int position = panel.getScrollPosition() / jump;
+        ScrollbarPager.this.view.setPageStart(position);
+      }
+    });
+
+    this.view = view;
+    view.setPager(this);
+  }
+
+  public void onRangeOrSizeChanged(PagingListView<T> listView) {
+    this.pageSize = listView.getPageSize();
+    this.dataSize = listView.getDataSize();
+
+    this.height = view.getBodyHeight();
+    this.spaceAbove = view.getHeaderHeight();
+    spacer.getElement().getStyle().setHeight(spaceAbove, Unit.PX);
+    panel.setSize("50px", "" + height + "px");
+
+    int h = Math.max(height + 1, jump * (dataSize - pageSize) + height);
+ panel.setWidget(new HTML("<div id='scroll-contents' style='width: 1px; height: " + h + "px;'></div>"));
+  }
+
+  /**
+   * Returns the number of units of scrolling caused by clicking on the
+   * scrollbar's up/down buttons, based on the browser user agent.
+   */
+  private native int getScrollPageAmount() /*-{
+    var ua = navigator.userAgent.toLowerCase();
+    if (ua.indexOf("webkit") != -1) {
+      return 40;
+    }
+    if (ua.indexOf("gecko") != -1) {
+      return 14;
+    }
+    return 40; // not tested
+  }-*/;
+}
=======================================
--- /dev/null
+++ /branches/2.1/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/client/SimplePager.java Mon Apr 26 09:03:43 2010
@@ -0,0 +1,156 @@
+/*
+ * 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.sample.bikeshed.cookbook.client;
+
+import com.google.gwt.bikeshed.list.client.PagingListView;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Label;
+
+/**
+ * A pager for controlling a PagingListView that uses a series of buttons
+ * for demo purposes.
+ *
+ * @param <T> the type of the PagingListView being controlled
+ */
+public class SimplePager<T> extends Composite implements PagingListView.Pager<T>,
+    ClickHandler {
+
+  private int dataSize;
+  private Button nextPageButton;
+  private int pageSize;
+  private int pageStart;
+  private Button prevPageButton;
+  private Button remove1Button;
+  private Button remove5Button;
+  private PagingListView<T> view;
+  private Label infoLabel;
+
+  public SimplePager(PagingListView<T> view) {
+    FlowPanel p = new FlowPanel();
+    p.add(prevPageButton = makeButton("Previous Page", "PREV"));
+    p.add(nextPageButton = makeButton("Next Page", "NEXT"));
+    p.add(remove5Button = makeButton("Remove 5 rows", "REM5"));
+    p.add(remove1Button = makeButton("Remove row", "REM1"));
+    p.add(makeButton("Add row", "ADD1"));
+    p.add(makeButton("Add 5 rows", "ADD5"));
+    p.add(infoLabel = new Label(""));
+    initWidget(p);
+
+    this.view = view;
+    view.setPager(this);
+  }
+
+  /**
+   * Returns true if it there is enough data to allow a given number of
+   * additional rows to be displayed.
+   */
+  public boolean canAddRows(int rows) {
+    return dataSize - pageSize >= rows;
+  }
+
+  /**
+   * Returns true if the page size is sufficient to allow a given number of
+   * rows to be removed.
+   */
+  public boolean canRemoveRows(int rows) {
+    return pageSize > rows;
+  }
+
+  /**
+   * Returns true if there is enough data such that a call to
+   * {...@link #nextPage()} will succeed in moving the starting point of the
+   * table forward.
+   */
+  public boolean hasNextPage() {
+    return pageStart + pageSize < dataSize;
+  }
+
+  /**
+   * Returns true if there is enough data such that a call to
+ * {...@link #previousPage()} will succeed in moving the starting point of the
+   * table backward.
+   */
+  public boolean hasPreviousPage() {
+    return pageStart > 0 && dataSize > 0;
+  }
+
+  /**
+   * Advance the starting row by 'pageSize' rows.
+   */
+  public void nextPage() {
+    view.setPageStart(pageStart + pageSize);
+  }
+
+  public void onClick(ClickEvent event) {
+    String id = ((Button) event.getSource()).getElement().getId();
+
+    if ("NEXT".equals(id)) {
+      nextPage();
+    } else if ("PREV".equals(id)) {
+      previousPage();
+    } else if (id.startsWith("ADD")) {
+      addRows(Integer.parseInt(id.substring(3)));
+    } else if (id.startsWith("REM")) {
+      removeRows(Integer.parseInt(id.substring(3)));
+    }
+    updateButtons();
+  }
+
+  public void onRangeOrSizeChanged(PagingListView<T> listView) {
+    this.pageSize = listView.getPageSize();
+    this.pageStart = listView.getPageStart();
+    this.dataSize = listView.getDataSize();
+    updateButtons();
+  }
+
+  /**
+   * Move the starting row back by 'pageSize' rows.
+   */
+  public void previousPage() {
+    view.setPageStart(pageStart - pageSize);
+  }
+
+  private void addRows(int rows) {
+    view.setPageSize(pageSize + rows);
+  }
+
+  private Button makeButton(String label, String id) {
+    Button button = new Button(label);
+    button.getElement().setId(id);
+    button.addClickHandler(this);
+    return button;
+  }
+
+  private void removeRows(int rows) {
+    view.setPageSize(pageSize - rows);
+  }
+
+  private void updateButtons() {
+    remove1Button.setEnabled(canRemoveRows(1));
+    remove5Button.setEnabled(canRemoveRows(5));
+    prevPageButton.setEnabled(hasPreviousPage());
+    nextPageButton.setEnabled(hasNextPage());
+
+    int page = (pageStart / pageSize) + 1;
+    int numPages = (dataSize + pageSize - 1) / pageSize;
+ infoLabel.setText("Page " + page + " of " + numPages + ": Page Start = " + pageStart + ", Page Size = " +
+        pageSize + ", Data Size = " + dataSize);
+  }
+}
=======================================
--- /branches/2.1/bikeshed/src/com/google/gwt/bikeshed/cells/client/ClickableTextCell.java Mon Apr 19 04:48:30 2010 +++ /branches/2.1/bikeshed/src/com/google/gwt/bikeshed/cells/client/ClickableTextCell.java Mon Apr 26 09:03:43 2010
@@ -40,7 +40,6 @@
   public Void onBrowserEvent(Element parent, String value, Void viewData,
       NativeEvent event, ValueUpdater<String, Void> valueUpdater) {
     String type = event.getType();
-    System.out.println(type);
     if (type.equals("click")) {
       valueUpdater.update(value, null);
     }
=======================================
--- /branches/2.1/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java Thu Apr 22 10:25:15 2010 +++ /branches/2.1/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java Mon Apr 26 09:03:43 2010
@@ -44,7 +44,7 @@
  *
  * @param <T> the data type of each row
  */
-public class PagingTableListView<T> extends Widget implements ListView<T> {
+public class PagingTableListView<T> extends Widget implements PagingListView<T> {

   private class TableSelectionHandler implements SelectionChangeHandler {
     public void onSelectionChange(SelectionChangeEvent event) {
@@ -61,22 +61,24 @@
   private List<Header<?>> footers = new ArrayList<Header<?>>();
   private List<Header<?>> headers = new ArrayList<Header<?>>();
   private TableRowElement hoveringRow;
+  private Pager<T> pager;
   private int pageSize = -1;
+
   private int pageStart = 0;

   /**
    * If null, each T will be used as its own key.
    */
   private ProvidesKey<T> providesKey;
-
   private HandlerRegistration selectionHandler;
-  private SelectionModel<? super T> selectionModel;
-
+
+  private SelectionModel<? super T> selectionModel;
+  private int size = 0;
   private TableElement table;
   private TableSectionElement tbody;
   private TableSectionElement tfoot;
+
   private TableSectionElement thead;
-  private int size = 0;

   /**
    * Constructs a table with a default page size of 10.
@@ -139,23 +141,16 @@
     addColumn(col, new TextHeader(headerString), null);
   }

-  /**
-   * Returns true if it there is enough data to allow a given number of
-   * additional rows to be displayed.
-   */
-  public boolean canAddRows(int rows) {
-    return size - pageSize >= rows;
+  // TODO: remove(Column)
+
+  public int getBodyHeight() {
+    int height = getClientHeight(tbody);
+    return height;
   }

-  /**
- * Returns true if the page size is sufficient to allow a given number of rows
-   * to be removed.
-   */
-  public boolean canRemoveRows(int rows) {
-    return pageSize > rows;
-  }
-
-  // TODO: remove(Column)
+  public int getDataSize() {
+    return size;
+  }

   public T getDisplayedItem(int indexOnPage) {
     if (indexOnPage < 0 || indexOnPage >= getNumDisplayedItems()) {
@@ -167,6 +162,11 @@
   public List<T> getDisplayedItems() {
     return new ArrayList<T>(dataValues);
   }
+
+  public int getHeaderHeight() {
+    int height = getClientHeight(thead);
+    return height;
+  }

   public int getNumDisplayedItems() {
     return Math.min(getPageSize(), size - pageStart);
@@ -191,31 +191,6 @@
   public int getSize() {
     return size;
   }
-
-  /**
-   * Returns true if there is enough data such that a call to
- * {...@link #nextPage()} will succeed in moving the starting point of the table
-   * forward.
-   */
-  public boolean hasNextPage() {
-    return pageStart + pageSize < size;
-  }
-
-  /**
-   * Returns true if there is enough data such that a call to
- * {...@link #previousPage()} will succeed in moving the starting point of the
-   * table backward.
-   */
-  public boolean hasPreviousPage() {
-    return pageStart > 0 && size > 0;
-  }
-
-  /**
-   * Advance the starting row by {...@link #getPageSize()} rows.
-   */
-  public void nextPage() {
-    setPageStart(Math.min(getSize() - 1, getPageStart() + getPageSize()));
-  }

   @Override
   public void onBrowserEvent(Event event) {
@@ -259,13 +234,6 @@
column.onBrowserEvent(cell, pageStart + row, value, event, providesKey);
     }
   }
-
-  /**
-   * Move the starting row back by {...@link #getPageSize()} rows.
-   */
-  public void previousPage() {
-    setPageStart(Math.max(0, getPageStart() - getPageSize()));
-  }

   /**
    * Redraw the table, requesting data from the delegate.
@@ -365,12 +333,22 @@

   public void setDataSize(int size, boolean isExact) {
     this.size = size;
-    updateRowVisibility();
+    if (size == 0) {
+      pageStart = 0;
+    } else if (pageStart > size - 1) {
+      pageStart = size - 1;
+    }
+    refresh();
+    updatePager();
   }

   public void setDelegate(Delegate<T> delegate) {
     this.delegate = delegate;
   }
+
+  public void setPager(PagingListView.Pager<T> pager) {
+    this.pager = pager;
+  }

   /**
    * Set the number of rows per page and refresh the table.
@@ -392,6 +370,7 @@
     if (pageStart + pageSize > size) {
       pageStart = Math.max(0, size - pageSize);
     }
+    updatePager();

     // TODO - avoid requesting data if the page size has decreased
     createRows();
@@ -407,6 +386,7 @@
    */
   public void setPageStart(int pageStart) {
     this.pageStart = Math.max(Math.min(pageStart, size - 1), 0);
+    updatePager();
     refresh();
   }

@@ -519,6 +499,17 @@
     return null;
   }

+  private native int getClientHeight(Element element) /*-{
+    return element.clientHeight;
+  }-*/;
+
+  private void updatePager() {
+ // Inform the pager about a change in page start, page size, or data size
+    if (pager != null) {
+      pager.onRangeOrSizeChanged(this);
+    }
+  }
+
   private void updateRowVisibility() {
     int visible = Math.min(pageSize, size - pageStart);

=======================================
--- /branches/2.1/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/client/EditableTableRecipe.java Tue Apr 20 16:34:24 2010 +++ /branches/2.1/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/client/EditableTableRecipe.java Mon Apr 26 09:03:43 2010
@@ -96,12 +96,12 @@
     FlowPanel nextPrevPanel = new FlowPanel();
     Button prevBtn = new Button("<", new ClickHandler() {
       public void onClick(ClickEvent event) {
-        table.previousPage();
+        table.setPageStart(table.getPageStart() - table.getPageSize());
       }
     });
     Button nextBtn = new Button(">", new ClickHandler() {
       public void onClick(ClickEvent event) {
-        table.nextPage();
+        table.setPageStart(table.getPageStart() + table.getPageSize());
       }
     });
     nextPrevPanel.add(prevBtn);
=======================================
--- /branches/2.1/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/client/MailRecipe.java Thu Apr 22 06:58:10 2010 +++ /branches/2.1/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/client/MailRecipe.java Mon Apr 26 09:03:43 2010
@@ -1,12 +1,12 @@
 /*
  * 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
@@ -34,11 +34,9 @@
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyUpEvent;
 import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.sample.bikeshed.style.client.Styles;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.FocusWidget;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.Label;
@@ -234,6 +232,8 @@
           + subject + ", read=" + isRead + ", date=" + date + "]";
     }
   }
+
+  private static Label messageIdsLabel = new Label("");

   private static Label selectionLabel = new Label("Selected NONE");

@@ -252,19 +252,33 @@
       "Impress your colleagues with bling-bling", "Degree available",
       "Rolex Watches", "Re: Re: yo bud", "Important notice"};

-  private Button add1Button;
-
-  private FocusWidget add5Button;
-
-  private List<Message> messages;
-
-  private Button nextPageButton;
-
-  private Button prevPageButton;
-
-  private Button remove1Button;
-
-  private Button remove5Button;
+ private final Comparator<Message> dateComparator = new Comparator<Message>() {
+    public int compare(Message o1, Message o2) {
+      long cmp = o1.date.getTime() - o2.date.getTime();
+      if (cmp < 0) {
+        return -1;
+      } else if (cmp > 0) {
+        return 1;
+      } else {
+        return 0;
+      }
+    }
+  };
+
+ private final Comparator<Message> idComparator = new Comparator<Message>() {
+    public int compare(Message o1, Message o2) {
+      // Integer comparison
+      return o1.id - o2.id;
+    }
+  };
+
+  private Comparator<Message> lastComparator = idComparator;
+
+  private boolean lastSortUp = true;
+
+  private int messageId = 10000;
+
+  private List<Message> messages;

   private MailSelectionModel selectionModel = new MailSelectionModel();

@@ -284,18 +298,10 @@
       for (Message item : selectedItems) {
         selectionModel.setSelected(item, true);
       }
-    } else if ("NEXT".equals(id)) {
-      table.nextPage();
-      updatePagingButtons();
-    } else if ("PREV".equals(id)) {
-      table.previousPage();
-      updatePagingButtons();
     } else if (id.startsWith("ADD")) {
- table.setPageSize(table.getPageSize() + Integer.parseInt(id.substring(3)));
-      updatePagingButtons();
+      addMessages(Integer.parseInt(id.substring(3)));
     } else if (id.startsWith("REM")) {
- table.setPageSize(Math.max(table.getPageSize() - Integer.parseInt(id.substring(3)), 0));
-      updatePagingButtons();
+      removeMessages(Integer.parseInt(id.substring(3)));
     } else {
       selectionModel.setType(id);
     }
@@ -306,43 +312,9 @@
     ListViewAdapter<Message> adapter = new ListViewAdapter<Message>();
     messages = adapter.getList();

-    Date now = new Date();
-    Random rand = new Random();
-    for (int i = 0; i < 25; i++) {
-      // Go back up to 90 days from the current date
-      long dateOffset = rand.nextInt(60 * 60 * 24 * 90) * 1000L;
-      Message message = new Message(10000 + i,
-          senders[rand.nextInt(senders.length)],
-          subjects[rand.nextInt(subjects.length)], new Date(now.getTime()
-              - dateOffset));
-      message.isRead = rand.nextBoolean();
-      messages.add(message);
-    }
-
-    final Comparator<Message> idComparator = new Comparator<Message>() {
-      public int compare(Message o1, Message o2) {
-        // Integer comparison
-        return o1.id - o2.id;
-      }
-    };
-
-    final Comparator<Message> dateComparator = new Comparator<Message>() {
-      public int compare(Message o1, Message o2) {
-        long cmp = o1.date.getTime() - o2.date.getTime();
-        if (cmp < 0) {
-          return -1;
-        } else if (cmp > 0) {
-          return 1;
-        } else {
-          return 0;
-        }
-      }
-    };
-
-    sortMessages(idComparator, true);
+    addMessages(10);

     table = new PagingTableListView<Message>(10);
-    table.setStyleName(Styles.common().table());
     table.setSelectionModel(selectionModel);
     adapter.addView(table);

@@ -425,6 +397,8 @@
     });
     table.addColumn(toggleColumn, "Toggle Read/Unread");

+    ScrollbarPager<Message> pager = new ScrollbarPager<Message>(table);
+
     Label searchLabel = new Label("Search Sender or Subject:");
     final TextBox searchBox = new TextBox();
     searchBox.addKeyUpHandler(new KeyUpHandler() {
@@ -442,27 +416,21 @@
     p.add(makeButton("Search Subject", "SUBJECT"));
     p.add(makeButton("Search Senders", "SENDER"));
     p.add(new HTML("<br>"));
-    p.add(table);
-    p.add(prevPageButton = makeButton("Previous Page", "PREV"));
-    prevPageButton.setEnabled(false);
-    p.add(nextPageButton = makeButton("Next Page", "NEXT"));
-    nextPageButton.setEnabled(true);
-    p.add(remove1Button = makeButton("Remove row", "REM1"));
-    remove1Button.setEnabled(true);
-    p.add(add1Button = makeButton("Add row", "ADD1"));
-    add1Button.setEnabled(true);
-    p.add(remove5Button = makeButton("Remove 5 rows", "REM5"));
-    remove5Button.setEnabled(true);
-    p.add(add5Button = makeButton("Add 5 rows", "ADD5"));
-    add5Button.setEnabled(true);
-    p.add(new HTML("<br>"));
+    HorizontalPanel hp = new HorizontalPanel();
+    hp.add(pager);
+    hp.add(table);
+    p.add(hp);
+    p.add(new HTML("<hr>"));
     p.add(makeButton("Select None", "NONE"));
     p.add(makeButton("Select All On This Page", "PAGE"));
     p.add(makeButton("Select All", "ALL"));
     p.add(makeButton("Select Read", "READ"));
     p.add(makeButton("Select Unread", "UNREAD"));
-    p.add(new HTML("<hr>"));
     p.add(selectionLabel);
+    p.add(new HTML("<hr>"));
+    p.add(makeButton("Add 5 messages", "ADD5"));
+    p.add(makeButton("Remove 5 messages", "REM5"));
+    p.add(messageIdsLabel);
     return p;
   }

@@ -507,6 +475,24 @@
       final GetValue<Message, String> getter) {
     return addColumn(table, text, TextCell.getInstance(), getter, null);
   }
+
+  private void addMessages(int count) {
+    Date now = new Date();
+    Random rand = new Random();
+    for (int i = 0; i < count; i++) {
+      // Go back up to 90 days from the current date
+      long dateOffset = rand.nextInt(60 * 60 * 24 * 90) * 1000L;
+      Message message = new Message(messageId++,
+          senders[rand.nextInt(senders.length)],
+          subjects[rand.nextInt(subjects.length)], new Date(now.getTime()
+              - dateOffset));
+      message.isRead = rand.nextBoolean();
+      messages.add(message);
+    }
+    sortMessages(lastComparator, lastSortUp);
+
+    messageIdsLabel.setText("Maximum message ID = " + (messageId - 1));
+  }

   private Button makeButton(String label, String id) {
     Button button = new Button(label);
@@ -514,8 +500,17 @@
     button.addClickHandler(this);
     return button;
   }
+
+  private void removeMessages(int count) {
+    count = Math.min(count, messages.size());
+    for (int i = 0; i < count; i++) {
+      messages.remove(0);
+    }
+  }

private void sortMessages(final Comparator<Message> comparator, boolean sortUp) {
+    lastComparator = comparator;
+    lastSortUp = sortUp;
     if (sortUp) {
       Collections.sort(messages, comparator);
     } else {
@@ -526,13 +521,4 @@
       });
     }
   }
-
-  private void updatePagingButtons() {
-    add1Button.setEnabled(table.canAddRows(1));
-    remove1Button.setEnabled(table.canRemoveRows(1));
-    add5Button.setEnabled(table.canAddRows(5));
-    remove5Button.setEnabled(table.canRemoveRows(5));
-    prevPageButton.setEnabled(table.hasPreviousPage());
-    nextPageButton.setEnabled(table.hasNextPage());
-  }
-}
+}

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

Reply via email to