Mail sample app to work on selection concepts
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7809 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/bikeshed/src/com/google/gwt/bikeshed/cells/client/ButtonCell.java b/bikeshed/src/com/google/gwt/bikeshed/cells/client/ButtonCell.java
index d318e2f..129966b 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/cells/client/ButtonCell.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/cells/client/ButtonCell.java
@@ -22,6 +22,11 @@
* A {@link Cell} used to render a button.
*/
public class ButtonCell extends Cell<String, Void> {
+
+ @Override
+ public boolean consumesEvents() {
+ return true;
+ }
@Override
public Void onBrowserEvent(Element parent, String value, Void viewData,
diff --git a/bikeshed/src/com/google/gwt/bikeshed/cells/client/Cell.java b/bikeshed/src/com/google/gwt/bikeshed/cells/client/Cell.java
index 44ed5fe..8d4d795 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/cells/client/Cell.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/cells/client/Cell.java
@@ -27,6 +27,14 @@
public abstract class Cell<C, V> {
/**
+ * Returns true if the cell is interested in browser events. The default
+ * implementation returns false.
+ */
+ public boolean consumesEvents() {
+ return false;
+ }
+
+ /**
* Handle a browser event that took place within the cell. The default
* implementation returns null.
*
@@ -43,8 +51,8 @@
}
/**
- * Render a cell as HTML into a StringBuilder, suitable for passing
- * to setInnerHTML on a container element.
+ * Render a cell as HTML into a StringBuilder, suitable for passing to
+ * {@link Element#setInnerHTML} on a container element.
*
* @param value the cell value to be rendered
* @param viewData view data associated with the cell
diff --git a/bikeshed/src/com/google/gwt/bikeshed/cells/client/CheckboxCell.java b/bikeshed/src/com/google/gwt/bikeshed/cells/client/CheckboxCell.java
index f0accb1..0a157e0 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/cells/client/CheckboxCell.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/cells/client/CheckboxCell.java
@@ -23,6 +23,11 @@
* A {@link Cell} used to render a checkbox.
*/
public class CheckboxCell extends Cell<Boolean, Void> {
+
+ @Override
+ public boolean consumesEvents() {
+ return true;
+ }
@Override
public Void onBrowserEvent(Element parent, Boolean value, Void viewData,
diff --git a/bikeshed/src/com/google/gwt/bikeshed/cells/client/TextInputCell.java b/bikeshed/src/com/google/gwt/bikeshed/cells/client/TextInputCell.java
index 4a7e5bd..6846084 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/cells/client/TextInputCell.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/cells/client/TextInputCell.java
@@ -23,6 +23,11 @@
* A {@link Cell} used to render a text input.
*/
public class TextInputCell extends Cell<String, Void> {
+
+ @Override
+ public boolean consumesEvents() {
+ return true;
+ }
@Override
public Void onBrowserEvent(Element parent, String value, Void viewData,
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 3a189aa..915e404 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java
@@ -19,6 +19,7 @@
import com.google.gwt.bikeshed.list.shared.ListHandler;
import com.google.gwt.bikeshed.list.shared.ListModel;
import com.google.gwt.bikeshed.list.shared.ListRegistration;
+import com.google.gwt.bikeshed.list.shared.SelectionModel;
import com.google.gwt.bikeshed.list.shared.SizeChangeEvent;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
@@ -45,21 +46,23 @@
public class PagingTableListView<T> extends Widget {
protected int curPage;
- private int pageSize;
- private int numPages;
- private ListRegistration listReg;
- private int totalSize;
private List<Column<T, ?, ?>> columns = new ArrayList<Column<T, ?, ?>>();
private ArrayList<T> data = new ArrayList<T>();
-
- private List<Header<?>> headers = new ArrayList<Header<?>>();
private List<Header<?>> footers = new ArrayList<Header<?>>();
+ private List<Header<?>> headers = new ArrayList<Header<?>>();
+ private ListRegistration listReg;
+ private int numPages;
+
+ private int pageSize;
+ private SelectionModel<T> selectionModel;
private TableElement table;
- private TableSectionElement thead;
- private TableSectionElement tfoot;
- private TableSectionElement tbody;
+ private TableSectionElement tbody;
+ private TableSectionElement tfoot;
+ private TableSectionElement thead;
+ private int totalSize;
+
public PagingTableListView(ListModel<T> listModel, final int pageSize) {
this.pageSize = pageSize;
setElement(table = Document.get().createTableElement());
@@ -149,6 +152,7 @@
int row = tr.getSectionRowIndex();
T value = data.get(row);
Column<T, ?, ?> column = columns.get(col);
+
column.onBrowserEvent(cell, curPage * pageSize + row, value, event);
}
}
@@ -156,6 +160,11 @@
public void previousPage() {
setPage(curPage - 1);
}
+
+ public void refresh() {
+ listReg.setRangeOfInterest(curPage * pageSize, pageSize);
+ updateRowVisibility();
+ }
/**
* Set the current visible page.
@@ -192,6 +201,10 @@
setPage(curPage);
}
+ public void setSelectionModel(SelectionModel<T> selectionModel) {
+ this.selectionModel = selectionModel;
+ }
+
protected void render(int start, int length, List<T> values) {
int numCols = columns.size();
int pageStart = curPage * pageSize;
@@ -200,6 +213,12 @@
for (int r = start; r < start + length; ++r) {
TableRowElement row = rows.getItem(r - pageStart);
T q = values.get(r - start);
+ if (selectionModel != null && selectionModel.isSelected(q)) {
+ row.setClassName("pagingTableListView selected");
+ } else {
+ row.setClassName("pagingTableListView " +
+ (((r - pageStart) & 0x1) == 0 ? "evenRow" : "oddRow"));
+ }
data.set(r - pageStart, q);
for (int c = 0; c < numCols; ++c) {
diff --git a/bikeshed/src/com/google/gwt/bikeshed/list/shared/SelectionModel.java b/bikeshed/src/com/google/gwt/bikeshed/list/shared/SelectionModel.java
new file mode 100644
index 0000000..2dfece3
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/shared/SelectionModel.java
@@ -0,0 +1,28 @@
+/*
+ * 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.shared;
+
+/**
+ * A model for selection within a list.
+ *
+ * @param <T> the data type of records in the list
+ */
+public interface SelectionModel<T> {
+
+ boolean isSelected(T object);
+
+ void setSelected(T object, boolean selected);
+}
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/mail/MailSample.gwt.xml b/bikeshed/src/com/google/gwt/sample/bikeshed/mail/MailSample.gwt.xml
new file mode 100644
index 0000000..19da671
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/mail/MailSample.gwt.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 0.0.999//EN" "http://google-web-toolkit.googlecode.com/svn/tags/0.0.999/distro-source/core/src/gwt-module.dtd">
+<module rename-to='mail'>
+ <!-- Inherit the core Web Toolkit stuff. -->
+ <inherits name='com.google.gwt.user.User'/>
+ <inherits name='com.google.gwt.bikeshed.list.List'/>
+ <inherits name='com.google.gwt.bikeshed.tree.Tree'/>
+
+ <!-- Inherit the default GWT style sheet. You can change -->
+ <!-- the theme of your GWT application by uncommenting -->
+ <!-- any one of the following lines. -->
+ <inherits name='com.google.gwt.user.theme.standard.Standard'/>
+ <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
+ <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
+
+ <!-- Other module inherits -->
+
+ <!-- Specify the app entry point class. -->
+ <entry-point class='com.google.gwt.sample.bikeshed.mail.client.MailSample'/>
+
+ <!-- Specify the paths for translatable code -->
+ <source path='client'/>
+ <source path='shared'/>
+
+</module>
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
new file mode 100644
index 0000000..cde957f
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/mail/client/MailSample.java
@@ -0,0 +1,195 @@
+/*
+ * 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.mail.client;
+
+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.shared.ListListModel;
+import com.google.gwt.bikeshed.list.shared.SelectionModel;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.client.ui.RootPanel;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+/**
+ * A demo of selection features.
+ */
+public class MailSample implements EntryPoint {
+
+ class Message {
+ int id;
+ boolean isRead;
+ boolean isSelected;
+ String sender;
+ String subject;
+
+ public Message(int id, String sender, String subject) {
+ super();
+ this.id = id;
+ this.sender = sender;
+ this.subject = subject;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Message)) {
+ return false;
+ }
+ return id == ((Message) obj).id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getSender() {
+ return sender;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ @Override
+ public int hashCode() {
+ return id;
+ }
+
+ public boolean isRead() {
+ return isRead;
+ }
+
+ public boolean isSelected() {
+ return isSelected;
+ }
+
+ @Override
+ public String toString() {
+ return "Message [id=" + id + ", isSelected=" + isSelected + ", sender="
+ + sender + ", subject=" + subject + ", read=" + isRead + "]";
+ }
+ }
+
+ class MailSelectionModel implements SelectionModel<Message> {
+ private Set<Integer> plusExceptions = new HashSet<Integer>();
+ private Set<Integer> minusExceptions = new HashSet<Integer>();
+
+ private boolean isDefaultSelected(Message object) {
+ return object.isRead();
+ }
+
+ public boolean isSelected(Message object) {
+ return (isDefaultSelected(object) || plusExceptions.contains(object.id))
+ && !minusExceptions.contains(object.id);
+ }
+
+ public void setSelected(Message object, boolean selected) {
+ if (!selected) {
+ minusExceptions.add(object.id);
+ plusExceptions.remove(object.id);
+ } else {
+ minusExceptions.remove(object.id);
+ plusExceptions.add(object.id);
+ }
+ }
+ }
+
+ private static final String[] senders = {
+ "test@example.com", "spam1@spam.com", "gwt@google.com"};
+
+ private static final String[] subjects = {
+ "GWT rocks", "What's a widget?", "Money in Nigeria"};
+
+ public void onModuleLoad() {
+ TextCell textCell = new TextCell();
+
+ ListListModel<Message> listModel = new ListListModel<Message>();
+ List<Message> messages = listModel.getList();
+ Random rand = new Random();
+ for (int i = 0; i < 1000; i++) {
+ Message message = new Message(i, senders[rand.nextInt(senders.length)],
+ subjects[rand.nextInt(subjects.length)]);
+ message.isRead = rand.nextBoolean();
+ messages.add(message);
+ }
+
+ final SelectionModel<Message> selectionModel = new MailSelectionModel();
+
+ final PagingTableListView<Message> table =
+ new PagingTableListView<Message>(listModel, 10);
+
+ Column<Message, Boolean, Void> selectedColumn = new Column<Message, Boolean, Void>(
+ new CheckboxCell()) {
+ @Override
+ public Boolean getValue(Message object) {
+ return selectionModel.isSelected(object);
+ }
+ };
+ selectedColumn.setFieldUpdater(new FieldUpdater<Message, Boolean, Void>() {
+ public void update(int index, Message object, Boolean value, Void viewData) {
+ selectionModel.setSelected(object, value);
+ table.refresh(); // TODO - remove
+ }
+ });
+ Header<String> selectedHeader = new Header<String>(textCell);
+ selectedHeader.setValue("Selected");
+ table.addColumn(selectedColumn, selectedHeader);
+
+ Column<Message, String, Void> isReadColumn =
+ new Column<Message, String, Void>(textCell) {
+ @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);
+
+ Column<Message, String, Void> senderColumn = new Column<Message, String, Void>(
+ new TextCell()) {
+ @Override
+ public String getValue(Message object) {
+ return object.getSender();
+ }
+ };
+ Header<String> senderHeader = new Header<String>(textCell);
+ senderHeader.setValue("Sender");
+ table.addColumn(senderColumn, senderHeader);
+
+ Column<Message, String, Void> subjectColumn = new Column<Message, String, Void>(
+ textCell) {
+ @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);
+
+ RootPanel.get().add(table);
+ }
+}
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/validation/client/ValidatableInputCell.java b/bikeshed/src/com/google/gwt/sample/bikeshed/validation/client/ValidatableInputCell.java
index 344cfb1..99e5f77 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/validation/client/ValidatableInputCell.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/validation/client/ValidatableInputCell.java
@@ -29,6 +29,11 @@
public class ValidatableInputCell extends Cell<String, ValidatableField<String>> {
@Override
+ public boolean consumesEvents() {
+ return true;
+ }
+
+ @Override
public ValidatableField<String> onBrowserEvent(Element parent, String value,
ValidatableField<String> viewData, NativeEvent event,
ValueUpdater<String, ValidatableField<String>> valueUpdater) {
diff --git a/bikeshed/war/Mail.css b/bikeshed/war/Mail.css
new file mode 100644
index 0000000..7856cdc
--- /dev/null
+++ b/bikeshed/war/Mail.css
@@ -0,0 +1,109 @@
+body {
+ background: url(bg.png) repeat-x;
+ background-color: rgb(216, 220, 224);
+ color: black;
+ margin: 8px;
+ margin-top: 3px;
+}
+
+body, table {
+ font-family: Helvetica Neue Light, Helvetica, Arial, sans-serif; */
+ font-weight: light;
+ font-size: small;
+}
+
+tr.selected {
+ background-color: rgb(56, 117, 215);
+}
+
+tr.evenRow {
+ background-color: rgb(255, 255, 255);
+}
+
+tr.oddRow {
+ background-color: rgb(220, 220, 220);
+}
+
+div.gwt-sstree-column {
+ overflow-y: scroll;
+ overflow-x: auto;
+ position: relative;
+}
+
+div.gwt-sstree {
+}
+
+div.gwt-sstree-selectedItem {
+ background-color: rgb(56, 117, 215);
+}
+
+div.gwt-sstree-evenRow {
+ background-color: rgb(255, 255, 255);
+}
+
+div.gwt-sstree-oddRow {
+ background-color: rgb(220, 220, 220);
+}
+
+/** Example rules used by the template application (remove for your app) */
+h1 {
+ font-size: 2em;
+ font-weight: bold;
+ color: #777777;
+ margin: 40px 0px 70px;
+ text-align: center;
+}
+
+.sendButton {
+ display: block;
+ font-size: 16pt;
+}
+
+/** Most GWT widgets already have a style name defined */
+.gwt-DialogBox {
+ width: 400px;
+}
+
+.dialogVPanel {
+ margin: 5px;
+}
+
+.serverResponseLabelError {
+ color: red;
+}
+
+.playerScoreBox {
+ border: 1px solid #777;
+ padding:3px;
+ background: #eee;
+ margin-bottom: 5px;
+}
+
+/** Set ids using widget.getElement().setId("idOfElement") */
+#closeButton {
+ margin: 15px 6px 6px;
+}
+
+.gwt-DialogBox {
+ border: 8px solid white;
+ border-right: 11px solid white;
+ border-bottom: 11px solid white;
+ -webkit-border-image: url(blueborder.png) 8 11 11 8 round round;
+ -moz-border-image: url(blueborder.png) 8 11 11 8 round round;
+}
+
+.gwt-DialogBox .Caption {
+ font-weight: light;
+ font-size: 12pt;
+ text-align: center;
+ margin-bottom: 0.5em;
+ border-bottom: 1px solid #ccc;
+}
+
+.gwt-SplitLayoutPanel-HDragger {
+ background: transparent url(hsplitter-grip.png) center center no-repeat;
+}
+
+.gwt-SplitLayoutPanel-VDragger {
+ background: transparent url(vsplitter-grip.png) center center no-repeat;
+}
diff --git a/bikeshed/war/Mail.html b/bikeshed/war/Mail.html
new file mode 100644
index 0000000..6f3cf17
--- /dev/null
+++ b/bikeshed/war/Mail.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <link type="text/css" rel="stylesheet" href="Mail.css">
+ <title>Mail Sample</title>
+ <script type="text/javascript" language="javascript" src="mail/mail.nocache.js"></script>
+ </head>
+
+ <body>
+ <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
+ <noscript>
+ <div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
+ Your web browser must have JavaScript enabled
+ in order for this application to display correctly.
+ </div>
+ </noscript>
+
+ <h1>Mail Sample</h1>
+ </body>
+</html>