Checkpoint validation work + some misc stock fixes
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7742 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/bikeshed/src/com/google/gwt/bikeshed/cells/client/FieldUpdater.java b/bikeshed/src/com/google/gwt/bikeshed/cells/client/FieldUpdater.java
index 2e0fd85..a02cdb9 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/cells/client/FieldUpdater.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/cells/client/FieldUpdater.java
@@ -26,9 +26,9 @@
/**
* Announces a new value for a field within a base object.
- *
+ * @param index TODO
* @param object the base object to be updated
* @param value the new value of the field being updated.
*/
- void update(T object, C value);
+ void update(int index, T object, C value);
}
diff --git a/bikeshed/src/com/google/gwt/bikeshed/list/client/Column.java b/bikeshed/src/com/google/gwt/bikeshed/list/client/Column.java
index dc81c23..7913c6a 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/list/client/Column.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/client/Column.java
@@ -35,17 +35,19 @@
this.cell = cell;
}
- public void onBrowserEvent(Element elem, final T object, NativeEvent event) {
+ public void onBrowserEvent(Element elem, final int index, final T object,
+ NativeEvent event) {
cell.onBrowserEvent(elem, getValue(object), event,
fieldUpdater == null ? null : new ValueUpdater<C>() {
public void update(C value) {
- fieldUpdater.update(object, value);
+ fieldUpdater.update(index, object, value);
}
});
}
public void render(T object, StringBuilder sb) {
- cell.render(getValue(object), sb);
+ C value = getValue(object);
+ cell.render(value, sb);
}
public void setFieldUpdater(FieldUpdater<T, C> fieldUpdater) {
@@ -56,5 +58,9 @@
return cell;
}
+ protected FieldUpdater<T, C> getFieldUpdater() {
+ return fieldUpdater;
+ }
+
protected abstract C getValue(T object);
-}
\ No newline at end of file
+}
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 271cd97..5959cd7 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/client/PagingTableListView.java
@@ -149,7 +149,7 @@
int row = tr.getSectionRowIndex();
T value = data.get(row);
Column<T, ?> column = columns.get(col);
- column.onBrowserEvent(cell, value, event);
+ column.onBrowserEvent(cell, curPage * pageSize + row, value, event);
}
}
diff --git a/bikeshed/src/com/google/gwt/bikeshed/list/shared/AbstractListModel.java b/bikeshed/src/com/google/gwt/bikeshed/list/shared/AbstractListModel.java
index 7152c27..f46dba0 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/list/shared/AbstractListModel.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/shared/AbstractListModel.java
@@ -151,10 +151,6 @@
protected void updateViewData(int start, int length, List<T> values) {
int end = start + length;
for (DefaultListRegistration reg : registrations) {
- // Inform the views if there is no data
- if (values.size() == 0) {
- reg.getHandler().onSizeChanged(new SizeChangeEvent(0, true));
- }
int curStart = reg.getStart();
int curLength = reg.getLength();
int curEnd = curStart + curLength;
diff --git a/bikeshed/src/com/google/gwt/bikeshed/list/shared/ListListModel.java b/bikeshed/src/com/google/gwt/bikeshed/list/shared/ListListModel.java
index 5eaf458..74e8977 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/list/shared/ListListModel.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/shared/ListListModel.java
@@ -223,6 +223,7 @@
@Override
protected void onRangeChanged() {
+ updateDataSize(listWrapper.size(), true);
updateViewData(0, listWrapper.size(), listWrapper);
}
}
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/FavoritesWidget.java b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/FavoritesWidget.java
index c099b4d..ef2f97e 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/FavoritesWidget.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/FavoritesWidget.java
@@ -47,6 +47,7 @@
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.buyColumn);
listView.addColumn(Columns.sellColumn);
}
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java
index 619feff..6aa5f9f 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/stocks/client/StockSample.java
@@ -143,19 +143,19 @@
// Hook up handlers to columns and the buy/sell popup.
Columns.favoriteColumn.setFieldUpdater(new FieldUpdater<StockQuote, Boolean>() {
- public void update(StockQuote object, Boolean value) {
+ public void update(int index, StockQuote object, Boolean value) {
setFavorite(object.getTicker(), value);
}
});
Columns.buyColumn.setFieldUpdater(new FieldUpdater<StockQuote, String>() {
- public void update(StockQuote quote, String value) {
+ public void update(int index, StockQuote quote, String value) {
buy(quote);
}
});
Columns.sellColumn.setFieldUpdater(new FieldUpdater<StockQuote, String>() {
- public void update(StockQuote quote, String value) {
+ public void update(int index, StockQuote quote, String value) {
sell(quote);
}
});
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/validation/Validation.gwt.xml b/bikeshed/src/com/google/gwt/bikeshed/sample/validation/Validation.gwt.xml
new file mode 100644
index 0000000..ea4cccf
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/validation/Validation.gwt.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
+<module rename-to='validation'>
+ <inherits name="com.google.gwt.bikeshed.list.List" />
+ <source path="client" />
+ <entry-point
+ class="com.google.gwt.bikeshed.sample.validation.client.Validation">
+ </entry-point>
+</module>
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/ValidatableColumn.java b/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/ValidatableColumn.java
new file mode 100644
index 0000000..e3600ba
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/ValidatableColumn.java
@@ -0,0 +1,80 @@
+/*
+ * 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.sample.validation.client;
+
+import com.google.gwt.bikeshed.cells.client.Cell;
+import com.google.gwt.bikeshed.cells.client.FieldUpdater;
+import com.google.gwt.bikeshed.cells.client.ValueUpdater;
+import com.google.gwt.bikeshed.list.client.Column;
+import com.google.gwt.bikeshed.sample.validation.client.ValidatableField.DefaultValidatableField;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NativeEvent;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A column that support validation.
+ *
+ * @param <T> the row type
+ * @param <C> the column type
+ */
+// TODO - avoid wrapping cells that are never modified
+public abstract class ValidatableColumn<T, C> extends Column<T, ValidatableField<C>> {
+
+ Map<T, ValidatableField<C>> fieldMap = new HashMap<T, ValidatableField<C>>();
+
+ public ValidatableColumn(Cell<ValidatableField<C>> cell) {
+ super(cell);
+ }
+
+ // Override onBrowserEvent to copy the ValueUpdater value into our copy
+ @Override
+ public void onBrowserEvent(Element elem, final int index, final T object,
+ NativeEvent event) {
+ final FieldUpdater<T, ValidatableField<C>> fieldUpdater = getFieldUpdater();
+ final ValidatableField<C> field = getValue(object);
+ getCell().onBrowserEvent(elem, field, event,
+ fieldUpdater == null ? null : new ValueUpdater<ValidatableField<C>>() {
+ public void update(ValidatableField<C> value) {
+ // Copy pending value from value (copy) to field (original)
+ field.setPendingValue(value.getPendingValue());
+ fieldUpdater.update(index, object, field);
+ }
+ });
+ }
+
+ /**
+ * Returns the value of the field with the underlying object that is to be
+ * validated.
+ *
+ * @param object the underlying data transfer object, of type T
+ * @return a value of type C
+ */
+ protected abstract C getValidatableValue(T object);
+
+ @Override
+ protected ValidatableField<C> getValue(T object) {
+ ValidatableField<C> vfield = fieldMap.get(object);
+ if (vfield == null) {
+ C validatableValue = getValidatableValue(object);
+ vfield = new DefaultValidatableField<C>(validatableValue);
+ fieldMap.put(object, vfield);
+ }
+
+ return vfield;
+ }
+}
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/ValidatableField.java b/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/ValidatableField.java
new file mode 100644
index 0000000..9b9d070
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/ValidatableField.java
@@ -0,0 +1,81 @@
+/*
+ * 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.sample.validation.client;
+
+/**
+ * A field value with a pending future value and a valid flag.
+ *
+ * @param <T> the value type of the field
+ */
+public interface ValidatableField<T> {
+ T getPendingValue();
+ T getValue();
+ boolean isInvalid();
+ void setInvalid(boolean isInvalid);
+ void setPendingValue(T pendingValue);
+ void setValue(T value);
+
+ /**
+ * Default implementation of ValidatableField.
+ *
+ * @param <T> the value type of the field
+ */
+ public static class DefaultValidatableField<T> implements ValidatableField<T> {
+ static int genserial = 0;
+ int serial;
+ boolean isInvalid;
+ T pendingValue;
+ T value;
+
+ public DefaultValidatableField(T value) {
+ this.serial = genserial++;
+ this.value = value;
+ }
+
+ public DefaultValidatableField(ValidatableField<T> other) {
+ if (other instanceof DefaultValidatableField<?>) {
+ this.serial = ((DefaultValidatableField<T>) other).serial;
+ }
+ this.value = other.getValue();
+ this.pendingValue = other.getPendingValue();
+ this.isInvalid = other.isInvalid();
+ }
+
+ public T getPendingValue() {
+ return pendingValue;
+ }
+
+ public T getValue() {
+ return value;
+ }
+
+ public boolean isInvalid() {
+ return isInvalid;
+ }
+
+ public void setInvalid(boolean isInvalid) {
+ this.isInvalid = isInvalid;
+ }
+
+ public void setPendingValue(T pendingValue) {
+ this.pendingValue = pendingValue;
+ }
+
+ public void setValue(T value) {
+ this.value = value;
+ }
+ }
+}
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/ValidatableInputCell.java b/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/ValidatableInputCell.java
new file mode 100644
index 0000000..2babea5
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/ValidatableInputCell.java
@@ -0,0 +1,63 @@
+/*
+ * 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.sample.validation.client;
+
+import com.google.gwt.bikeshed.cells.client.Cell;
+import com.google.gwt.bikeshed.cells.client.ValueUpdater;
+import com.google.gwt.bikeshed.sample.validation.client.ValidatableField.DefaultValidatableField;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.InputElement;
+import com.google.gwt.dom.client.NativeEvent;
+
+/**
+ * A String Cell that supports validation.
+ */
+public class ValidatableInputCell extends Cell<ValidatableField<String>> {
+
+ @Override
+ public void onBrowserEvent(Element parent, ValidatableField<String> value, NativeEvent event,
+ ValueUpdater<ValidatableField<String>> valueUpdater) {
+ if (event.getType().equals("change")) {
+ InputElement input = parent.getFirstChild().cast();
+
+ // Mark as pending
+ input.getStyle().setColor("blue");
+
+ ValidatableField<String> field = new DefaultValidatableField<String>(value);
+ field.setPendingValue(input.getValue());
+ valueUpdater.update(field);
+ }
+ }
+
+ @Override
+ public void render(ValidatableField<String> value, StringBuilder sb) {
+ String pendingValue = value.getPendingValue();
+ sb.append("<input type=\"text\" value=\"");
+ boolean invalid = value.isInvalid();
+ if (pendingValue != null) {
+ sb.append(pendingValue);
+ } else {
+ sb.append(value.getValue());
+ }
+ sb.append("\" style=\"color:");
+ if (pendingValue != null) {
+ sb.append(invalid ? "red" : "blue");
+ } else {
+ sb.append("black");
+ }
+ sb.append("\"></input>");
+ }
+}
diff --git a/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/Validation.java b/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/Validation.java
new file mode 100644
index 0000000..cfd1910
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/bikeshed/sample/validation/client/Validation.java
@@ -0,0 +1,139 @@
+/*
+ * 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.sample.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.PagingTableListView;
+import com.google.gwt.bikeshed.list.shared.ListListModel;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.RootPanel;
+
+import java.util.List;
+
+/**
+ * Validation demo.
+ */
+public class Validation implements EntryPoint {
+
+ static class Address {
+ static int genkey = 0;
+ int key;
+ String message;
+ String state;
+ String zip;
+ boolean zipInvalid;
+
+ public Address(Address address) {
+ this.key = address.key;
+ this.state = address.state;
+ this.zip = address.zip;
+ }
+
+ public Address(String state, String zip) {
+ this.key = genkey++;
+ this.state = state;
+ this.zip = zip;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Address)) {
+ return false;
+ }
+ return ((Address) other).key == key;
+ }
+
+ @Override
+ public int hashCode() {
+ return key;
+ }
+ }
+
+ public static boolean zipInvalid(int zip) {
+ return zip % 3 == 0;
+ }
+
+ public void onModuleLoad() {
+ ListListModel<Address> listModel = new ListListModel<Address>();
+ final List<Address> list = listModel.getList();
+ for (int i = 10; i < 50; i++) {
+ if (zipInvalid(30000 + i)) {
+ continue;
+ }
+
+ String zip = "300" + i;
+ list.add(new Address("GA", zip));
+ }
+
+ PagingTableListView<Address> table = new PagingTableListView<Address>(listModel, 10);
+ Column<Address, String> stateColumn = new Column<Address, String>(new TextCell()) {
+ @Override
+ protected String getValue(Address object) {
+ return object.state;
+ }
+ };
+
+ ValidatableColumn<Address, String> zipColumn =
+ new ValidatableColumn<Address, String>(new ValidatableInputCell()) {
+ @Override
+ protected String getValidatableValue(Address object) {
+ return object.zip;
+ }
+ };
+ zipColumn.setFieldUpdater(new FieldUpdater<Address, ValidatableField<String>>() {
+ public void update(final int index, final Address object, final ValidatableField<String> value) {
+ // Perform validation after a 2-second delay
+ new Timer() {
+ @Override
+ public void run() {
+ String pendingValue = value.getPendingValue();
+
+ int zip = Integer.parseInt(pendingValue);
+ boolean zipInvalid = Validation.zipInvalid(zip);
+
+ final Address newValue = new Address(object);
+ newValue.zip = pendingValue == null ? value.getValue() : pendingValue;
+ newValue.zipInvalid = zipInvalid;
+
+ value.setInvalid(zipInvalid);
+ if (!zipInvalid) {
+ value.setValue(pendingValue);
+ value.setPendingValue(null);
+ }
+
+ list.set(index, newValue);
+ }
+ }.schedule(2000);
+ }
+ });
+
+ Column<Address, String> messageColumn = new Column<Address, String>(new TextCell()) {
+ @Override
+ protected String getValue(Address object) {
+ return object.zipInvalid ? "Please fix the zip code" : "";
+ }
+ };
+
+ table.addColumn(stateColumn);
+ table.addColumn(zipColumn);
+ table.addColumn(messageColumn);
+
+ RootPanel.get().add(table);
+ }
+}
diff --git a/bikeshed/war/Validation.html b/bikeshed/war/Validation.html
new file mode 100644
index 0000000..93317bf
--- /dev/null
+++ b/bikeshed/war/Validation.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <title>Validation</title>
+ <script type="text/javascript" language="javascript" src="validation/validation.nocache.js"></script>
+ </head>
+
+ <body>
+ <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
+
+ </body>
+</html>