Removing the Expenses sample from bikeshed now that it has been converted to a sample. I'm leaving the Scaffold app for now until I know that its safe to delete it.
Review at http://gwt-code-reviews.appspot.com/791801
Review by: cramsdale@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8624 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/Cookbook.gwt.xml b/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/Cookbook.gwt.xml
index 7560bd1..0ee4466 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/Cookbook.gwt.xml
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/cookbook/Cookbook.gwt.xml
@@ -1,7 +1,6 @@
<module rename-to='cookbook'>
<inherits name="com.google.gwt.requestfactory.RequestFactory"/>
<inherits name='com.google.gwt.user.User'/>
- <inherits name='com.google.gwt.sample.bikeshed.style.Style'/>
<inherits name='com.google.gwt.user.cellview.CellView'/>
<entry-point class='com.google.gwt.sample.bikeshed.cookbook.client.Cookbook'/>
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/Style.gwt.xml b/bikeshed/src/com/google/gwt/sample/bikeshed/style/Style.gwt.xml
deleted file mode 100644
index 05ad12f..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/Style.gwt.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<module>
- <inherits name="com.google.gwt.resources.Resources"/>
- <source path='client'/>
-</module>
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/Styles.java b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/Styles.java
deleted file mode 100644
index 6740c43..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/Styles.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.style.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.CssResource;
-import com.google.gwt.resources.client.ImageResource;
-import com.google.gwt.resources.client.CssResource.NotStrict;
-
-/**
- * The Styles used in bikeshed.
- */
-public class Styles {
-
- /**
- * Common styles.
- */
- public interface Common extends CssResource {
-
- String approvedOption();
-
- String blankOption();
-
- String box();
-
- String deniedOption();
-
- /**
- * Applied to the amount column in ExpenseDetails.
- */
- String expenseDetailsAmountColumn();
-
- /**
- * Applied to the approval column in ExpenseDetails.
- */
- String expenseDetailsApprovalColumn();
-
- /**
- * Applied to the category column in ExpenseDetails.
- */
- String expenseDetailsCategoryColumn();
-
- /**
- * Applied to the date column in ExpenseDetails.
- */
- String expenseDetailsDateColumn();
-
- /**
- * Applied to the message in the error popup.
- */
- String expenseDetailsErrorPopupMessage();
-
- /**
- * Applied to the created column in ExpenseList.
- */
- String expenseListCreatedColumn();
-
- /**
- * Applied to the department column in ExpenseList.
- */
- String expenseListDepartmentColumn();
-
- /**
- * Applied to the purpose column in ExpenseList.
- */
- String expenseListPurposeColumn();
-
- String header();
-
- String headerLeft();
-
- String headerMain();
-
- String padded();
-
- /**
- * Applied to popup panels.
- */
- String popupPanel();
-
- /**
- * Applied to columns used as spacers.
- */
- String spacerColumn();
-
- String table();
-
- /**
- * Applied to the username portion of a tree item.
- */
- String usernameTreeItem();
-
- /**
- * Applied to the username portion of a tree item when selected.
- */
- String usernameTreeItemSelected();
- }
-
- /**
- * Shared resources.
- */
- public interface Resources extends ClientBundle {
-
- @NotStrict
- @Source("common.css")
- Common common();
-
- /**
- * Icon used to represent an approved item.
- */
- ImageResource approvedIcon();
-
- /**
- * Blank icon used for spacing.
- */
- ImageResource blankIcon();
-
- /**
- * Icon used to represent a denied item.
- */
- ImageResource deniedIcon();
-
- /**
- * Icon used to represent an error.
- */
- ImageResource errorIcon();
-
- /**
- * Icon used to represent a user group.
- */
- ImageResource groupIcon();
-
- /**
- * Animated image used to indicate a pending change.
- */
- ImageResource pendingCommit();
-
- /**
- * Right rounded corner of a search box.
- */
- ImageResource searchRight();
-
- /**
- * Icon used to represent a user.
- */
- ImageResource userIcon();
- }
-
- private static Resources resources;
-
- static {
- resources = GWT.create(Resources.class);
- resources.common().ensureInjected();
- }
-
- public static Common common() {
- return resources.common();
- }
-
- public static Resources resources() {
- return resources;
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/approvedIcon.png b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/approvedIcon.png
deleted file mode 100644
index 9de89cc..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/approvedIcon.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/blankIcon.png b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/blankIcon.png
deleted file mode 100644
index cf5edd9..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/blankIcon.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/common.css b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/common.css
deleted file mode 100644
index fd6b29c..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/common.css
+++ /dev/null
@@ -1,220 +0,0 @@
-/* global */
-body, table, td {
- font-family: Arial, sans-serif;
- font-weight: light;
-}
-
-h1 {
- color: #4b4a4a;
-}
-
-/* odds and ends */
-.box {
- border: 1px solid #ccc;
- background-color: white;
- margin: 0.25em;
- padding: 0.5em;
- -webkit-border-radius: 4px;
- -moz-border-radius: 4px;
-}
-
-.padded {
- padding: 5px;
-}
-
-.header {
- font-weight: bold;
- font-size: 12pt;
- margin: 0.5em;
-}
-
-.headerLeft {
- font-weight: light;
- font-size: 12pt;
- margin-bottom: 0.5em;
-}
-
-.headerMain {
- font-weight: light;
- font-size: 18pt;
-}
-
-/* ExpenseTree */
-
-.usernameTreeItem {
- color: #999;
- font-size: 90%;
-}
-
-.usernameTreeItemSelected {
- color: white;
- font-size: 90%;
-}
-
-/* ExpenseList */
-.expenseListCreatedColumn {
- width: 25ex;
-}
-.expenseListDepartmentColumn {
- width: 25ex;
-}
-.expenseListPurposeColumn {
- width: 50ex;
-}
-
-/* EpenseDetails */
-.expenseDetailsDateColumn {
- width: 35ex;
-}
-.expenseDetailsCategoryColumn {
- width: 30ex;
-}
-.expenseDetailsAmountColumn {
- width: 18ex;
-}
-.expenseDetailsApprovalColumn {
- width: 250px;
-}
-.expenseDetailsErrorPopupMessage {
- width: 300px;
- padding-bottom: 10px;
- font-size: 130%;
- color: red;
- text-align: center;
-}
-
-.popupPanel {
- border: 3px solid white;
- border-right: 11px solid white;
- border-bottom: 11px solid white;
- -webkit-border-image: url(blueborder.png) 3 11 11 3 round round;
- -moz-border-image: url(blueborder.png) 3 11 11 3 round round;
- padding: 10px;
-}
-
-@sprite .blankOption {
- gwt-image: 'blankIcon';
- padding-left: 20px;
- width: auto;
- height: auto;
- overflow: auto;
-}
-
-@sprite .approvedOption {
- gwt-image: 'approvedIcon';
- padding-left: 20px;
- width: auto;
- height: auto;
- overflow: auto;
-}
-
-@sprite .deniedOption {
- gwt-image: 'deniedIcon';
- padding-left: 20px;
- width: auto;
- height: auto;
- overflow: auto;
-}
-
-.spacerColumn {
- width: 15px;
- border: 0 !important;
-}
-
-/* tables */
-.table {
- width: 100%;
- font-size: 8pt;
- border-spacing: 0px 0px;
- border-collapse: collapse;
-}
-
-.table td {
- border-bottom: 1px solid #ccc;
-}
-
-/* date picker */
-.gwt-DatePicker {
- border: 1px solid #A2BBDD;
- cursor: default;
-}
-.gwt-DatePicker td,
-.datePickerMonthSelector td:focus {
- outline: none
-}
-.datePickerDays {
- width: 100%;
- background: white;
-}
-.datePickerDay,
-.datePickerWeekdayLabel,
-.datePickerWeekendLabel {
- font-size: 75%;
- text-align: center;
- padding: 4px;
- outline: none;
-}
-.datePickerWeekdayLabel,
-.datePickerWeekendLabel {
- background: #C3D9FF;
- padding: 0px 4px 2px;
- cursor: default;
-}
-.datePickerDay {
- padding: 4px;
- cursor: hand;
- cursor: pointer;
-}
-.datePickerDayIsToday {
- border: 1px solid black;
- padding: 3px;
-}
-.datePickerDayIsWeekend {
- background: #EEEEEE;
-}
-.datePickerDayIsFiller {
- color: #888888;
-}
-.datePickerDayIsValue {
- background: #aaccee;
-}
-.datePickerDayIsDisabled {
- color: #AAAAAA;
- font-style: italic;
-}
-.datePickerDayIsHighlighted {
- background: #F0E68C;
-}
-.datePickerDayIsValueAndHighlighted {
- background: #bbddd9;
-}
-.datePickerMonthSelector {
- background: #C3D9FF;
- width: 100%;
-}
-td.datePickerMonth {
- text-align: center;
- vertical-align: center;
- white-space: nowrap;
- font-size: 70%;
- font-weight: bold;
- color: blue;
-}
-.datePickerPreviousButton,
-.datePickerNextButton {
- font-size: 120%;
- line-height: 1em;
- color: blue;
- cursor: hand;
- cursor: pointer;
- padding: 0px 4px;
-}
-
-/* splitters */
-.gwt-SplitLayoutPanel-HDragger {
- background: #b6cef3 url(hsplitter-grip.png) center center no-repeat;
-}
-
-.gwt-SplitLayoutPanel-VDragger {
- background: #b6cef3 url(vsplitter-grip.png) center center no-repeat;
-}
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/deniedIcon.png b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/deniedIcon.png
deleted file mode 100644
index 85dc91a..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/deniedIcon.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/errorIcon.png b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/errorIcon.png
deleted file mode 100644
index 07d8899..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/errorIcon.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/groupIcon.png b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/groupIcon.png
deleted file mode 100644
index af8e401..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/groupIcon.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/pendingCommit.gif b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/pendingCommit.gif
deleted file mode 100644
index dbe1ce9..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/pendingCommit.gif
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/searchCenter.png b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/searchCenter.png
deleted file mode 100644
index 582af8e..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/searchCenter.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/searchLeft.png b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/searchLeft.png
deleted file mode 100644
index 9c86965..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/searchLeft.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/searchRight.png b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/searchRight.png
deleted file mode 100644
index 2841b7b..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/searchRight.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/userIcon.png b/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/userIcon.png
deleted file mode 100644
index bbf73fd..0000000
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/style/client/userIcon.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/Expenses.gwt.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/Expenses.gwt.xml
deleted file mode 100644
index 2fcbfba..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/Expenses.gwt.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?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="expenses">
- <inherits name="com.google.gwt.user.User" />
- <inherits name="com.google.gwt.user.theme.standard.Standard" />
-
- <inherits name="com.google.gwt.sample.expenses.gwt.ExpensesCommon" />
- <entry-point class="com.google.gwt.sample.expenses.gwt.client.Expenses" />
-</module>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/ExpensesCommon.gwt.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/ExpensesCommon.gwt.xml
index a06a5db..4b0cfa9 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/ExpensesCommon.gwt.xml
+++ b/bikeshed/src/com/google/gwt/sample/expenses/gwt/ExpensesCommon.gwt.xml
@@ -3,7 +3,6 @@
<module>
<inherits name='com.google.gwt.app.App' />
<inherits name='com.google.gwt.requestfactory.RequestFactory'/>
- <inherits name='com.google.gwt.sample.bikeshed.style.Style'/>
<inherits name='com.google.gwt.mobile.Mobile'/>
<inherits name='com.google.gwt.user.cellview.CellView'/>
<inherits name='com.google.gwt.logging.Logging'/>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/ExpensesMobile.gwt.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/ExpensesMobile.gwt.xml
deleted file mode 100644
index 3ecd874..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/ExpensesMobile.gwt.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?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="expensesMobile">
- <inherits name="com.google.gwt.user.User" />
- <inherits name="com.google.gwt.user.theme.standard.Standard" />
-
- <inherits name="com.google.gwt.sample.expenses.gwt.ExpensesCommon" />
- <entry-point class="com.google.gwt.sample.expenses.gwt.client.ExpensesMobile" />
-</module>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/ScaffoldCommon.gwt.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/ScaffoldCommon.gwt.xml
index e0428be..ca00444 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/ScaffoldCommon.gwt.xml
+++ b/bikeshed/src/com/google/gwt/sample/expenses/gwt/ScaffoldCommon.gwt.xml
@@ -3,7 +3,6 @@
<module>
<inherits name='com.google.gwt.app.App' />
<inherits name='com.google.gwt.requestfactory.RequestFactory'/>
- <inherits name='com.google.gwt.sample.bikeshed.style.Style'/>
<inherits name='com.google.gwt.mobile.Mobile'/>
<inherits name='com.google.gwt.user.cellview.CellView'/>
<inherits name='com.google.gwt.logging.Logging'/>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.java
deleted file mode 100644
index 1ca7aa6..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.java
+++ /dev/null
@@ -1,1052 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.cell.client.AbstractEditableCell;
-import com.google.gwt.cell.client.Cell;
-import com.google.gwt.cell.client.DateCell;
-import com.google.gwt.cell.client.FieldUpdater;
-import com.google.gwt.cell.client.NumberCell;
-import com.google.gwt.cell.client.TextCell;
-import com.google.gwt.cell.client.ValueUpdater;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.dom.client.SelectElement;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.i18n.client.NumberFormat;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.requestfactory.shared.RequestObject;
-import com.google.gwt.resources.client.ImageResource;
-import com.google.gwt.sample.bikeshed.style.client.Styles;
-import com.google.gwt.sample.expenses.gwt.request.EmployeeRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpenseRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpenseRecordChanged;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecord;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecordChanged;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiFactory;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.cellview.client.CellTable;
-import com.google.gwt.user.cellview.client.Column;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.HasVerticalAlignment;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.valuestore.shared.Property;
-import com.google.gwt.valuestore.shared.Record;
-import com.google.gwt.valuestore.shared.SyncResult;
-import com.google.gwt.view.client.ListDataProvider;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Details about the current expense report on the right side of the app,
- * including the list of expenses.
- */
-public class ExpenseDetails extends Composite
- implements ExpenseRecordChanged.Handler, ReportRecordChanged.Handler {
-
- /**
- * The maximum amount that can be approved for a given report.
- */
- private static final int MAX_COST = 250;
-
- /**
- * The auto refresh interval in milliseconds.
- */
- private static final int REFRESH_INTERVAL = 5000;
-
- /**
- * The ViewData associated with the {@link ApprovalCell}.
- */
- private static class ApprovalViewData {
- private final String pendingApproval;
- private String rejectionText;
-
- public ApprovalViewData(String approval) {
- this.pendingApproval = approval;
- }
-
- public String getPendingApproval() {
- return pendingApproval;
- }
-
- public String getRejectionText() {
- return rejectionText;
- }
-
- public boolean isRejected() {
- return rejectionText != null;
- }
-
- public void reject(String text) {
- this.rejectionText = text;
- }
- }
-
- /**
- * The cell used for approval status.
- */
- private class ApprovalCell extends AbstractEditableCell<
- String, ApprovalViewData> {
-
- private final String approvedText = Expenses.Approval.APPROVED.getText();
- private final String deniedText = Expenses.Approval.DENIED.getText();
- private final String errorIconHtml;
- private final String pendingIconHtml;
-
- public ApprovalCell() {
- super("change", "click");
-
- // Cache the html string for the error icon.
- ImageResource errorIcon = Styles.resources().errorIcon();
- AbstractImagePrototype errorImg = AbstractImagePrototype.create(
- errorIcon);
- errorIconHtml = errorImg.getHTML();
-
- // Cache the html string for the pending icon.
- ImageResource pendingIcon = Styles.resources().pendingCommit();
- AbstractImagePrototype pendingImg = AbstractImagePrototype.create(
- pendingIcon);
- pendingIconHtml = pendingImg.getHTML();
- }
-
- @Override
- public void onBrowserEvent(Element parent, String value, Object key,
- NativeEvent event, ValueUpdater<String> valueUpdater) {
- String type = event.getType();
- ApprovalViewData viewData = getViewData(key);
- if ("change".equals(type)) {
- // Disable the select box.
- SelectElement select = parent.getFirstChild().cast();
- select.setDisabled(true);
-
- // Add the pending icon if it isn't already visible.
- if (viewData == null) {
- Element tmpElem = Document.get().createDivElement();
- tmpElem.setInnerHTML(pendingIconHtml);
- parent.appendChild(tmpElem.getFirstChildElement());
- }
-
- // Remember which value is now selected.
- int index = select.getSelectedIndex();
- String pendingValue = select.getOptions().getItem(index).getValue();
- viewData = new ApprovalViewData(pendingValue);
- setViewData(key, viewData);
-
- // Update the value updater.
- if (valueUpdater != null) {
- valueUpdater.update(pendingValue);
- }
- } else if ("click".equals(type) && viewData != null
- && parent.getChildCount() >= 3) {
- // Alert the user of the error
- Element img = parent.getChild(1).cast();
- Element anchor = img.getNextSiblingElement();
- if (anchor.isOrHasChild(Element.as(event.getEventTarget().cast()))) {
- // Alert the user of the error.
- showErrorPopup(viewData.getRejectionText());
-
- // Clear the view data now that we've viewed the message.
- clearViewData(key);
- parent.removeChild(anchor);
- parent.removeChild(img);
- }
- }
- }
-
- @Override
- public void render(String value, Object key, StringBuilder sb) {
- // Get the view data.
- ApprovalViewData viewData = getViewData(key);
- if (viewData != null && viewData.getPendingApproval().equals(value)) {
- clearViewData(key);
- viewData = null;
- }
-
- boolean isRejected = false;
- boolean isDisabled = false;
- String pendingValue = null;
- String renderValue = value;
- if (viewData != null) {
- isRejected = viewData.isRejected();
- pendingValue = viewData.getPendingApproval();
- if (!isRejected) {
- renderValue = pendingValue;
- // If there is a delta value that has not been rejected, then the
- // combo box should remain disabled.
- isDisabled = true;
- }
- }
- boolean isApproved = approvedText.equals(renderValue);
- boolean isDenied = deniedText.equals(renderValue);
-
- // Create the select element.
- sb.append("<select style='background-color:white;");
- sb.append("border:1px solid #707172;width:10em;margin-right:10px;'");
- if (isDisabled) {
- sb.append(" disabled='true'");
- }
- sb.append(">");
- sb.append("<option></option>");
-
- // Approved Option.
- sb.append("<option");
- if (isApproved) {
- sb.append(" selected='selected'");
- }
- sb.append(">").append(approvedText).append("</option>");
-
- // Denied Option.
- sb.append("<option");
- if (isDenied) {
- sb.append(" selected='selected'");
- }
- sb.append(">").append(deniedText).append("</option>");
-
- sb.append("</select>");
-
- // Add an icon indicating the commit state.
- if (isRejected) {
- // Add error icon if viewData does not match.
- sb.append(errorIconHtml);
- sb.append(
- "<a style='padding-left:3px;color:red;' href='javascript:;'>Error!</a>");
- } else if (pendingValue != null) {
- // Add refresh icon if pending.
- sb.append(pendingIconHtml);
- }
- }
- }
-
- /**
- * The popup used to enter the rejection reason.
- */
- private class DenialPopup extends PopupPanel {
- private Button cancelButton = new Button("Cancel", new ClickHandler() {
- public void onClick(ClickEvent event) {
- reasonDenied = "";
- hide();
- }
- });
- private Button confirmButton = new Button("Confirm", new ClickHandler() {
- public void onClick(ClickEvent event) {
- reasonDenied = reasonBox.getText();
- hide();
- }
- });
-
- private ExpenseRecord expenseRecord;
- private TextBox reasonBox = new TextBox();
- private String reasonDenied;
-
- public DenialPopup() {
- super(false, true);
- setStyleName(Styles.common().popupPanel());
- setGlassEnabled(true);
- confirmButton.setWidth("11ex");
- cancelButton.setWidth("11ex");
- reasonBox.getElement().getStyle().setMarginLeft(10.0, Unit.PX);
- reasonBox.getElement().getStyle().setMarginRight(10.0, Unit.PX);
-
- HorizontalPanel hPanel = new HorizontalPanel();
- hPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
- hPanel.add(new HTML("<b>Reason:</b>"));
- hPanel.add(reasonBox);
- hPanel.add(confirmButton);
- hPanel.add(cancelButton);
- setWidget(hPanel);
- cancelButton.getElement().getParentElement().getStyle().setPaddingLeft(
- 5.0, Unit.PX);
- }
-
- public ExpenseRecord getExpenseRecord() {
- return expenseRecord;
- }
-
- public String getReasonDenied() {
- return reasonDenied;
- }
-
- public void popup() {
- center();
- reasonBox.setFocus(true);
- }
-
- public void setExpenseRecord(ExpenseRecord expenseRecord) {
- this.expenseRecord = expenseRecord;
- }
-
- public void setReasonDenied(String reasonDenied) {
- this.reasonDenied = reasonDenied;
- reasonBox.setText(reasonDenied);
- }
- }
-
- interface ExpenseDetailsUiBinder extends UiBinder<Widget, ExpenseDetails> {
- }
-
- /**
- * The styles applied to the table.
- */
- interface TableStyle extends CellTable.CleanStyle {
- String evenRow();
-
- String hoveredRow();
-
- String oddRow();
-
- String selectedRow();
- }
-
- /**
- * The resources applied to the table.
- */
- interface TableResources extends CellTable.CleanResources {
- @Source("ExpenseDetailsCellTable.css")
- TableStyle cellTableStyle();
- }
-
- private static ExpenseDetailsUiBinder uiBinder = GWT.create(
- ExpenseDetailsUiBinder.class);
-
- @UiField
- Element approvedLabel;
-
- @UiField
- Element costLabel;
-
- ExpensesRequestFactory expensesRequestFactory;
-
- @UiField
- Element notes;
-
- @UiField
- TextBox notesBox;
-
- @UiField
- Anchor notesEditLink;
-
- @UiField
- Element notesEditLinkWrapper;
-
- @UiField
- Element notesPending;
-
- @UiField
- Element reportName;
-
- @UiField
- Anchor reportsLink;
-
- @UiField
- CellTable<ExpenseRecord> table;
-
- @UiField
- Element unreconciledLabel;
-
- private List<SortableHeader> allHeaders = new ArrayList<SortableHeader>();
-
- private ApprovalCell approvalCell;
-
- /**
- * The default {@link Comparator} used for sorting.
- */
- private Comparator<ExpenseRecord> defaultComparator;
-
- /**
- * The popup used to display errors to the user.
- */
- private final PopupPanel errorPopup = new PopupPanel(false, true);
-
- /**
- * The label inside the error popup.
- */
- private final Label errorPopupMessage = new Label();
-
- /**
- * The data provider that provides expense items.
- */
- private final ListDataProvider<ExpenseRecord> items;
-
- /**
- * The set of Expense keys that we have seen. When a new key is added, we
- * compare it to the list of known keys to determine if it is new.
- */
- private Map<Object, ExpenseRecord> knownExpenseKeys = null;
-
- private Comparator<ExpenseRecord> lastComparator;
-
- /**
- * Keep track of the last receiver so we can ignore stale responses.
- */
- private Receiver<List<ExpenseRecord>> lastReceiver;
-
- /**
- * The {@link Timer} used to periodically refresh the table.
- */
- private final Timer refreshTimer = new Timer() {
- @Override
- public void run() {
- requestExpenses();
- }
- };
-
- /**
- * The current report being displayed.
- */
- private ReportRecord report;
-
- /**
- * The total amount that has been approved.
- */
- private double totalApproved;
-
- public ExpenseDetails() {
- createErrorPopup();
- initWidget(uiBinder.createAndBindUi(this));
- items = new ListDataProvider<ExpenseRecord>();
- items.setKeyProvider(Expenses.EXPENSE_RECORD_KEY_PROVIDER);
- table.setKeyProvider(items);
- items.addDataDisplay(table);
-
- // Switch to edit notes.
- notesEditLink.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent event) {
- setNotesEditState(true, false, report.getNotes());
- }
- });
-
- // Switch to view mode.
- notesBox.addBlurHandler(new BlurHandler() {
- public void onBlur(BlurEvent event) {
- // The text box will be blurred on cancel, so only save the notes if
- // it is visible.
- if (notesBox.isVisible()) {
- saveNotes();
- }
- }
- });
- notesBox.addKeyUpHandler(new KeyUpHandler() {
- public void onKeyUp(KeyUpEvent event) {
- int keyCode = event.getNativeKeyCode();
- switch (keyCode) {
- case KeyCodes.KEY_ENTER:
- saveNotes();
- break;
- case KeyCodes.KEY_ESCAPE:
- // Cancel the edit.
- setNotesEditState(false, false, report.getNotes());
- break;
- }
- }
- });
- }
-
- public Anchor getReportsLink() {
- return reportsLink;
- }
-
- public void onExpenseRecordChanged(ExpenseRecordChanged event) {
- ExpenseRecord newRecord = event.getRecord();
- Object newKey = items.getKey(newRecord);
-
- int index = 0;
- List<ExpenseRecord> list = items.getList();
- for (ExpenseRecord r : list) {
- if (items.getKey(r).equals(newKey)) {
- list.set(index, newRecord);
-
- // Update the view data if the approval has been updated.
- ApprovalViewData avd = approvalCell.getViewData(newKey);
- if (avd != null
- && avd.getPendingApproval().equals(newRecord.getApproval())) {
- syncCommit(newRecord, null);
- }
- }
- index++;
- }
-
- refreshCost();
- if (lastComparator != null) {
- sortExpenses(list, lastComparator);
- }
- }
-
- public void onReportChanged(ReportRecordChanged event) {
- ReportRecord changed = event.getRecord();
- if (report != null && report.getId().equals(changed.getId())) {
- report = changed;
- setNotesEditState(false, false, changed.getNotes());
- }
- }
-
- public void setExpensesRequestFactory(
- ExpensesRequestFactory expensesRequestFactory) {
- this.expensesRequestFactory = expensesRequestFactory;
- }
-
- /**
- * Set the {@link ReportRecord} to show.
- *
- * @param report the {@link ReportRecord}
- * @param department the selected department
- * @param employee the selected employee
- */
- public void setReportRecord(
- ReportRecord report, String department, EmployeeRecord employee) {
- this.report = report;
- knownExpenseKeys = null;
- reportName.setInnerText(report.getPurpose());
- costLabel.setInnerText("");
- approvedLabel.setInnerText("");
- unreconciledLabel.setInnerText("");
- setNotesEditState(false, false, report.getNotes());
- items.getList().clear();
- totalApproved = 0;
-
- // Update the breadcrumb.
- reportsLink.setText(ExpenseList.getBreadcrumb(department, employee));
-
- // Reset sorting state of table
- lastComparator = defaultComparator;
- for (SortableHeader header : allHeaders) {
- header.setSorted(false);
- header.setReverseSort(true);
- }
- allHeaders.get(0).setSorted(true);
- allHeaders.get(0).setReverseSort(false);
- table.redrawHeaders();
-
- // Request the expenses.
- requestExpenses();
- }
-
- @UiFactory
- CellTable<ExpenseRecord> createTable() {
- CellTable.Resources resources = GWT.create(TableResources.class);
- CellTable<ExpenseRecord> view = new CellTable<ExpenseRecord>(
- 100, resources);
- Styles.Common common = Styles.common();
- view.addColumnStyleName(0, common.spacerColumn());
- view.addColumnStyleName(1, common.expenseDetailsDateColumn());
- view.addColumnStyleName(3, common.expenseDetailsCategoryColumn());
- view.addColumnStyleName(4, common.expenseDetailsAmountColumn());
- view.addColumnStyleName(5, common.expenseDetailsApprovalColumn());
- view.addColumnStyleName(6, common.spacerColumn());
-
- // Spacer column.
- view.addColumn(new Column<ExpenseRecord, String>(new TextCell()) {
- @Override
- public String getValue(ExpenseRecord object) {
- return "<div style='display:none;'/>";
- }
- });
-
- // Created column.
- GetValue<ExpenseRecord, Date> createdGetter = new GetValue<
- ExpenseRecord, Date>() {
- public Date getValue(ExpenseRecord object) {
- return object.getCreated();
- }
- };
- defaultComparator = createColumnComparator(createdGetter, false);
- Comparator<ExpenseRecord> createdDesc = createColumnComparator(
- createdGetter, true);
- addColumn(view, "Created",
- new DateCell(DateTimeFormat.getFormat("MMM dd yyyy")), createdGetter,
- defaultComparator, createdDesc);
- lastComparator = defaultComparator;
-
- // Description column.
- addColumn(view, "Description", new TextCell(),
- new GetValue<ExpenseRecord, String>() {
- public String getValue(ExpenseRecord object) {
- return object.getDescription();
- }
- });
-
- // Category column.
- addColumn(view, "Category", new TextCell(),
- new GetValue<ExpenseRecord, String>() {
- public String getValue(ExpenseRecord object) {
- return object.getCategory();
- }
- });
-
- // Amount column.
- final GetValue<ExpenseRecord, Double> amountGetter = new GetValue<
- ExpenseRecord, Double>() {
- public Double getValue(ExpenseRecord object) {
- return object.getAmount();
- }
- };
- Comparator<ExpenseRecord> amountAsc = createColumnComparator(
- amountGetter, false);
- Comparator<ExpenseRecord> amountDesc = createColumnComparator(
- amountGetter, true);
- addColumn(view, "Amount", new NumberCell(NumberFormat.getCurrencyFormat()),
- new GetValue<ExpenseRecord, Number>() {
- public Number getValue(ExpenseRecord object) {
- return amountGetter.getValue(object);
- }
- }, amountAsc, amountDesc);
-
- // Dialog box to obtain a reason for a denial
- final DenialPopup denialPopup = new DenialPopup();
- denialPopup.addCloseHandler(new CloseHandler<PopupPanel>() {
- public void onClose(CloseEvent<PopupPanel> event) {
- String reasonDenied = denialPopup.getReasonDenied();
- ExpenseRecord record = denialPopup.getExpenseRecord();
- if (reasonDenied == null || reasonDenied.length() == 0) {
- // We need to redraw the table to reset the select box.
- syncCommit(record, null);
- } else {
- updateExpenseRecord(record, "Denied", reasonDenied);
- }
- }
- });
-
- // Approval column.
- approvalCell = new ApprovalCell();
- Column<ExpenseRecord, String> approvalColumn = addColumn(view,
- "Approval Status", approvalCell, new GetValue<ExpenseRecord, String>() {
- public String getValue(ExpenseRecord object) {
- return object.getApproval();
- }
- });
- approvalColumn.setFieldUpdater(new FieldUpdater<ExpenseRecord, String>() {
- public void update(int index, final ExpenseRecord object, String value) {
- if ("Denied".equals(value)) {
- denialPopup.setExpenseRecord(object);
- denialPopup.setReasonDenied(object.getReasonDenied());
- denialPopup.popup();
- } else {
- updateExpenseRecord(object, value, "");
- }
- }
- });
-
- // Spacer column.
- view.addColumn(new Column<ExpenseRecord, String>(new TextCell()) {
- @Override
- public String getValue(ExpenseRecord object) {
- return "<div style='display:none;'/>";
- }
- });
-
- return view;
- }
-
- /**
- * Add a column of a {@link Comparable} type using default comparators.
- *
- * @param <C> the column type
- * @param table the table
- * @param text the header text
- * @param cell the cell used to render values
- * @param getter the {@link GetValue} used to retrieve cell values
- * @return the new column
- */
- private <C extends Comparable<C>> Column<ExpenseRecord, C> addColumn(
- final CellTable<ExpenseRecord> table, final String text,
- final Cell<C> cell, final GetValue<ExpenseRecord, C> getter) {
- return addColumn(table, text, cell, getter,
- createColumnComparator(getter, false),
- createColumnComparator(getter, true));
- }
-
- /**
- * Add a column with the specified comparators.
- *
- * @param <C> the column type
- * @param table the table
- * @param text the header text
- * @param cell the cell used to render values
- * @param getter the {@link GetValue} used to retrieve cell values
- * @param ascComparator the comparator used to sort ascending
- * @param descComparator the comparator used to sort ascending
- * @return the new column
- */
- private <C> Column<ExpenseRecord, C> addColumn(
- final CellTable<ExpenseRecord> table, final String text,
- final Cell<C> cell, final GetValue<ExpenseRecord, C> getter,
- final Comparator<ExpenseRecord> ascComparator,
- final Comparator<ExpenseRecord> descComparator) {
-
- // Create the column.
- final Column<ExpenseRecord, C> column = new Column<ExpenseRecord, C>(cell) {
- @Override
- public C getValue(ExpenseRecord object) {
- return getter.getValue(object);
- }
- };
- final SortableHeader header = new SortableHeader(text);
- allHeaders.add(header);
-
- // Hook up sorting.
- header.setUpdater(new ValueUpdater<String>() {
- public void update(String value) {
- header.setSorted(true);
- header.toggleReverseSort();
-
- for (SortableHeader otherHeader : allHeaders) {
- if (otherHeader != header) {
- otherHeader.setSorted(false);
- otherHeader.setReverseSort(true);
- }
- }
-
- sortExpenses(items.getList(),
- header.getReverseSort() ? descComparator : ascComparator);
- table.redrawHeaders();
- }
- });
- table.addColumn(column, header);
- return column;
- }
-
- /**
- * Create a comparator for the column.
- *
- * @param <C> the column type
- * @param getter the {@link GetValue} used to get the cell value
- * @param descending true if descending, false if ascending
- * @return the comparator
- */
- private <C extends Comparable<C>> Comparator<
- ExpenseRecord> createColumnComparator(
- final GetValue<ExpenseRecord, C> getter, final boolean descending) {
- return new Comparator<ExpenseRecord>() {
- public int compare(ExpenseRecord o1, ExpenseRecord o2) {
- // Null check the row object.
- if (o1 == null && o2 == null) {
- return 0;
- } else if (o1 == null) {
- return descending ? 1 : -1;
- } else if (o2 == null) {
- return descending ? -1 : 1;
- }
-
- // Compare the column value.
- C c1 = getter.getValue(o1);
- C c2 = getter.getValue(o2);
- if (c1 == null && c2 == null) {
- return 0;
- } else if (c1 == null) {
- return descending ? 1 : -1;
- } else if (c2 == null) {
- return descending ? -1 : 1;
- }
- int comparison = c1.compareTo(c2);
- return descending ? -comparison : comparison;
- }
- };
- }
-
- /**
- * Create the error message popup.
- */
- private void createErrorPopup() {
- errorPopup.setGlassEnabled(true);
- errorPopup.setStyleName(Styles.common().popupPanel());
- errorPopupMessage.addStyleName(
- Styles.common().expenseDetailsErrorPopupMessage());
-
- Button closeButton = new Button("Dismiss", new ClickHandler() {
- public void onClick(ClickEvent event) {
- errorPopup.hide();
- }
- });
-
- // Organize the widgets in the popup.
- VerticalPanel layout = new VerticalPanel();
- layout.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
- layout.add(errorPopupMessage);
- layout.add(closeButton);
- errorPopup.setWidget(layout);
- }
-
- /**
- * Return a formatted currency string.
- *
- * @param amount the amount in dollars
- * @return a formatted string
- */
- private String formatCurrency(double amount) {
- boolean negative = amount < 0;
- if (negative) {
- amount = -amount;
- }
- int dollars = (int) amount;
- int cents = (int) ((amount * 100) % 100);
-
- StringBuilder sb = new StringBuilder();
- if (negative) {
- sb.append("-");
- }
- sb.append("$");
- sb.append(dollars);
- sb.append('.');
- if (cents < 10) {
- sb.append('0');
- }
- sb.append(cents);
- return sb.toString();
- }
-
- /**
- * Get the error message from a sync operation.
- *
- * @param response the response of the operation
- * @return the error message, or an empty string if no error.
- */
- private String getErrorMessageFromSync(Set<SyncResult> response) {
- String errorMessage = "";
- for (SyncResult result : response) {
- if (result.hasViolations()) {
- Map<String, String> violations = result.getViolations();
- for (String message : violations.values()) {
- errorMessage += message + " ";
- }
- }
- }
- return errorMessage;
- }
-
- /**
- * Get the columns displayed in the expense table.
- */
- private Collection<Property<?>> getExpenseColumns() {
- List<Property<?>> columns = new ArrayList<Property<?>>();
- columns.add(ExpenseRecord.amount);
- columns.add(ExpenseRecord.approval);
- columns.add(ExpenseRecord.category);
- columns.add(ExpenseRecord.created);
- columns.add(ExpenseRecord.description);
- columns.add(ExpenseRecord.reasonDenied);
- return columns;
- }
-
- /**
- * Refresh the total cost and approved amount.
- */
- private void refreshCost() {
- double totalCost = 0;
- totalApproved = 0;
- List<ExpenseRecord> records = items.getList();
- for (ExpenseRecord record : records) {
- double cost = record.getAmount();
- totalCost += cost;
- if (Expenses.Approval.APPROVED.is(record.getApproval())) {
- totalApproved += cost;
- }
- }
- double unreconciled = totalCost - totalApproved;
- costLabel.setInnerText(formatCurrency(totalCost));
- approvedLabel.setInnerText(formatCurrency(totalApproved));
- unreconciledLabel.setInnerText(formatCurrency(unreconciled));
- }
-
- /**
- * Request the expenses.
- */
- private void requestExpenses() {
- // Cancel the timer since we are about to send a request.
- refreshTimer.cancel();
- lastReceiver = new Receiver<List<ExpenseRecord>>() {
- public void onSuccess(
- List<ExpenseRecord> newValues, Set<SyncResult> syncResults) {
- if (this == lastReceiver) {
- List<ExpenseRecord> list = new ArrayList<ExpenseRecord>(newValues);
- sortExpenses(list, lastComparator);
- items.setList(list);
- refreshCost();
-
- // Add the new keys and changed values to the known keys.
- boolean isInitialData = knownExpenseKeys == null;
- if (knownExpenseKeys == null) {
- knownExpenseKeys = new HashMap<Object, ExpenseRecord>();
- }
- for (ExpenseRecord value : newValues) {
- Object key = items.getKey(value);
- if (!isInitialData) {
- ExpenseRecord existing = knownExpenseKeys.get(key);
- if (existing == null
- || !value.getAmount().equals(existing.getAmount())
- || !value.getDescription().equals(existing.getDescription())
- || !value.getCategory().equals(existing.getCategory())) {
- (new PhaseAnimation.CellTablePhaseAnimation<ExpenseRecord>(
- table, value, items)).run();
- }
- }
- knownExpenseKeys.put(key, value);
- }
- }
-
- // Reschedule the timer.
- refreshTimer.schedule(REFRESH_INTERVAL);
- }
- };
- expensesRequestFactory.expenseRequest().findExpensesByReport(
- report.getRef(Record.id)).forProperties(getExpenseColumns()).fire(
- lastReceiver);
- }
-
- /**
- * Save the notes that the user entered in the notes box.
- */
- private void saveNotes() {
- // Early exit if the notes haven't changed.
- final String pendingNotes = notesBox.getText();
- if (pendingNotes.equals(report.getNotes())) {
- setNotesEditState(false, false, pendingNotes);
- return;
- }
-
- // Switch to the pending view.
- setNotesEditState(false, true, pendingNotes);
-
- // Submit the delta.
- RequestObject<Void> editRequest = expensesRequestFactory.reportRequest().persist(report);
- ReportRecord editableReport = editRequest.edit(report);
- editableReport.setNotes(pendingNotes);
- editRequest.fire(new Receiver<Void>() {
- public void onSuccess(Void ignore, Set<SyncResult> response) {
- // We expect onReportChanged to be called if there are no errors.
- String errorMessage = getErrorMessageFromSync(response);
- if (errorMessage.length() > 0) {
- showErrorPopup(errorMessage);
- setNotesEditState(false, false, report.getNotes());
- }
- }
- });
- }
-
- /**
- * Set the state of the notes section.
- *
- * @param editable true for edit state, false for view state
- * @param pending true if changes are pending, false if not
- * @param notesText the current notes
- */
- private void setNotesEditState(
- boolean editable, boolean pending, String notesText) {
- notesBox.setText(notesText);
- notes.setInnerText(notesText);
-
- notesBox.setVisible(editable && !pending);
- setVisible(notes, !editable);
- setVisible(notesEditLinkWrapper, !editable && !pending);
- setVisible(notesPending, pending);
- notesBox.setFocus(editable);
- }
-
- /**
- * Show the error popup.
- *
- * @param errorMessage the error message
- */
- private void showErrorPopup(String errorMessage) {
- errorPopupMessage.setText(errorMessage);
- errorPopup.center();
- }
-
- private void sortExpenses(
- List<ExpenseRecord> list, final Comparator<ExpenseRecord> comparator) {
- lastComparator = comparator;
- Collections.sort(list, comparator);
- }
-
- /**
- * Update the state of a pending approval change.
- *
- * @param record the {@link ExpenseRecord} to sync
- * @param message the error message if rejected, or null if accepted
- */
- private void syncCommit(ExpenseRecord record, String message) {
- final Object key = items.getKey(record);
- if (message != null) {
- final ApprovalViewData avd = approvalCell.getViewData(key);
- if (avd != null) {
- avd.reject(message);
- }
- }
-
- // Redraw the table so the changes are applied.
- table.redraw();
- }
-
- private void updateExpenseRecord(
- final ExpenseRecord record, String approval, String reasonDenied) {
- // Verify that the total is under the cap.
- if (Expenses.Approval.APPROVED.is(approval)
- && !Expenses.Approval.APPROVED.is(record.getApproval())) {
- double amount = record.getAmount();
- if (amount + totalApproved > MAX_COST) {
- syncCommit(record,
- "The total approved amount for an expense report cannot exceed $"
- + MAX_COST + ".");
- return;
- }
- }
-
- // Create a delta and sync with the value store.
- RequestObject<Void> editRequest = expensesRequestFactory.expenseRequest().persist(record);
- ExpenseRecord editableRecord = editRequest.edit(record);
- editableRecord.setApproval(approval);
- editableRecord.setReasonDenied(reasonDenied);
- editRequest.fire(new Receiver<Void>() {
- public void onSuccess(Void ignore, Set<SyncResult> response) {
- String errorMessage = getErrorMessageFromSync(response);
- if (errorMessage.length() > 0) {
- syncCommit(record, errorMessage.length() > 0 ? errorMessage : null);
- }
- }
- });
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.ui.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.ui.xml
deleted file mode 100644
index 25791ae..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.ui.xml
+++ /dev/null
@@ -1,269 +0,0 @@
-<!DOCTYPE ui:UiBinder SYSTEM 'http://dl.google.com/gwt/DTD/xhtml.ent'>
-<ui:UiBinder
- xmlns:ui='urn:ui:com.google.gwt.uibinder'
- xmlns:m='urn:import:com.google.gwt.mobile.client'
- xmlns:g='urn:import:com.google.gwt.user.client.ui'
- xmlns:c='urn:import:com.google.gwt.user.cellview.client'>
-
- <ui:style
- field='desktop'
- src='desktop.css' />
-
- <ui:image
- field='cornerTopRight' />
- <ui:image
- field='cornerTopLeft' />
- <ui:image
- field='cornerBottomRight' />
- <ui:image
- field='cornerBottomLeft' />
- <ui:image
- field='leftArrow' />
- <ui:image
- field='pendingNotes' />
-
- <ui:style>
- .details {
- width: 100%;
- margin-top: 25px;
- }
-
- @sprite .leftArrow {
- gwt-image: 'leftArrow';
- }
-
- .link {
- text-decoration: underline;
- color: black;
- cursor: hand;
- cursor: pointer;
- }
-
- .link:hover {
- text-decoration: underline;
- color: black;
- cursor: hand;
- cursor: pointer;
- }
-
- .reportLink {
- margin-left: 5px;
- }
-
- .label {
- width: 150px;
- padding: 3px 0px 3px 9px;
- }
-
- .amount {
- width: 100px;
- padding: 3px 9px 3px 0px;
- }
-
- .dotted {
- border-bottom: 1px dotted black;
- }
-
- .notesColumn {
- width: 350px;
- padding-right: 20px;
- }
-
- .notesTextBox {
- width: 300px;
- border: 1px solid #d7dde8;
- padding: 3px;
- }
-
- .notesEditLink {
- font-weight: bold;
- }
-
- @sprite .pendingNotes {
- gwt-image: 'pendingNotes';
- margin-left: 10px;
- }
- </ui:style>
-
- <g:DockLayoutPanel
- unit='PX'>
- <g:north
- size='180'>
- <g:HTMLPanel
- styleName='{desktop.breadcrumbBar}'>
- <table
- align='center'
- width='100%'
- cellspacing='0'
- cellpadding='0'>
- <!-- Top of 9 box. -->
- <tr>
- <td
- class='{desktop.breadcrumbCorner}'>
- <div
- class='{desktop.breadcrumbCornerTopLeft}' />
- </td>
- <td
- class='{desktop.breadcrumbBorder}'>
- <div
- class='{desktop.breadcrumbBorderInner}' />
- </td>
- <td
- class='{desktop.breadcrumbCorner}'>
- <div
- class='{desktop.breadcrumbCornerTopRight}' />
- </td>
- </tr>
- <tr>
- <!-- Left of 9 box. -->
- <td
- class='{desktop.breadcrumbBorder}'>
- <div
- class='{desktop.breadcrumbBorderInner}' />
- </td>
- <!-- Breadcrumb. -->
- <td
- class='{desktop.breadcrumb} {desktop.breadcrumbBorder}'
- ui:field='reportName'>
- </td>
- <!-- Right of 9 box. -->
- <td
- class='{desktop.breadcrumbBorder}'>
- <div
- class='{desktop.breadcrumbBorderInner}' />
- </td>
- </tr>
- <!-- Bottom of 9 box. -->
- <tr>
- <td
- class='{desktop.breadcrumbCorner}'>
- <div
- class='{desktop.breadcrumbCornerBottomLeft}' />
- </td>
- <td
- class='{desktop.breadcrumbBorder}'>
- <div
- class='{desktop.breadcrumbBorderInner}' />
- </td>
- <td
- class='{desktop.breadcrumbCorner}'>
- <div
- class='{desktop.breadcrumbCornerBottomRight}' />
- </td>
- </tr>
-
- <!-- Link back to report list. -->
- <tr>
- <td
- colspan='3'
- style='padding-top:6px;'>
- <table
- cellpadding='0'
- cellspacing='0'>
- <tr>
- <td>
- <div
- class='{style.leftArrow}' />
- </td>
- <td>
- <g:Anchor
- styleName='{style.reportLink} {style.link}'
- ui:field='reportsLink' />
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </table>
-
- <!-- Details about the Report. -->
- <table
- class='{style.details}'
- cellpadding='0'
- cellspacing='0'>
- <tr>
- <td
- class='{style.label}'>
- Cost:
- </td>
- <td
- align='right'
- class='{style.amount}'
- ui:field='costLabel'>
- </td>
- <td
- rowspan='3'>
-
- </td>
- <td
- class='{style.notesColumn}'>
- <table
- cellspacing='0'
- cellpadding='0'>
- <tr>
- <td>
- Notes:
- </td>
- <td>
- <div
- class='{style.pendingNotes}'
- ui:field='notesPending' />
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
- <td
- class='{style.label} {style.dotted}'>
- Approved:
- </td>
- <td
- align='right'
- class='{style.amount} {style.dotted}'
- ui:field='approvedLabel'>
- </td>
- <td
- rowspan='2'
- class='{style.notesColumn}'
- valign='top'>
- <g:TextBox
- styleName='{style.notesTextBox}'
- ui:field='notesBox' />
- <span
- ui:field='notes' />
- <span
- ui:field='notesEditLinkWrapper'>
- (<g:Anchor
- styleName='{style.link} {style.notesEditLink}'
- ui:field='notesEditLink'>edit</g:Anchor>)
- </span>
- </td>
- </tr>
- <tr>
- <td
- class='{style.label}'>
- <b>Un-reconciled:</b>
- </td>
- <td
- align='right'
- class='{style.amount}'
- style='font-weight:bold'
- ui:field='unreconciledLabel'>
- </td>
- </tr>
- </table>
- </g:HTMLPanel>
- </g:north>
-
- <g:center>
- <m:MobileScrollPanel>
- <c:CellTable
- addStyleNames='{desktop.table}'
- width='100%'
- ui:field='table' />
- </m:MobileScrollPanel>
- </g:center>
- </g:DockLayoutPanel>
-
-</ui:UiBinder>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetailsCellTable.css b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetailsCellTable.css
deleted file mode 100644
index 8977833..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetailsCellTable.css
+++ /dev/null
@@ -1,80 +0,0 @@
-.cellTable {
-
-}
-
-.footer {
- border-top: 2px solid #6f7277;
- padding: 3px 9px;
- text-align: left;
- color: #4b4a4a;
- text-shadow: #ddf 1px 1px 0;
-}
-
-.header {
- border-bottom: 2px solid #6f7277;
- padding: 3px 9px;
- text-align: left;
- color: #4b4a4a;
- text-shadow: #ddf 1px 1px 0;
-}
-
-.cell {
- padding: 4px 9px;
-}
-
-.firstColumn {
- padding: 0px;
-}
-
-.lastColumn {
- padding: 0px;
-}
-
-.firstColumnFooter {
- border: 0px;
- padding: 0px;
-}
-
-.firstColumnHeader {
- border: 0px;
- padding: 0px;
-}
-
-.lastColumnFooter {
- border: 0px;
- padding: 0px;
-}
-
-.lastColumnHeader {
- border: 0px;
- padding: 0px;
-}
-
-.evenRow {
- background-color: #ffffff;
-}
-
-.oddRow {
- background-color: #f3f7fb;
-}
-
-.hoveredRow {
-
-}
-
-.keyboardSelectedRow {
-
-}
-
-.keyboardSelectedCell {
-
-}
-
-.selectedRow {
-
-}
-
-@sprite .loading {
- gwt-image: 'cellTableLoading';
- margin: 30px;
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseList.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseList.java
deleted file mode 100644
index 6e04d38..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseList.java
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.cell.client.AbstractCell;
-import com.google.gwt.cell.client.Cell;
-import com.google.gwt.cell.client.DateCell;
-import com.google.gwt.cell.client.TextCell;
-import com.google.gwt.cell.client.ValueUpdater;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.regexp.shared.RegExp;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.sample.bikeshed.style.client.Styles;
-import com.google.gwt.sample.expenses.gwt.request.EmployeeRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecord;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecordChanged;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiFactory;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.cellview.client.CellTable;
-import com.google.gwt.user.cellview.client.Column;
-import com.google.gwt.user.cellview.client.SimplePager;
-import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.valuestore.shared.Property;
-import com.google.gwt.valuestore.shared.SyncResult;
-import com.google.gwt.view.client.AsyncDataProvider;
-import com.google.gwt.view.client.HasData;
-import com.google.gwt.view.client.NoSelectionModel;
-import com.google.gwt.view.client.Range;
-import com.google.gwt.view.client.SelectionChangeEvent;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * The list of expense reports on the right side of the app.
- */
-public class ExpenseList extends Composite
- implements ReportRecordChanged.Handler {
-
- /**
- * The auto refresh interval in milliseconds.
- */
- private static final int REFRESH_INTERVAL = 5000;
-
- private static ExpenseListUiBinder uiBinder = GWT.create(
- ExpenseListUiBinder.class);
-
- /**
- * Utility method to get the first part of the breadcrumb based on the
- * department and employee.
- *
- * @param department the selected department
- * @param employee the selected employee
- * @return the breadcrumb
- */
- public static String getBreadcrumb(
- String department, EmployeeRecord employee) {
- if (employee != null) {
- return "Reports for " + employee.getDisplayName();
- } else if (department != null) {
- return "Reports for " + department;
- } else {
- return "All Reports";
- }
- }
-
- /**
- * A text box that displays default text.
- */
- private static class DefaultTextBox extends TextBox {
-
- /**
- * The text color used when the box is disabled and empty.
- */
- private static final String TEXTBOX_DISABLED_COLOR = "#aaaaaa";
-
- private final String defaultText;
-
- public DefaultTextBox(final String defaultText) {
- this.defaultText = defaultText;
- resetDefaultText();
-
- // Add focus and blur handlers.
- addFocusHandler(new FocusHandler() {
- public void onFocus(FocusEvent event) {
- getElement().getStyle().clearColor();
- if (defaultText.equals(getText())) {
- setText("");
- }
- }
- });
- addBlurHandler(new BlurHandler() {
- public void onBlur(BlurEvent event) {
- if ("".equals(getText())) {
- resetDefaultText();
- }
- }
- });
- }
-
- public String getDefaultText() {
- return defaultText;
- }
-
- /**
- * Reset the text box to the default text.
- */
- public void resetDefaultText() {
- setText(defaultText);
- getElement().getStyle().setColor(TEXTBOX_DISABLED_COLOR);
- }
- }
-
- interface ExpenseListUiBinder extends UiBinder<Widget, ExpenseList> {
- }
- /**
- * Custom listener for this widget.
- */
- interface Listener {
-
- /**
- * Called when the user selects a report.
- *
- * @param report the selected report
- */
- void onReportSelected(ReportRecord report);
- }
-
- /**
- * The styles applied to the table.
- */
- interface TableStyle extends CellTable.CleanStyle {
- String evenRow();
-
- String hoveredRow();
-
- String oddRow();
-
- String selectedRow();
- }
-
- /**
- * The resources applied to the table.
- */
- interface TableResources extends CellTable.CleanResources {
- @Source("ExpenseListCellTable.css")
- TableStyle cellTableStyle();
- }
-
- /**
- * A cell used to highlight search text.
- */
- private class HighlightCell extends AbstractCell<String> {
-
- private static final String replaceString =
- "<span style='color:red;font-weight:bold;'>$1</span>";
-
- @Override
- public void render(String value, Object viewData, StringBuilder sb) {
- if (value != null) {
- if (searchRegExp != null) {
- value = searchRegExp.replace(value, replaceString);
- }
- sb.append(value);
- }
- }
- }
-
- /**
- * The data provider used to retrieve reports.
- */
- private class ReportDataProvider extends AsyncDataProvider<ReportRecord> {
- @Override
- protected void onRangeChanged(HasData<ReportRecord> display) {
- requestReports(false);
- }
- }
-
- @UiField
- Element breadcrumb;
- @UiField
- SimplePager pager;
- @UiField(provided = true)
- DefaultTextBox searchBox;
- @UiField
- Image searchButton;
-
- /**
- * The main table. We provide this in the constructor before calling
- * {@link UiBinder#createAndBindUi(Object)} because the pager depends on it.
- */
- @UiField(provided = true)
- CellTable<ReportRecord> table;
-
- private List<SortableHeader> allHeaders = new ArrayList<SortableHeader>();
-
- /**
- * The department being searched.
- */
- private String department;
-
- /**
- * The employee being searched.
- */
- private EmployeeRecord employee;
-
- /**
- * Indicates that the report count is stale.
- */
- private boolean isCountStale = true;
-
- /**
- * The field to sort by.
- */
- private String orderBy = ReportRecord.purpose.getName();
-
- /**
- * The set of Report keys that we have seen. When a new key is added, we
- * compare it to the list of known keys to determine if it is new.
- */
- private Set<Object> knownReportKeys = null;
-
- /**
- * Keep track of the last receiver so that we know if a response is stale.
- */
- private Receiver<List<ReportRecord>> lastDataReceiver;
-
- /**
- * Keep track of the last receiver so that we know if a response is stale.
- */
- private Receiver<Long> lastDataSizeReceiver;
-
- private Listener listener;
-
- /**
- * The {@link Timer} used to periodically refresh the table.
- */
- private final Timer refreshTimer = new Timer() {
- @Override
- public void run() {
- isCountStale = true;
- requestReports(true);
- }
- };
-
- /**
- * The columns to request with each report.
- */
- private final List<Property<?>> reportColumns;
-
- /**
- * The data provider that provides reports.
- */
- private final ReportDataProvider reports = new ReportDataProvider();
-
- /**
- * The factory used to send requests.
- */
- private ExpensesRequestFactory requestFactory;
-
- /**
- * The string that the user searched for.
- */
- private RegExp searchRegExp;
-
- /**
- * The starts with search string.
- */
- private String startsWithSearch;
-
- public ExpenseList() {
- reports.setKeyProvider(Expenses.REPORT_RECORD_KEY_PROVIDER);
- reportColumns = new ArrayList<Property<?>>();
- reportColumns.add(ReportRecord.created);
- reportColumns.add(ReportRecord.purpose);
- reportColumns.add(ReportRecord.notes);
-
- // Initialize the widget.
- createTable();
- searchBox = new DefaultTextBox("search");
- initWidget(uiBinder.createAndBindUi(this));
-
- // Add the view to the data provider.
- reports.addDataDisplay(table);
-
- // Listen for key events from the text boxes.
- searchBox.addKeyUpHandler(new KeyUpHandler() {
- public void onKeyUp(KeyUpEvent event) {
- // Search on enter.
- if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
- search();
- return;
- }
-
- // Highlight as the user types.
- String text = searchBox.getText();
- if (text.length() > 0) {
- searchRegExp = RegExp.compile("(" + text + ")", "ig");
- } else {
- searchRegExp = null;
- }
- table.redraw();
- }
- });
- searchButton.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent event) {
- search();
- }
- });
- }
-
- public void onReportChanged(ReportRecordChanged event) {
- ReportRecord changed = event.getRecord();
- Long changedId = changed.getId();
- List<ReportRecord> records = table.getDisplayedItems();
- int i = 0;
- for (ReportRecord record : records) {
- if (record != null && changedId.equals(record.getId())) {
- List<ReportRecord> changedList = new ArrayList<ReportRecord>();
- changedList.add(changed);
- reports.updateRowData(i + table.getPageStart(), changedList);
- }
- i++;
- }
- }
-
- /**
- * Set the current department and employee to filter on.
- *
- * @param department the department, or null if none selected
- * @param employee the employee, or null if none selected
- */
- public void setEmployee(String department, EmployeeRecord employee) {
- this.department = department;
- this.employee = employee;
- isCountStale = true;
- searchBox.resetDefaultText();
- startsWithSearch = null;
- breadcrumb.setInnerText(getBreadcrumb(department, employee));
- searchRegExp = null;
-
- // Refresh the table.
- pager.setPageStart(0);
- requestReports(false);
- }
-
- public void setListener(Listener listener) {
- this.listener = listener;
- }
-
- public void setRequestFactory(ExpensesRequestFactory factory) {
- this.requestFactory = factory;
- requestReports(false);
- }
-
- @UiFactory
- SimplePager createPager() {
- SimplePager p = new SimplePager(TextLocation.RIGHT);
- p.setDisplay(table);
- p.setRangeLimited(true);
- return p;
- }
-
- /**
- * Add a sortable column to the table.
- *
- * @param <C> the data type for the column
- * @param text the header text
- * @param cell the cell used to render the column
- * @param getter the getter to retrieve the value for the column
- * @param property the property to sort by
- * @return the column
- */
- private <C> Column<ReportRecord, C> addColumn(final String text,
- final Cell<C> cell, final GetValue<ReportRecord, C> getter,
- final Property<?> property) {
- final Column<ReportRecord, C> column = new Column<ReportRecord, C>(cell) {
- @Override
- public C getValue(ReportRecord object) {
- return getter.getValue(object);
- }
- };
- final SortableHeader header = new SortableHeader(text);
- allHeaders.add(header);
-
- // Sort created by default.
- if (property == ReportRecord.created) {
- header.setSorted(true);
- header.setReverseSort(true);
- orderBy = property.getName() + " DESC";
- }
-
- header.setUpdater(new ValueUpdater<String>() {
- public void update(String value) {
- header.setSorted(true);
- header.toggleReverseSort();
-
- for (SortableHeader otherHeader : allHeaders) {
- if (otherHeader != header) {
- otherHeader.setSorted(false);
- otherHeader.setReverseSort(true);
- }
- }
- table.redrawHeaders();
-
- // Request sorted rows.
- orderBy = property.getName();
- if (header.getReverseSort()) {
- orderBy += " DESC";
- }
- searchBox.resetDefaultText();
- searchRegExp = null;
-
- // Go to the first page of the newly-sorted results
- pager.firstPage();
- requestReports(false);
- }
- });
- table.addColumn(column, header);
- return column;
- }
-
- /**
- * Create the {@link CellTable}.
- */
- private void createTable() {
- CellTable.Resources resources = GWT.create(TableResources.class);
- table = new CellTable<ReportRecord>(20, resources);
- Styles.Common common = Styles.common();
- table.addColumnStyleName(0, common.spacerColumn());
- table.addColumnStyleName(1, common.expenseListPurposeColumn());
- table.addColumnStyleName(3, common.expenseListDepartmentColumn());
- table.addColumnStyleName(4, common.expenseListCreatedColumn());
- table.addColumnStyleName(5, common.spacerColumn());
-
- // Add a selection model.
- final NoSelectionModel<ReportRecord> selectionModel = new NoSelectionModel<
- ReportRecord>();
- table.setSelectionModel(selectionModel);
- selectionModel.addSelectionChangeHandler(
- new SelectionChangeEvent.Handler() {
- public void onSelectionChange(SelectionChangeEvent event) {
- Object selected = selectionModel.getLastSelectedObject();
- if (selected != null && listener != null) {
- listener.onReportSelected((ReportRecord) selected);
- }
- }
- });
-
- // Spacer column.
- table.addColumn(new Column<ReportRecord, String>(new TextCell()) {
- @Override
- public String getValue(ReportRecord object) {
- return "<div style='display:none;'/>";
- }
- });
-
- // Purpose column.
- addColumn(
- "Purpose", new HighlightCell(), new GetValue<ReportRecord, String>() {
- public String getValue(ReportRecord object) {
- return object.getPurpose();
- }
- }, ReportRecord.purpose);
-
- // Notes column.
- addColumn(
- "Notes", new HighlightCell(), new GetValue<ReportRecord, String>() {
- public String getValue(ReportRecord object) {
- return object.getNotes();
- }
- }, ReportRecord.notes);
-
- // Department column.
- addColumn(
- "Department", new TextCell(), new GetValue<ReportRecord, String>() {
- public String getValue(ReportRecord object) {
- return object.getDepartment();
- }
- }, ReportRecord.department);
-
- // Created column.
- addColumn("Created", new DateCell(DateTimeFormat.getFormat("MMM dd yyyy")),
- new GetValue<ReportRecord, Date>() {
- public Date getValue(ReportRecord object) {
- return object.getCreated();
- }
- }, ReportRecord.created);
-
- // Spacer column.
- table.addColumn(new Column<ReportRecord, String>(new TextCell()) {
- @Override
- public String getValue(ReportRecord object) {
- return "<div style='display:none;'/>";
- }
- });
- }
-
- /**
- * Send a request for reports in the current range.
- *
- * @param isPolling true if this request is caused by polling
- */
- private void requestReports(boolean isPolling) {
- // Cancel the refresh timer.
- refreshTimer.cancel();
-
- // Early exit if we don't have a request factory to request from.
- if (requestFactory == null) {
- return;
- }
-
- // Clear the known keys.
- if (!isPolling) {
- knownReportKeys = null;
- }
-
- // Get the parameters.
- String startsWith = startsWithSearch;
- if (startsWith == null || searchBox.getDefaultText().equals(startsWith)) {
- startsWith = "";
- }
- Range range = table.getVisibleRange();
- Long employeeId = employee == null ? -1 : new Long(employee.getId());
- String dept = department == null ? "" : department;
-
- // If a search string is specified, the results will not be sorted.
- if (startsWith.length() > 0) {
- for (SortableHeader header : allHeaders) {
- header.setSorted(false);
- header.setReverseSort(false);
- }
- table.redrawHeaders();
- }
-
- // Request the total data size.
- if (isCountStale) {
- isCountStale = false;
- if (!isPolling) {
- pager.startLoading();
- }
- lastDataSizeReceiver = new Receiver<Long>() {
- public void onSuccess(Long response, Set<SyncResult> syncResults) {
- if (this == lastDataSizeReceiver) {
- int count = response.intValue();
- // Treat count == 1000 as inexact due to AppEngine limitation
- reports.updateRowCount(count, count != 1000);
- }
- }
- };
- requestFactory.reportRequest().countReportsBySearch(
- employeeId, dept, startsWith).fire(lastDataSizeReceiver);
- }
-
- // Request reports in the current range.
- lastDataReceiver = new Receiver<List<ReportRecord>>() {
- public void onSuccess(
- List<ReportRecord> newValues, Set<SyncResult> syncResults) {
- if (this == lastDataReceiver) {
- int size = newValues.size();
- if (size < table.getPageSize()) {
- // Now we know the exact data size
- reports.updateRowCount(table.getPageStart() + size, true);
- }
- if (size > 0) {
- reports.updateRowData(table.getPageStart(), newValues);
- }
-
- // Add the new keys to the known keys.
- boolean isInitialData = knownReportKeys == null;
- if (knownReportKeys == null) {
- knownReportKeys = new HashSet<Object>();
- }
- for (ReportRecord value : newValues) {
- Object key = reports.getKey(value);
- if (!isInitialData && !knownReportKeys.contains(key)) {
- (new PhaseAnimation.CellTablePhaseAnimation<ReportRecord>(
- table, value, reports)).run();
- }
- knownReportKeys.add(key);
- }
- }
- refreshTimer.schedule(REFRESH_INTERVAL);
- }
- };
-
- requestFactory.reportRequest().findReportEntriesBySearch(employeeId, dept,
- startsWith, orderBy, range.getStart(), range.getLength()).forProperties(
- reportColumns).fire(lastDataReceiver);
- }
-
- /**
- * Search based on the search box text.
- */
- private void search() {
- isCountStale = true;
- startsWithSearch = searchBox.getText();
- requestReports(false);
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseList.ui.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseList.ui.xml
deleted file mode 100644
index 8d3f6b5..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseList.ui.xml
+++ /dev/null
@@ -1,191 +0,0 @@
-<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
-<ui:UiBinder
- xmlns:ui="urn:ui:com.google.gwt.uibinder"
- xmlns:g="urn:import:com.google.gwt.user.client.ui"
- xmlns:m='urn:import:com.google.gwt.mobile.client'
- xmlns:c='urn:import:com.google.gwt.user.cellview.client'>
-
- <ui:with
- field='styles'
- type='com.google.gwt.sample.bikeshed.style.client.Styles.Resources' />
- <ui:style field='desktop' src='desktop.css' />
-
- <ui:image
- field='searchCenter'
- src='../../../bikeshed/style/client/searchCenter.png'
- repeatStyle="Horizontal" />
- <ui:image
- field='searchLeft'
- src='../../../bikeshed/style/client/searchLeft.png' />
-
- <ui:image
- field='cornerTopRight' />
- <ui:image
- field='cornerTopLeft' />
- <ui:image
- field='cornerBottomRight' />
- <ui:image
- field='cornerBottomLeft' />
-
- <ui:style>
- .textBox {
- width: 250px;
- border: 0px;
- padding: 4px 0px 2px;
- height: 16px;
- font-size: 12px;
- outline-width: 0px;
- background: transparent;
- }
-
- .searchButton {
- cursor: pointer;
- cursor: hand;
- }
-
- @sprite .searchCenter {
- gwt-image: 'searchCenter';
- padding-top: 1px;
- }
-
- @sprite .searchLeft {
- gwt-image: 'searchLeft';
- }
-
- .center {
- border-bottom: 1px solid #d7dde8;
- }
- </ui:style>
-
- <g:DockLayoutPanel
- unit='PX'>
-
- <g:north
- size='70'>
- <g:HTMLPanel
- styleName='{desktop.breadcrumbBar}'>
- <table
- align='center'
- width='100%'
- cellspacing='0'
- cellpadding='0'>
- <!-- Top of 9 box. -->
- <tr>
- <td
- class='{desktop.breadcrumbCorner}'>
- <div
- class='{desktop.breadcrumbCornerTopLeft}' />
- </td>
- <td
- colspan='2'
- class='{desktop.breadcrumbBorder}'>
- <div
- class='{desktop.breadcrumbBorderInner}' />
- </td>
- <td
- class='{desktop.breadcrumbCorner}'>
- <div
- class='{desktop.breadcrumbCornerTopRight}' />
- </td>
- </tr>
- <tr>
- <!-- Left of 9 box. -->
- <td
- class='{desktop.breadcrumbBorder}'>
- <div
- class='{desktop.breadcrumbBorderInner}' />
- </td>
- <!-- Breadcrumb. -->
- <td
- class='{desktop.breadcrumb} {desktop.breadcrumbBorder}'
- align='left'
- ui:field='breadcrumb'>
- All Reports
- </td>
- <!-- Search Box. -->
- <td
- class='{desktop.breadcrumbBorder}'
- align='right'
- valign='middle'>
- <table
- cellspacing='0'
- cellpadding='0'>
- <tr>
- <td
- valign='top'>
- <div
- class='{style.searchLeft}' />
- </td>
- <td
- valign='top'
- class='{style.searchCenter}'>
- <g:TextBox
- styleName='{style.textBox}'
- ui:field='searchBox' />
- </td>
- <td
- valign='top'>
- <g:Image
- addStyleNames='{style.searchButton}'
- ui:field='searchButton'
- resource='{styles.searchRight}' />
- </td>
- <td>
- <div
- style='width:50px;' />
- </td>
- </tr>
- </table>
- </td>
- <!-- Right of 9 box. -->
- <td
- class='{desktop.breadcrumbBorder}'>
- <div
- class='{desktop.breadcrumbBorderInner}' />
- </td>
- </tr>
- <!-- Bottom of 9 box. -->
- <tr>
- <td
- class='{desktop.breadcrumbCorner}'>
- <div
- class='{desktop.breadcrumbCornerBottomLeft}' />
- </td>
- <td
- colspan='2'
- class='{desktop.breadcrumbBorder}'>
- <div
- class='{desktop.breadcrumbBorderInner}' />
- </td>
- <td
- class='{desktop.breadcrumbCorner}'>
- <div
- class='{desktop.breadcrumbCornerBottomRight}' />
- </td>
- </tr>
- </table>
- </g:HTMLPanel>
- </g:north>
-
- <g:center>
- <m:MobileScrollPanel
- styleName='{style.center}'>
- <c:CellTable
- addStyleNames='{desktop.table}'
- width='100%'
- ui:field='table' />
- </m:MobileScrollPanel>
- </g:center>
-
- <g:south
- size='30'>
- <g:HTMLPanel>
- <div
- style='position:absolute;right:30px;'>
- <c:SimplePager
- ui:field='pager' />
- </div>
- </g:HTMLPanel>
- </g:south>
- </g:DockLayoutPanel>
-</ui:UiBinder>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseListCellTable.css b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseListCellTable.css
deleted file mode 100644
index 85fdabd..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseListCellTable.css
+++ /dev/null
@@ -1,87 +0,0 @@
-.cellTable {
-
-}
-
-.footer {
- border-top: 2px solid #6f7277;
- padding: 3px 9px;
- text-align: left;
- color: #4b4a4a;
- text-shadow: #ddf 1px 1px 0;
-}
-
-.header {
- border-bottom: 2px solid #6f7277;
- padding: 3px 9px;
- text-align: left;
- color: #4b4a4a;
- text-shadow: #ddf 1px 1px 0;
-}
-
-.cell {
- padding: 4px 9px;
-}
-
-.firstColumn {
- padding: 0px;
-}
-
-.lastColumn {
- padding: 0px;
-}
-
-.firstColumnFooter {
- border: 0px;
- padding: 0px;
-}
-
-.firstColumnHeader {
- border: 0px;
- padding: 0px;
-}
-
-.lastColumnFooter {
- border: 0px;
- padding: 0px;
-}
-
-.lastColumnHeader {
- border: 0px;
- padding: 0px;
-}
-
-.evenRow {
- background-color: #ffffff;
- cursor: hand;
- cursor: pointer;
-}
-
-.oddRow {
- background-color: #f3f7fb;
- cursor: hand;
- cursor: pointer;
-}
-
-@sprite .hoveredRow {
- gwt-image: 'cellTableSelectedBackground';
- background-color: #628cd5;
- color: white;
- height: auto;
- overflow: auto;
-}
-
-.keyboardSelectedRow {
-
-}
-
-.keyboardSelectedCell {
-
-}
-
-.selectedRow {
-}
-
-@sprite .loading {
- gwt-image: 'cellTableLoading';
- margin: 30px;
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseTree.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseTree.java
deleted file mode 100644
index 4b83c8e..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseTree.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.cell.client.AbstractCell;
-import com.google.gwt.cell.client.Cell;
-import com.google.gwt.cell.client.IconCellDecorator;
-import com.google.gwt.cell.client.TextCell;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Style.Overflow;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.sample.bikeshed.style.client.Styles;
-import com.google.gwt.sample.expenses.gwt.request.EmployeeRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.user.cellview.client.CellTree;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.valuestore.shared.Property;
-import com.google.gwt.valuestore.shared.SyncResult;
-import com.google.gwt.view.client.AsyncDataProvider;
-import com.google.gwt.view.client.HasData;
-import com.google.gwt.view.client.ListDataProvider;
-import com.google.gwt.view.client.ProvidesKey;
-import com.google.gwt.view.client.Range;
-import com.google.gwt.view.client.SelectionChangeEvent;
-import com.google.gwt.view.client.SingleSelectionModel;
-import com.google.gwt.view.client.TreeViewModel;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-/**
- * The employee tree located on the left of the app.
- */
-public class ExpenseTree extends Composite {
-
- /**
- * Custom listener for this widget.
- */
- public interface Listener {
-
- /**
- * Called when the user selects a tree item.
- *
- * @param department the selected department name
- * @param employee the selected employee
- */
- void onSelection(String department, EmployeeRecord employee);
- }
-
- /**
- * A {@link AbstractCell} that represents an {@link EmployeeRecord}.
- */
- private class EmployeeCell extends IconCellDecorator<EmployeeRecord> {
-
- public EmployeeCell() {
- super(Styles.resources().userIcon(), new AbstractCell<EmployeeRecord>() {
-
- private final String usernameStyle = Styles.common().usernameTreeItem();
- private final String usernameStyleSelected =
- Styles.common().usernameTreeItemSelected();
-
- @Override
- public boolean dependsOnSelection() {
- return true;
- }
-
- @Override
- public void render(
- EmployeeRecord value, Object viewData, StringBuilder sb) {
- if (value != null) {
- sb.append(value.getDisplayName()).append("<br>");
- sb.append("<span class='").append(usernameStyle);
- if (lastEmployee != null
- && lastEmployee.getId().equals(value.getId())) {
- sb.append(" ").append(usernameStyleSelected);
- }
- sb.append("'>");
- sb.append(value.getUserName());
- sb.append("</span>");
- }
- }
- });
- }
- }
-
- /**
- * The {@link ListDataProvider} used for Employee lists.
- */
- private class EmployeeListDataProvider extends AsyncDataProvider<
- EmployeeRecord> implements Receiver<List<EmployeeRecord>> {
-
- private final String department;
-
- public EmployeeListDataProvider(String department) {
- this.department = department;
- }
-
- @Override
- public void addDataDisplay(HasData<EmployeeRecord> display) {
- super.addDataDisplay(display);
-
- // Request the count anytime a view is added.
- requestFactory.employeeRequest().countEmployeesByDepartment(
- department).fire(new Receiver<Long>() {
- public void onSuccess(Long response, Set<SyncResult> syncResults) {
- updateRowCount(response.intValue(), true);
- }
- });
- }
-
- public void onSuccess(
- List<EmployeeRecord> response, Set<SyncResult> syncResults) {
- updateRowData(0, response);
- }
-
- @Override
- protected void onRangeChanged(HasData<EmployeeRecord> view) {
- Range range = view.getVisibleRange();
- requestFactory.employeeRequest().findEmployeeEntriesByDepartment(
- department, range.getStart(), range.getLength()).forProperties(
- getEmployeeMenuProperties()).fire(this);
- }
- }
-
- /**
- * The {@link TreeViewModel} used to browse expense reports.
- */
- private class ExpensesTreeViewModel implements TreeViewModel {
-
- /**
- * The department cell singleton.
- */
- private final Cell<String> departmentCell = new TextCell();
-
- /**
- * The {@link EmployeeCell} singleton.
- */
- private final EmployeeCell employeeCell = new EmployeeCell();
-
- public <T> NodeInfo<?> getNodeInfo(T value) {
- if (value == null) {
- // Top level.
- return new DefaultNodeInfo<String>(
- departments, departmentCell, selectionModel, null);
- } else if (isAllDepartment(value)) {
- // Employees are not displayed under the 'All' Department.
- return null;
- } else if (value instanceof String) {
- // Second level.
- EmployeeListDataProvider dataProvider = new EmployeeListDataProvider(
- (String) value);
- return new DefaultNodeInfo<EmployeeRecord>(
- dataProvider, employeeCell, selectionModel, null);
- }
-
- return null;
- }
-
- /**
- * @return true if the object is the All department
- */
- public boolean isAllDepartment(Object value) {
- return departments.getList().get(0).equals(value);
- }
-
- /**
- * @return true if the object is a department
- */
- public boolean isDepartment(Object value) {
- return departments.getList().contains(value.toString());
- }
-
- public boolean isLeaf(Object value) {
- return !isDepartment(value) || isAllDepartment(value);
- }
- }
-
- /**
- * The data provider that provides departments.
- */
- private ListDataProvider<String> departments = new ListDataProvider<String>();
-
- /**
- * The last selected department.
- */
- private String lastDepartment;
-
- /**
- * The last selected employee.
- */
- private EmployeeRecord lastEmployee;
-
- /**
- * The listener of this widget.
- */
- private Listener listener;
-
- /**
- * The factory used to send requests.
- */
- private ExpensesRequestFactory requestFactory;
-
- /**
- * The shared {@link SingleSelectionModel}.
- */
- private final SingleSelectionModel<Object> selectionModel =
- new SingleSelectionModel<Object>();
-
- /**
- * The main widget.
- */
- private CellTree tree;
-
- public ExpenseTree() {
- // Initialize the departments.
- List<String> departmentList = departments.getList();
- departmentList.add("All");
- for (String department : Expenses.DEPARTMENTS) {
- departmentList.add(department);
- }
-
- // Initialize the widget.
- createTree();
- initWidget(tree);
- getElement().getStyle().setOverflow(Overflow.AUTO);
- }
-
- public void setListener(Listener listener) {
- this.listener = listener;
- }
-
- public void setRequestFactory(ExpensesRequestFactory factory) {
- this.requestFactory = factory;
- }
-
- /**
- * Create the {@link CellTree}.
- */
- private void createTree() {
- final ExpensesTreeViewModel model = new ExpensesTreeViewModel();
-
- // Listen for selection. We need to add this handler before the CellBrowser
- // adds its own handler.
- selectionModel.addSelectionChangeHandler(
- new SelectionChangeEvent.Handler() {
- public void onSelectionChange(SelectionChangeEvent event) {
- Object selected = selectionModel.getSelectedObject();
- if (selected == null) {
- lastEmployee = null;
- lastDepartment = null;
- } else if (selected instanceof EmployeeRecord) {
- lastEmployee = (EmployeeRecord) selected;
- } else if (selected instanceof String) {
- lastEmployee = null;
- if (model.isAllDepartment(selected)) {
- lastDepartment = null;
- } else {
- lastDepartment = (String) selected;
- }
- }
-
- if (listener != null) {
- listener.onSelection(lastDepartment, lastEmployee);
- }
- }
- });
- selectionModel.setKeyProvider(new ProvidesKey<Object>() {
- public Object getKey(Object item) {
- if (item instanceof EmployeeRecord) {
- return Expenses.EMPLOYEE_RECORD_KEY_PROVIDER.getKey(
- (EmployeeRecord) item);
- }
- return item;
- }
- });
-
- // Create a CellBrowser.
- CellTree.Resources resources = GWT.create(CellTree.CleanResources.class);
- tree = new CellTree(model, null, resources);
- tree.setAnimationEnabled(true);
- }
-
- private Collection<Property<?>> getEmployeeMenuProperties() {
- List<Property<?>> columns = new ArrayList<Property<?>>();
- columns.add(EmployeeRecord.displayName);
- columns.add(EmployeeRecord.userName);
- return columns;
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/Expenses.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/Expenses.java
deleted file mode 100644
index 7f3c483..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/Expenses.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.shared.HandlerManager;
-import com.google.gwt.requestfactory.client.AuthenticationFailureHandler;
-import com.google.gwt.requestfactory.client.LoginWidget;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.requestfactory.shared.RequestEvent;
-import com.google.gwt.requestfactory.shared.UserInformationRecord;
-import com.google.gwt.resources.client.ImageResource;
-import com.google.gwt.sample.bikeshed.style.client.Styles;
-import com.google.gwt.sample.expenses.gwt.request.EmployeeRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpenseRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpenseRecordChanged;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecord;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecordChanged;
-import com.google.gwt.user.client.Window.Location;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.RootLayoutPanel;
-import com.google.gwt.valuestore.shared.SyncResult;
-import com.google.gwt.view.client.ProvidesKey;
-
-import java.util.Set;
-
-/**
- * Entry point for the Expenses app.
- */
-public class Expenses implements EntryPoint {
-
- /**
- * An enum describing the approval status.
- */
- public static enum Approval {
- BLANK("", "inherit", Styles.resources().blankIcon()), APPROVED("Approved",
- "#00aa00", Styles.resources().approvedIcon()), DENIED("Denied",
- "#ff0000", Styles.resources().deniedIcon());
-
- /**
- * Get the {@link Approval} from the specified string.
- *
- * @param approval the approval string
- * @return the {@link Approval}
- */
- public static Approval from(String approval) {
- if (APPROVED.is(approval)) {
- return APPROVED;
- } else if (DENIED.is(approval)) {
- return DENIED;
- }
- return BLANK;
- }
-
- private final String color;
- private final String iconHtml;
- private final String text;
-
- private Approval(String text, String color, ImageResource res) {
- this.text = text;
- this.color = color;
- this.iconHtml = AbstractImagePrototype.create(res).getHTML();
- }
-
- public String getColor() {
- return color;
- }
-
- public String getIconHtml() {
- return iconHtml;
- }
-
- public String getText() {
- return text;
- }
-
- public boolean is(String compare) {
- return text.equals(compare);
- }
- }
-
- public static final String[] DEPARTMENTS = {
- "Engineering", "Finance", "Marketing", "Operations", "Sales"};
-
- /**
- * The key provider for {@link EmployeeRecord}s.
- */
- public static final ProvidesKey<EmployeeRecord> EMPLOYEE_RECORD_KEY_PROVIDER = new ProvidesKey<EmployeeRecord>() {
- public Object getKey(EmployeeRecord item) {
- return item == null ? null : item.getId();
- }
- };
-
- /**
- * The key provider for {@link ExpenseRecord}s.
- */
- public static final ProvidesKey<ExpenseRecord> EXPENSE_RECORD_KEY_PROVIDER = new ProvidesKey<ExpenseRecord>() {
- public Object getKey(ExpenseRecord item) {
- return item == null ? null : item.getId();
- }
- };
-
- /**
- * The key provider for {@link ReportRecord}s.
- */
- public static final ProvidesKey<ReportRecord> REPORT_RECORD_KEY_PROVIDER = new ProvidesKey<ReportRecord>() {
- public Object getKey(ReportRecord item) {
- return item == null ? null : item.getId();
- }
- };
-
- private String lastDepartment;
- private EmployeeRecord lastEmployee;
- private ExpensesRequestFactory requestFactory;
- private ExpensesShell shell;
-
- public void onModuleLoad() {
- final HandlerManager eventBus = new HandlerManager(null);
- requestFactory = GWT.create(ExpensesRequestFactory.class);
- requestFactory.init(eventBus);
-
- RootLayoutPanel root = RootLayoutPanel.get();
-
- shell = new ExpensesShell();
- final ExpenseTree expenseTree = shell.getExpenseTree();
- final ExpenseList expenseList = shell.getExpenseList();
- final ExpenseDetails expenseDetails = shell.getExpenseDetails();
-
- root.add(shell);
-
- // Check for Authentication failures or mismatches
- eventBus.addHandler(RequestEvent.TYPE, new AuthenticationFailureHandler());
-
- // Add a login widget to the page
- final LoginWidget login = shell.getLoginWidget();
- Receiver<UserInformationRecord> receiver = new Receiver<UserInformationRecord>() {
- public void onSuccess(UserInformationRecord userInformationRecord, Set<SyncResult> syncResults) {
- login.setUserInformation(userInformationRecord);
- }
- };
- requestFactory.userInformationRequest().getCurrentUserInformation(
- Location.getHref()).fire(receiver);
-
- // Listen for requests from ExpenseTree.
- expenseTree.setListener(new ExpenseTree.Listener() {
- public void onSelection(String department, EmployeeRecord employee) {
- lastDepartment = department;
- lastEmployee = employee;
- expenseList.setEmployee(department, employee);
- shell.showExpenseDetails(false);
- }
- });
- expenseTree.setRequestFactory(requestFactory);
-
- // Listen for requests from the ExpenseList.
- expenseList.setListener(new ExpenseList.Listener() {
- public void onReportSelected(ReportRecord report) {
- expenseDetails.setExpensesRequestFactory(requestFactory);
- expenseDetails.setReportRecord(report, lastDepartment, lastEmployee);
- shell.showExpenseDetails(true);
- }
- });
- expenseList.setRequestFactory(requestFactory);
- eventBus.addHandler(ReportRecordChanged.TYPE, expenseList);
-
- // Forward change events to the expense details.
- eventBus.addHandler(ExpenseRecordChanged.TYPE, expenseDetails);
- eventBus.addHandler(ReportRecordChanged.TYPE, expenseDetails);
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesMobile.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesMobile.java
deleted file mode 100644
index 486f6f2..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesMobile.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.event.shared.HandlerManager;
-import com.google.gwt.requestfactory.client.AuthenticationFailureHandler;
-import com.google.gwt.requestfactory.client.LoginWidget;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.requestfactory.shared.RequestEvent;
-import com.google.gwt.requestfactory.shared.UserInformationRecord;
-import com.google.gwt.sample.expenses.gwt.request.EmployeeRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.Window.Location;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.valuestore.shared.SyncResult;
-import com.google.gwt.valuestore.shared.Value;
-
-import java.util.Set;
-
-/**
- * Entry point for the mobile version of the Expenses app.
- */
-public class ExpensesMobile implements EntryPoint {
-
- /**
- * The url parameter that specifies the employee id.
- */
- private static final String EMPLOYEE_ID_PARAM = "employeeId";
-
- /**
- * TODO(jgw): Put this some place more sensible.
- *
- * @param amount the amount in dollars
- */
- public static String formatCurrency(double amount) {
- StringBuilder sb = new StringBuilder();
-
- int price = (int) (amount * 100);
- boolean negative = price < 0;
- if (negative) {
- price = -price;
- }
- int dollars = price / 100;
- int cents = price % 100;
-
- if (negative) {
- sb.append("-");
- }
-
- sb.append(dollars);
- sb.append('.');
- if (cents < 10) {
- sb.append('0');
- }
- sb.append(cents);
-
- return sb.toString();
- }
-
- /**
- * This is the entry point method.
- */
- public void onModuleLoad() {
- // Get the employee ID from the URL.
- long employeeId = 1;
- try {
- String value = Window.Location.getParameter(EMPLOYEE_ID_PARAM);
- if (value != null && value.length() > 0) {
- employeeId = Long.parseLong(value);
- }
- } catch (NumberFormatException e) {
- RootPanel.get().add(new Label("employeeId is invalid"));
- return;
- }
-
- final HandlerManager eventBus = new HandlerManager(null);
- final ExpensesRequestFactory requestFactory = GWT.create(
- ExpensesRequestFactory.class);
- requestFactory.init(eventBus);
-
- requestFactory.employeeRequest().findEmployee(Value.of(employeeId)).fire(
- new Receiver<EmployeeRecord>() {
- public void onSuccess(EmployeeRecord employee,
- Set<SyncResult> syncResults) {
- final ExpensesMobileShell shell = new ExpensesMobileShell(eventBus,
- requestFactory, employee);
- RootPanel.get().add(shell);
-
- // Check for Authentication failures or mismatches
- eventBus.addHandler(RequestEvent.TYPE,
- new AuthenticationFailureHandler());
-
- // Add a login widget to the page
- final LoginWidget login = shell.getLoginWidget();
- Receiver<UserInformationRecord> receiver
- = new Receiver<UserInformationRecord>() {
- public void onSuccess(UserInformationRecord userInformationRecord,
- Set<SyncResult> syncResults) {
- login.setUserInformation(userInformationRecord);
- }
- };
- requestFactory.userInformationRequest().getCurrentUserInformation(
- Location.getHref()).fire(receiver);
- }
- });
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesMobileShell.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesMobileShell.java
deleted file mode 100644
index d540149..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesMobileShell.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.shared.HandlerManager;
-import com.google.gwt.requestfactory.client.LoginWidget;
-import com.google.gwt.sample.expenses.gwt.request.EmployeeRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpenseRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecord;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.SimplePanel;
-import com.google.gwt.user.client.ui.Widget;
-
-import java.util.ArrayList;
-
-/**
- * TODO.
- */
-public class ExpensesMobileShell extends Composite {
-
- interface ShellUiBinder extends UiBinder<Widget, ExpensesMobileShell> { }
- private static ShellUiBinder BINDER = GWT.create(ShellUiBinder.class);
-
- @UiField SimplePanel container;
- @UiField HTML backButton, addButton, refreshButton, customButton;
- @UiField LoginWidget loginWidget;
- @UiField Element titleSpan;
-
- private MobileReportList reportList;
- private MobileExpenseList expenseList;
- private MobileExpenseDetails expenseDetails;
- private MobileExpenseEntry expenseEntry;
- private MobileReportEntry reportEntry;
-
- private final EmployeeRecord employee;
- private final HandlerManager eventBus;
- private final ExpensesRequestFactory requestFactory;
- private ArrayList<MobilePage> pages = new ArrayList<MobilePage>();
-
- public ExpensesMobileShell(HandlerManager eventBus,
- ExpensesRequestFactory requestFactory, EmployeeRecord employee) {
- this.eventBus = eventBus;
- this.requestFactory = requestFactory;
- this.employee = employee;
-
- initWidget(BINDER.createAndBindUi(this));
- showReportList();
- }
-
- /**
- * @return the login widget
- */
- public LoginWidget getLoginWidget() {
- return loginWidget;
- }
-
- @UiHandler("addButton")
- @SuppressWarnings("unused")
- void onAdd(ClickEvent evt) {
- topPage().onAdd();
- }
-
- @UiHandler("backButton")
- @SuppressWarnings("unused")
- void onBack(ClickEvent evt) {
- popPage();
- }
-
- @UiHandler("customButton")
- @SuppressWarnings("unused")
- void onCustom(ClickEvent evt) {
- topPage().onCustom();
- }
-
- @UiHandler("refreshButton")
- @SuppressWarnings("unused")
- void onRefresh(ClickEvent evt) {
- topPage().onRefresh(true);
- }
-
- private void popPage() {
- assert pages.size() > 1;
- pages.remove(topPage());
- MobilePage topPage = topPage();
- showPage(topPage);
- topPage.onRefresh(false);
- }
-
- private void pushPage(MobilePage page) {
- pages.add(page);
- showPage(page);
- }
-
- private void showExpenseDetails(ExpenseRecord expense) {
- if (expenseDetails == null) {
- expenseDetails = new MobileExpenseDetails(
- new MobileExpenseDetails.Listener() {
- public void onEditExpense(ExpenseRecord expense) {
- showExpenseEntry(expense);
- }
- }, eventBus, requestFactory);
- }
-
- expenseDetails.show(expense);
- pushPage(expenseDetails);
- }
-
- private void showExpenseEntry(ExpenseRecord expense) {
- if (expenseEntry == null) {
- expenseEntry = new MobileExpenseEntry(new MobileExpenseEntry.Listener() {
- public void onExpenseUpdated() {
- popPage();
- }
- }, requestFactory);
- }
-
- expenseEntry.show(expense);
- pushPage(expenseEntry);
- }
-
- private void showReportEntry(ReportRecord report) {
- if (reportEntry == null) {
- reportEntry = new MobileReportEntry(new MobileReportEntry.Listener() {
- public void onReportUpdated() {
- popPage();
- }
- }, requestFactory);
- }
-
- reportEntry.show(report);
- pushPage(reportEntry);
- }
-
- private void showExpenseList(final ReportRecord report) {
- if (expenseList == null) {
- expenseList = new MobileExpenseList(new MobileExpenseList.Listener() {
- public void onCreateExpense(ReportRecord report) {
- showNewExpenseEntry(report);
- }
-
- public void onEditReport(ReportRecord report) {
- showReportEntry(report);
- }
-
- public void onExpenseSelected(ExpenseRecord expense) {
- showExpenseDetails(expense);
- }
- }, requestFactory);
- }
-
- expenseList.show(report);
- pushPage(expenseList);
- }
-
- private void showNewExpenseEntry(ReportRecord report) {
- if (expenseEntry == null) {
- expenseEntry = new MobileExpenseEntry(new MobileExpenseEntry.Listener() {
- public void onExpenseUpdated() {
- popPage();
- }
- }, requestFactory);
- }
-
- expenseEntry.create(report);
- pushPage(expenseEntry);
- }
-
- private void showNewReportEntry(EmployeeRecord reporter) {
- if (reportEntry == null) {
- reportEntry = new MobileReportEntry(new MobileReportEntry.Listener() {
- public void onReportUpdated() {
- popPage();
- }
- }, requestFactory);
- }
-
- reportEntry.create(reporter);
- pushPage(reportEntry);
- }
-
- private void showPage(MobilePage page) {
- Widget oldPage = container.getWidget();
- if (oldPage != null) {
- container.remove(oldPage);
- }
-
- container.add(page.asWidget());
-
- titleSpan.setInnerText(page.getPageTitle());
- backButton.setVisible(pages.size() > 1);
- refreshButton.setVisible(page.needsRefreshButton());
- addButton.setVisible(page.needsAddButton());
-
- String custom = page.needsCustomButton();
- if (custom != null) {
- customButton.setText(custom);
- customButton.setVisible(true);
- } else {
- customButton.setVisible(false);
- }
- }
-
- private void showReportList() {
- if (reportList == null) {
- reportList = new MobileReportList(new MobileReportList.Listener() {
- public void onCreateReport(EmployeeRecord reporter) {
- showNewReportEntry(reporter);
- }
-
- public void onReportSelected(ReportRecord report) {
- showExpenseList(report);
- }
- }, requestFactory, employee);
- }
-
- pushPage(reportList);
- }
-
- private MobilePage topPage() {
- return pages.get(pages.size() - 1);
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesMobileShell.ui.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesMobileShell.ui.xml
deleted file mode 100644
index cfb495b..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesMobileShell.ui.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
-<ui:UiBinder
- xmlns:ui='urn:ui:com.google.gwt.uibinder'
- xmlns:m='urn:import:com.google.gwt.mobile.client'
- xmlns:r='urn:import:com.google.gwt.requestfactory.client'
- xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-
- <ui:style field='mobile' src='mobile.css'/>
-
- <g:HTMLPanel>
- <r:LoginWidget styleName='{mobile.login}' ui:field="loginWidget"/>
- <div class='{mobile.bar}'>
- <g:HTML ui:field='backButton' styleName='{mobile.backButton}'><div>Back</div></g:HTML>
- <g:HTML ui:field='addButton' styleName='{mobile.button}'><img src='images/add.png'/></g:HTML>
- <g:HTML ui:field='customButton' styleName='{mobile.customButton}'/>
- <g:HTML ui:field='refreshButton' styleName='{mobile.button}'><img src='images/refresh.png'/></g:HTML>
- <div class='{mobile.title}' ui:field='titleSpan'>Expenses</div>
- </div>
- <g:SimplePanel ui:field='container'/>
- </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesShell.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesShell.java
deleted file mode 100644
index 19120ee..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesShell.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.layout.client.Layout;
-import com.google.gwt.layout.client.Layout.Layer;
-import com.google.gwt.requestfactory.client.LoginWidget;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.DockLayoutPanel;
-import com.google.gwt.user.client.ui.LayoutPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-/**
- * UI shell for expenses sample app.
- */
-public class ExpensesShell extends Composite {
-
- interface ShellUiBinder extends UiBinder<Widget, ExpensesShell> {
- }
-
- private static ShellUiBinder uiBinder = GWT.create(ShellUiBinder.class);
-
- @UiField
- ExpenseList expenseList;
- @UiField
- ExpenseTree expenseTree;
- @UiField
- LayoutPanel layoutPanel;
- @UiField
- LoginWidget loginWidget;
- @UiField
- DockLayoutPanel dockLayout;
-
- private final ExpenseDetails expenseDetails = new ExpenseDetails();
-
- public ExpensesShell() {
- initWidget(uiBinder.createAndBindUi(this));
-
- // Handle breadcrumb events from Expense Details.
- expenseDetails.getReportsLink().addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent event) {
- showExpenseDetails(false);
- }
- });
- }
-
- public ExpenseDetails getExpenseDetails() {
- return expenseDetails;
- }
-
- public ExpenseList getExpenseList() {
- return expenseList;
- }
-
- public ExpenseTree getExpenseTree() {
- return expenseTree;
- }
-
- /**
- * @return the login widget
- */
- public LoginWidget getLoginWidget() {
- return loginWidget;
- }
-
- /**
- * Show or hide the expense details. When showing, the expense list is hidden.
- *
- * @param isShowing true to show details, false to show reports list
- */
- public void showExpenseDetails(boolean isShowing) {
- if (isShowing) {
- showWidget(expenseDetails, false);
- } else {
- showWidget(expenseList, true);
- }
- }
-
- /**
- * Slide a widget into view.
- *
- * @param widget the widget to show
- * @param fromLeft true to slide from left, false to slide from right
- */
- private void showWidget(Widget widget, boolean fromLeft) {
- // Early out if the widget is already in the layout panel.
- final Widget current = layoutPanel.getWidget(0);
- if (current == widget) {
- return;
- }
-
- // Initialize the layout.
- layoutPanel.add(widget);
- layoutPanel.setWidgetLeftWidth(current, 0, Unit.PCT, 100, Unit.PCT);
- if (fromLeft) {
- layoutPanel.setWidgetLeftWidth(widget, -100, Unit.PCT, 100, Unit.PCT);
- } else {
- layoutPanel.setWidgetLeftWidth(widget, 100, Unit.PCT, 100, Unit.PCT);
- }
- layoutPanel.forceLayout();
-
- // Slide into view.
- if (fromLeft) {
- layoutPanel.setWidgetLeftWidth(current, 100, Unit.PCT, 100, Unit.PCT);
- } else {
- layoutPanel.setWidgetLeftWidth(current, -100, Unit.PCT, 100, Unit.PCT);
- }
- layoutPanel.setWidgetLeftWidth(widget, 0, Unit.PCT, 100, Unit.PCT);
- layoutPanel.animate(500, new Layout.AnimationCallback() {
- public void onAnimationComplete() {
- // Remove the old widget when the animation completes.
- layoutPanel.remove(current);
- }
-
- public void onLayout(Layer layer, double progress) {
- }
- });
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesShell.ui.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesShell.ui.xml
deleted file mode 100644
index 3e642b8..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesShell.ui.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
-<ui:UiBinder
- xmlns:ui='urn:ui:com.google.gwt.uibinder'
- xmlns:g='urn:import:com.google.gwt.user.client.ui'
- xmlns:m='urn:import:com.google.gwt.mobile.client'
- xmlns:r='urn:import:com.google.gwt.requestfactory.client'
- xmlns:e='urn:import:com.google.gwt.sample.expenses.gwt.client'>
-
- <ui:with field='styles' type='com.google.gwt.sample.bikeshed.style.client.Styles' />
-
- <ui:image field='logo' />
-
- <ui:style>
- @sprite .logo {
- gwt-image: 'logo';
- }
-
- .login {
- position: absolute;
- left: 75%;
- right: 0%;
- text-align: center;
- background-color: white;
- color: #7b8fae;
- }
-
- .title {
- border-bottom: 1px solid #c3c3c3;
- }
-
- .titleText {
- color: #7b8fae;
- font-size: 20pt;
- font-weight: bold;
- text-shadow: #ddd 3px 3px 1px;
- }
-
- .expenseTree {
- background-color: #d7dde8;
- border-right: 1px solid #c3c3c3;
- }
- </ui:style>
-
- <g:DockLayoutPanel unit='PX'>
- <g:north size='96'>
- <g:HTMLPanel styleName='{style.title}'>
- <r:LoginWidget styleName='{style.login}' ui:field="loginWidget"/>
- <table height='100%' cellpadding='8' cellspacing='0'>
- <tr>
- <td>
- <div class='{style.logo}' />
- </td>
- <td class='{style.titleText}' valign='middle'>
- Expense Reports
- </td>
- </tr>
- </table>
- </g:HTMLPanel>
- </g:north>
-
- <g:center>
- <g:DockLayoutPanel ui:field='dockLayout'>
- <g:west size='225'>
- <m:MobileScrollPanel addStyleNames='{style.expenseTree}'>
- <e:ExpenseTree ui:field='expenseTree' />
- </m:MobileScrollPanel>
- </g:west>
- <g:center>
- <g:LayoutPanel ui:field='layoutPanel'>
- <g:layer>
- <e:ExpenseList ui:field='expenseList' />
- </g:layer>
- </g:LayoutPanel>
- </g:center>
- </g:DockLayoutPanel>
- </g:center>
- </g:DockLayoutPanel>
-
-</ui:UiBinder>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/GetValue.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/GetValue.java
deleted file mode 100644
index eb9e166..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/GetValue.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-/**
- * An interface for retrieving a value of type C from a record of type T.
- *
- * @param <T> the underlying record data type
- * @param <C> the extracted data type
- */
-public interface GetValue<T, C> {
- C getValue(T object);
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseDetails.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseDetails.java
deleted file mode 100644
index 620f299..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseDetails.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.event.shared.HandlerManager;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.sample.expenses.gwt.request.ExpenseRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpenseRecordChanged;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.valuestore.shared.PropertyReference;
-import com.google.gwt.valuestore.shared.SyncResult;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * TODO: doc.
- */
-public class MobileExpenseDetails extends Composite implements MobilePage {
-
- /**
- * TODO: doc.
- */
- public interface Listener {
- void onEditExpense(ExpenseRecord expense);
- }
-
- interface Binder extends UiBinder<Widget, MobileExpenseDetails> {
- }
-
- private static Binder BINDER = GWT.create(Binder.class);
-
- @UiField
- Element approvalText, nameText, dateText, categoryText, priceText, reasonRow,
- reasonText;
-
- private ExpenseRecord expense;
- private final Listener listener;
- private final ExpensesRequestFactory requestFactory;
-
- public MobileExpenseDetails(Listener listener, HandlerManager eventBus,
- ExpensesRequestFactory requestFactory) {
- this.listener = listener;
- this.requestFactory = requestFactory;
-
- eventBus.addHandler(ExpenseRecordChanged.TYPE,
- new ExpenseRecordChanged.Handler() {
- public void onExpenseRecordChanged(ExpenseRecordChanged event) {
- if (expense != null) {
- ExpenseRecord newRecord = event.getRecord();
- if (newRecord.getId().equals(expense.getId())) {
- show(newRecord);
- }
- }
- }
- });
-
- initWidget(BINDER.createAndBindUi(this));
- }
-
- public Widget asWidget() {
- return this;
- }
-
- public String getPageTitle() {
- return expense != null ? expense.getDescription() : "";
- }
-
- public boolean needsAddButton() {
- return false;
- }
-
- public String needsCustomButton() {
- return "Edit";
- }
-
- public boolean needsRefreshButton() {
- return true;
- }
-
- public void onAdd() {
- }
-
- public void onCustom() {
- listener.onEditExpense(expense);
- }
-
- public void onRefresh(boolean clear) {
- PropertyReference<Long> idRef = new PropertyReference<Long>(expense,
- ExpenseRecord.id);
-
- requestFactory.expenseRequest().findExpense(idRef).fire(
- new Receiver<List<ExpenseRecord>>() {
- public void onSuccess(List<ExpenseRecord> response, Set<SyncResult> syncResults) {
- assert response.size() == 1;
- show(response.get(0));
- }
- });
- }
-
- public void show(ExpenseRecord expense) {
- this.expense = expense;
-
- DateTimeFormat formatter = DateTimeFormat.getMediumDateFormat();
-
- Expenses.Approval approval = Expenses.Approval.from(expense.getApproval());
- nameText.setInnerText(expense.getDescription());
- dateText.setInnerText(formatter.format(expense.getCreated()));
- categoryText.setInnerText(expense.getCategory());
- priceText.setInnerText(ExpensesMobile.formatCurrency(expense.getAmount()));
- approvalText.setInnerHTML(Expenses.Approval.BLANK.equals(approval)
- ? "Awaiting Review" : approval.getText());
- approvalText.getStyle().setColor(approval.getColor());
-
- reasonText.setInnerText(expense.getReasonDenied());
- if (Expenses.Approval.DENIED.equals(approval)) {
- // Show the reason denied.
- reasonRow.getStyle().clearDisplay();
- } else {
- // Hide the reason denied.
- reasonRow.getStyle().setDisplay(Display.NONE);
- }
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseDetails.ui.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseDetails.ui.xml
deleted file mode 100644
index 2cf62d1..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseDetails.ui.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
-<ui:UiBinder
- xmlns:ui='urn:ui:com.google.gwt.uibinder'
- xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-
- <ui:style>
- .form {
- padding: 0.5em;
- background-color: #ebeff9;
- font-weight: bold;
- font-size: 13px;
- }
-
- .label {
- padding-right: 5px;
- }
-
- .reasonText {
- font-weight: normal;
- }
- </ui:style>
-
- <g:HTMLPanel styleName='{style.form}'>
- <table border='0'>
- <tr><td class='{style.label}'>Name:</td><td ui:field='nameText'></td></tr>
- <tr><td class='{style.label}'>Date:</td><td ui:field='dateText'></td></tr>
- <tr>
- <td class='{style.label}'>Category:</td><td ui:field='categoryText'>
- </td>
- </tr>
- <tr>
- <td class='{style.label}'>Price:</td><td>$<span ui:field='priceText'/>
- </td>
- </tr>
- <tr>
- <td class='{style.label}'>Status:</td><td ui:field='approvalText'></td>
- </tr>
- <tr ui:field='reasonRow'>
- <td></td>
- <td ui:field='reasonText' class='{style.reasonText}'></td>
- </tr>
- </table>
- </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseEntry.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseEntry.java
deleted file mode 100644
index 7cd556b..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseEntry.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.requestfactory.shared.RequestObject;
-import com.google.gwt.sample.expenses.gwt.request.ExpenseRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecord;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.valuestore.shared.SyncResult;
-
-import java.util.Date;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * TODO: doc.
- */
-public class MobileExpenseEntry extends Composite implements MobilePage {
-
- /**
- * TODO: doc.
- */
- public interface Listener {
- void onExpenseUpdated();
- }
-
- interface Binder extends UiBinder<Widget, MobileExpenseEntry> { }
- private static Binder BINDER = GWT.create(Binder.class);
-
- @UiField TextBox nameText, categoryText, priceText;
- @UiField ListBox dateYear, dateMonth, dateDay;
- @UiField Element errorText;
-
- private ExpenseRecord expense;
- private final ExpensesRequestFactory requestFactory;
- private final Listener listener;
- private RequestObject<Void> requestObject;
-
- public MobileExpenseEntry(Listener listener,
- ExpensesRequestFactory requestFactory) {
- this.listener = listener;
- this.requestFactory = requestFactory;
- initWidget(BINDER.createAndBindUi(this));
-
- populateList(dateYear, 2000, 2010);
- populateList(dateMonth, 1, 12);
- populateList(dateDay, 1, 31);
- }
-
- public Widget asWidget() {
- return this;
- }
-
- public void create(ReportRecord report) {
- expense = (ExpenseRecord) requestFactory.create(ExpenseRecord.class);
- requestObject = requestFactory.expenseRequest().persist(expense);
- ExpenseRecord editableExpense = requestObject.edit(expense);
- editableExpense.setReport(report);
- displayExpense();
- }
-
- public String getPageTitle() {
- return expense != null ? expense.getDescription() : "";
- }
-
- public boolean needsAddButton() {
- return false;
- }
-
- public String needsCustomButton() {
- return "Done";
- }
-
- public boolean needsRefreshButton() {
- return false;
- }
-
- public void onAdd() {
- }
-
- @SuppressWarnings("deprecation")
- public void onCustom() {
- ExpenseRecord editableExpense = requestObject.edit(expense);
- editableExpense.setDescription(nameText.getText());
- editableExpense.setCategory(categoryText.getText());
-
- // TODO(jgw): validate amount (in dollars -- database is in pennies)
- String amountText = priceText.getText();
- double amount = Double.parseDouble(amountText);
- editableExpense.setAmount(amount);
-
- // TODO(jgw): Use non-deprecated date methods for this.
- Date date = new Date(
- dateYear.getSelectedIndex() + 100,
- dateMonth.getSelectedIndex(),
- dateDay.getSelectedIndex() + 1
- );
- editableExpense.setCreated(date);
-
- // TODO: wait throbber
- requestObject.fire(new Receiver<Void>() {
- public void onSuccess(Void ignore, Set<SyncResult> response) {
- // Check for commit errors.
- String errorMessage = "";
- for (SyncResult result : response) {
- if (result.hasViolations()) {
- Map<String, String> violations = result.getViolations();
- for (String message : violations.values()) {
- errorMessage += message + " ";
- }
- }
- }
- if (errorMessage.length() > 0) {
- errorText.setInnerText(errorMessage);
- } else {
- listener.onExpenseUpdated();
- }
- }
- });
- }
-
- public void onRefresh(boolean clear) {
- }
-
- public void show(ExpenseRecord expense) {
- this.expense = expense;
- displayExpense();
- }
-
- @SuppressWarnings("deprecation")
- private void displayExpense() {
- errorText.setInnerText("");
- nameText.setText(expense.getDescription());
- categoryText.setText(expense.getCategory());
- priceText.setText(ExpensesMobile.formatCurrency(expense.getAmount()));
-
- // TODO(jgw): Use non-deprecated date methods for this.
- Date d = expense.getCreated();
- dateYear.setSelectedIndex(d.getYear() - 100);
- dateMonth.setSelectedIndex(d.getMonth());
- dateDay.setSelectedIndex(d.getDate() - 1);
- }
-
- private void populateList(ListBox list, int start, int end) {
- for (int i = start; i <= end; ++i) {
- if (i < 10) {
- list.addItem("0" + i);
- } else {
- list.addItem("" + i);
- }
- }
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseEntry.ui.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseEntry.ui.xml
deleted file mode 100644
index 92e1cc5..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseEntry.ui.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
-<ui:UiBinder
- xmlns:ui='urn:ui:com.google.gwt.uibinder'
- xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-
- <ui:style>
- .form {
- padding: 0.5em;
- background-color: #ebeff9;
- font-weight: bold;
- font-size: 13px;
- }
-
- .middleColumn {
- padding-left: 0px;
- padding-right: 0px;
- }
-
- .error {
- }
- </ui:style>
-
- <g:HTMLPanel styleName='{style.form}'>
- <table border='0'>
- <tr>
- <td>Name:</td><td class='{style.middleColumn}'></td>
- <td><g:TextBox ui:field='nameText'/></td>
- </tr>
- <tr>
- <td>Date:</td><td class='{style.middleColumn}'></td>
- <td><g:ListBox ui:field='dateYear'/>/<g:ListBox ui:field='dateMonth'/>/<g:ListBox ui:field='dateDay'/></td>
- </tr>
- <tr>
- <td>Category:</td><td class='{style.middleColumn}'></td>
- <td><g:TextBox ui:field='categoryText'/></td>
- </tr>
- <tr>
- <td>Price:</td><td class='{style.middleColumn}'>$</td>
- <td><g:TextBox ui:field='priceText'/></td>
- </tr>
- </table>
- <div class='error' ui:field='errorText'/>
- </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseList.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseList.java
deleted file mode 100644
index 586c3f2..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileExpenseList.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.cell.client.AbstractCell;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.sample.expenses.gwt.request.ExpenseRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecord;
-import com.google.gwt.user.cellview.client.CellList;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.valuestore.shared.Property;
-import com.google.gwt.valuestore.shared.SyncResult;
-import com.google.gwt.view.client.AsyncDataProvider;
-import com.google.gwt.view.client.HasData;
-import com.google.gwt.view.client.NoSelectionModel;
-import com.google.gwt.view.client.SelectionChangeEvent;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * TODO: doc.
- */
-public class MobileExpenseList extends Composite implements MobilePage {
-
- /**
- * The auto refresh interval in milliseconds.
- */
- private static final int REFRESH_INTERVAL = 5000;
-
- /**
- * TODO: doc.
- */
- public interface Listener {
- void onCreateExpense(ReportRecord report);
-
- void onEditReport(ReportRecord report);
-
- void onExpenseSelected(ExpenseRecord expense);
- }
-
- /**
- * The cell used to render {@link ExpenseRecord}s.
- */
- private class ExpenseCell extends AbstractCell<ExpenseRecord> {
-
- private final String approvedHtml;
- private final String approvedText = Expenses.Approval.APPROVED.getText();
- private final String blankHtml;
- private final String deniedHtml;
- private final String deniedText = Expenses.Approval.DENIED.getText();
-
- public ExpenseCell() {
- approvedHtml = Expenses.Approval.APPROVED.getIconHtml();
- blankHtml = Expenses.Approval.BLANK.getIconHtml();
- deniedHtml = Expenses.Approval.DENIED.getIconHtml();
- }
-
- @Override
- public void render(ExpenseRecord value, Object viewData, StringBuilder sb) {
- sb.append("<div class='item'>");
- String approval = value.getApproval();
- if (approvedText.equals(approval)) {
- sb.append(approvedHtml);
- } else if (deniedText.equals(approval)) {
- sb.append(deniedHtml);
- } else {
- sb.append(blankHtml);
- }
- sb.append(value.getDescription());
- sb.append(" (");
- sb.append(ExpensesMobile.formatCurrency(value.getAmount()));
- sb.append(")</div>");
- }
- }
-
- private final ExpensesRequestFactory requestFactory;
- private final CellList<ExpenseRecord> expenseList;
- private final AsyncDataProvider<ExpenseRecord> expenseDataProvider;
- private final NoSelectionModel<ExpenseRecord> expenseSelection;
-
- /**
- * The set of Expense keys that we already know are denied. When a new key is
- * added, we compare it to the list of known keys to determine if it is new.
- */
- private Set<Object> knownDeniedKeys = null;
-
- /**
- * The receiver for the last request.
- */
- private Receiver<List<ExpenseRecord>> lastReceiver;
-
- private ReportRecord report;
- private final Listener listener;
-
- /**
- * The {@link Timer} used to periodically refresh the table.
- */
- private final Timer refreshTimer = new Timer() {
- @Override
- public void run() {
- requestExpenses();
- }
- };
-
- public MobileExpenseList(
- final Listener listener, final ExpensesRequestFactory requestFactory) {
- this.listener = listener;
- this.requestFactory = requestFactory;
- expenseDataProvider = new AsyncDataProvider<ExpenseRecord>() {
- @Override
- protected void onRangeChanged(HasData<ExpenseRecord> view) {
- requestExpenses();
- }
- };
- expenseDataProvider.setKeyProvider(Expenses.EXPENSE_RECORD_KEY_PROVIDER);
-
- expenseList = new CellList<ExpenseRecord>(new ExpenseCell());
-
- expenseSelection = new NoSelectionModel<ExpenseRecord>();
- expenseList.setSelectionModel(expenseSelection);
- expenseSelection.addSelectionChangeHandler(
- new SelectionChangeEvent.Handler() {
- public void onSelectionChange(SelectionChangeEvent event) {
- listener.onExpenseSelected(
- expenseSelection.getLastSelectedObject());
- }
- });
-
- expenseDataProvider.addDataDisplay(expenseList);
- initWidget(expenseList);
- }
-
- public Widget asWidget() {
- return this;
- }
-
- public String getPageTitle() {
- return report != null ? report.getPurpose() : "";
- }
-
- public boolean needsAddButton() {
- return true;
- }
-
- public String needsCustomButton() {
- return "Edit";
- }
-
- public boolean needsRefreshButton() {
- return true;
- }
-
- public void onAdd() {
- listener.onCreateExpense(report);
- }
-
- public void onCustom() {
- listener.onEditReport(report);
- }
-
- public void onRefresh(boolean clear) {
- if (clear) {
- expenseDataProvider.updateRowCount(0, true);
- }
- requestExpenses();
- }
-
- public void show(ReportRecord report) {
- this.report = report;
- knownDeniedKeys = null;
-
- onRefresh(true);
- }
-
- private Collection<Property<?>> getExpenseColumns() {
- List<Property<?>> columns = new ArrayList<Property<?>>();
- columns.add(ExpenseRecord.description);
- columns.add(ExpenseRecord.amount);
- return columns;
- }
-
- /**
- * Request the expenses.
- */
- private void requestExpenses() {
- refreshTimer.cancel();
- if (requestFactory == null || report == null) {
- return;
- }
- lastReceiver = new Receiver<List<ExpenseRecord>>() {
- public void onSuccess(
- List<ExpenseRecord> newValues, Set<SyncResult> syncResults) {
- if (this == lastReceiver) {
- int size = newValues.size();
- expenseDataProvider.updateRowCount(size, true);
- expenseDataProvider.updateRowData(0, newValues);
-
- // Add the new keys to the known keys.
- boolean isInitialData = knownDeniedKeys == null;
- if (knownDeniedKeys == null) {
- knownDeniedKeys = new HashSet<Object>();
- }
- for (ExpenseRecord value : newValues) {
- Object key = expenseDataProvider.getKey(value);
- String approval = value.getApproval();
- if (Expenses.Approval.DENIED.getText().equals(approval)) {
- if (!isInitialData && !knownDeniedKeys.contains(key)) {
- (new PhaseAnimation.CellListPhaseAnimation<ExpenseRecord>(
- expenseList, value, expenseDataProvider)).run();
- }
- knownDeniedKeys.add(key);
- } else {
- knownDeniedKeys.remove(key);
- }
- }
-
- refreshTimer.schedule(REFRESH_INTERVAL);
- }
- }
- };
- requestFactory.expenseRequest().findExpensesByReport(
- report.getRef(ReportRecord.id)).forProperties(getExpenseColumns()).fire(
- lastReceiver);
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobilePage.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobilePage.java
deleted file mode 100644
index a778bab..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobilePage.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.user.client.ui.Widget;
-
-/**
- * TODO: doc.
- */
-public interface MobilePage {
-
- Widget asWidget();
-
- String getPageTitle();
-
- boolean needsAddButton();
- String needsCustomButton();
- boolean needsRefreshButton();
-
- void onAdd();
- void onCustom();
-
- /**
- * Refresh the page.
- *
- * @param clear true to clear the data first
- */
- void onRefresh(boolean clear);
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileReportEntry.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileReportEntry.java
deleted file mode 100644
index 5791343..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileReportEntry.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.requestfactory.shared.RequestObject;
-import com.google.gwt.sample.expenses.gwt.request.EmployeeRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecord;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.valuestore.shared.SyncResult;
-
-import java.util.Date;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Form to create a new ReportRecord.
- */
-public class MobileReportEntry extends Composite implements MobilePage {
-
- /**
- * TODO: doc.
- */
- public interface Listener {
- void onReportUpdated();
- }
-
- interface Binder extends UiBinder<Widget, MobileReportEntry> {
- }
-
- private static Binder BINDER = GWT.create(Binder.class);
-
- @UiField
- TextBox purposeText, notesText;
- @UiField
- ListBox dateYear, dateMonth, dateDay, departmentList;
- @UiField
- Element errorText;
-
- private ReportRecord report;
- private final ExpensesRequestFactory requestFactory;
- private final Listener listener;
- private RequestObject<Void> requestObject;
-
- public MobileReportEntry(Listener listener,
- ExpensesRequestFactory requestFactory) {
- this.listener = listener;
- this.requestFactory = requestFactory;
- initWidget(BINDER.createAndBindUi(this));
-
- for (String department : Expenses.DEPARTMENTS) {
- departmentList.addItem(department);
- }
-
- populateList(dateYear, 2000, 2010);
- populateList(dateMonth, 1, 12);
- populateList(dateDay, 1, 31);
- }
-
- public Widget asWidget() {
- return this;
- }
-
- public void create(EmployeeRecord reporter) {
- report = (ReportRecord) requestFactory.create(ReportRecord.class);
- requestObject = requestFactory.reportRequest().persist(report);
- ReportRecord editableReport = requestObject.edit(report);
- editableReport.setReporter(reporter);
- displayReport();
- }
-
- public String getPageTitle() {
- return report != null ? report.getPurpose() : "";
- }
-
- public boolean needsAddButton() {
- return false;
- }
-
- public String needsCustomButton() {
- return "Done";
- }
-
- public boolean needsRefreshButton() {
- return false;
- }
-
- public void onAdd() {
- }
-
- @SuppressWarnings("deprecation")
- public void onCustom() {
- ReportRecord editableReport = requestObject.edit(report);
- editableReport.setPurpose(purposeText.getText());
- editableReport.setNotes(notesText.getText());
- editableReport.setDepartment(departmentList.getValue(departmentList.getSelectedIndex()));
-
- // TODO(jgw): Use non-deprecated date methods for this.
- Date date = new Date(dateYear.getSelectedIndex() + 100,
- dateMonth.getSelectedIndex(), dateDay.getSelectedIndex() + 1);
- editableReport.setCreated(date);
-
- // TODO: wait throbber
- requestObject.fire(new Receiver<Void>() {
- public void onSuccess(Void ignore, Set<SyncResult> response) {
- // Check for commit errors.
- String errorMessage = "";
- for (SyncResult result : response) {
- if (result.hasViolations()) {
- Map<String, String> violations = result.getViolations();
- for (String message : violations.values()) {
- errorMessage += message + " ";
- }
- }
- }
- if (errorMessage.length() > 0) {
- errorText.setInnerText(errorMessage);
- } else {
- listener.onReportUpdated();
- }
- }
- });
- }
-
- public void onRefresh(boolean clear) {
- }
-
- public void show(ReportRecord report) {
- this.report = report;
- displayReport();
- }
-
- @SuppressWarnings("deprecation")
- private void displayReport() {
- errorText.setInnerText("");
- purposeText.setText(report.getPurpose());
- notesText.setText(report.getNotes());
- String department = report.getDepartment();
- departmentList.setSelectedIndex(0);
- for (int i = 0; i < Expenses.DEPARTMENTS.length; i++) {
- if (Expenses.DEPARTMENTS[i].equals(department)) {
- departmentList.setSelectedIndex(i);
- }
- }
-
- // TODO(jgw): Use non-deprecated date methods for this.
- Date d = report.getCreated();
- dateYear.setSelectedIndex(d.getYear() - 100);
- dateMonth.setSelectedIndex(d.getMonth());
- dateDay.setSelectedIndex(d.getDate() - 1);
- }
-
- private void populateList(ListBox list, int start, int end) {
- for (int i = start; i <= end; ++i) {
- if (i < 10) {
- list.addItem("0" + i);
- } else {
- list.addItem("" + i);
- }
- }
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileReportEntry.ui.xml b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileReportEntry.ui.xml
deleted file mode 100644
index 24a1ac7..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileReportEntry.ui.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
-<ui:UiBinder
- xmlns:ui='urn:ui:com.google.gwt.uibinder'
- xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-
- <ui:style>
- .form {
- padding: 0.5em;
- background-color: #ebeff9;
- font-weight: bold;
- font-size: 13px;
- }
-
- .error {
- }
- </ui:style>
-
- <g:HTMLPanel styleName='{style.form}'>
- <table border='0'>
- <tr>
- <td>Purpose:</td>
- <td><g:TextBox ui:field='purposeText'/></td>
- </tr>
- <tr>
- <td>Date:</td>
- <td><g:ListBox ui:field='dateYear'/>/<g:ListBox ui:field='dateMonth'/>/<g:ListBox ui:field='dateDay'/></td>
- </tr>
- <tr>
- <td>Department:</td>
- <td><g:ListBox ui:field='departmentList'/></td>
- </tr>
- <tr>
- <td>Notes:</td>
- <td><g:TextBox ui:field='notesText'/></td>
- </tr>
- </table>
- <div class='error' ui:field='errorText'/>
- </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileReportList.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileReportList.java
deleted file mode 100644
index 957bfed..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/MobileReportList.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.cell.client.AbstractCell;
-import com.google.gwt.requestfactory.shared.Receiver;
-import com.google.gwt.sample.expenses.gwt.request.EmployeeRecord;
-import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
-import com.google.gwt.sample.expenses.gwt.request.ReportRecord;
-import com.google.gwt.user.cellview.client.CellList;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.valuestore.shared.Property;
-import com.google.gwt.valuestore.shared.SyncResult;
-import com.google.gwt.view.client.AsyncDataProvider;
-import com.google.gwt.view.client.HasData;
-import com.google.gwt.view.client.NoSelectionModel;
-import com.google.gwt.view.client.SelectionChangeEvent;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-/**
- * TODO: doc.
- */
-public class MobileReportList extends Composite implements MobilePage {
-
- /**
- * TODO: doc.
- */
- public interface Listener {
- void onCreateReport(EmployeeRecord reporter);
-
- void onReportSelected(ReportRecord report);
- }
-
- /**
- * The receiver for the last request.
- */
- private Receiver<List<ReportRecord>> lastReceiver;
-
- private final EmployeeRecord employee;
- private final Listener listener;
- private final CellList<ReportRecord> reportList;
- private final AsyncDataProvider<ReportRecord> reportDataProvider;
- private final NoSelectionModel<ReportRecord> reportSelection;
- private final ExpensesRequestFactory requestFactory;
-
- public MobileReportList(final Listener listener,
- final ExpensesRequestFactory requestFactory, EmployeeRecord employee) {
- this.listener = listener;
- this.requestFactory = requestFactory;
- this.employee = employee;
-
- reportDataProvider = new AsyncDataProvider<ReportRecord>() {
- @Override
- protected void onRangeChanged(HasData<ReportRecord> view) {
- requestReports();
- }
- };
- reportDataProvider.setKeyProvider(Expenses.REPORT_RECORD_KEY_PROVIDER);
-
- reportList = new CellList<ReportRecord>(new AbstractCell<ReportRecord>() {
- @Override
- public void render(
- ReportRecord value, Object viewData, StringBuilder sb) {
- sb.append("<div class='item'>" + value.getPurpose() + "</div>");
- }
- });
-
- reportSelection = new NoSelectionModel<ReportRecord>();
- reportSelection.setKeyProvider(Expenses.REPORT_RECORD_KEY_PROVIDER);
- reportSelection.addSelectionChangeHandler(
- new SelectionChangeEvent.Handler() {
- public void onSelectionChange(SelectionChangeEvent event) {
- listener.onReportSelected(reportSelection.getLastSelectedObject());
- }
- });
-
- reportList.setSelectionModel(reportSelection);
- reportDataProvider.addDataDisplay(reportList);
-
- initWidget(reportList);
- onRefresh(false);
- }
-
- public Widget asWidget() {
- return this;
- }
-
- public String getPageTitle() {
- return "Expense Reports";
- }
-
- public boolean needsAddButton() {
- return true;
- }
-
- public String needsCustomButton() {
- return null;
- }
-
- public boolean needsRefreshButton() {
- return true;
- }
-
- public void onAdd() {
- listener.onCreateReport(employee);
- }
-
- public void onCustom() {
- }
-
- public void onRefresh(boolean clear) {
- if (clear) {
- reportDataProvider.updateRowCount(0, true);
- }
- requestReports();
- }
-
- private Collection<Property<?>> getReportColumns() {
- List<Property<?>> columns = new ArrayList<Property<?>>();
- columns.add(ReportRecord.created);
- columns.add(ReportRecord.purpose);
- return columns;
- }
-
- private void requestReports() {
- if (requestFactory == null) {
- return;
- }
- lastReceiver = new Receiver<List<ReportRecord>>() {
- public void onSuccess(
- List<ReportRecord> newValues, Set<SyncResult> syncResults) {
- int size = newValues.size();
- reportDataProvider.updateRowCount(size, true);
- reportDataProvider.updateRowData(0, newValues);
- }
- };
- requestFactory.reportRequest().findReportEntriesBySearch(employee.getId(), "",
- "", ReportRecord.created.getName() + " DESC", 0, 25).forProperties(
- getReportColumns()).fire(lastReceiver);
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/PhaseAnimation.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/PhaseAnimation.java
deleted file mode 100644
index fdc76b68..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/PhaseAnimation.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.animation.client.Animation;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.user.cellview.client.CellList;
-import com.google.gwt.user.cellview.client.CellTable;
-import com.google.gwt.view.client.ProvidesKey;
-
-import java.util.List;
-
-/**
- * An animation used to phase in a value in a {@link CellTable}.
- *
- * @param <T> the data type of items
- */
-public abstract class PhaseAnimation<T> extends Animation {
-
- /**
- * The duration of the animation used to phase in new rows.
- */
- private static final int DEFAULT_DURATION = 4000;
-
- /**
- * A {@link PhaseAnimation} for {@link CellList}.
- *
- * @param <T> the data type of items
- */
- public static class CellListPhaseAnimation<T> extends PhaseAnimation<T> {
-
- private final CellList<T> cellList;
-
- /**
- * Construct a new {@link PhaseAnimation}.
- *
- * @param cellList the {@link CellList} to animate
- * @param value the value to phase in
- * @param keyProvider the {@link ProvidesKey}
- */
- public CellListPhaseAnimation(CellList<T> cellList, T value,
- ProvidesKey<T> keyProvider) {
- super(value, keyProvider);
- this.cellList = cellList;
- }
-
- @Override
- protected T getDisplayedItem(int index) {
- return cellList.getDisplayedItem(index);
- }
-
- @Override
- protected List<T> getDisplayedItems() {
- return cellList.getDisplayedItems();
- }
-
- @Override
- protected Element getRowElement(int index) {
- return cellList.getRowElement(index);
- }
- }
-
- /**
- * A {@link PhaseAnimation} for {@link CellTable}.
- *
- * @param <T> the data type of items
- */
- public static class CellTablePhaseAnimation<T> extends PhaseAnimation<T> {
-
- private final CellTable<T> cellTable;
-
- /**
- * Construct a new {@link PhaseAnimation}.
- *
- * @param cellTable the {@link CellTable} to animate
- * @param value the value to phase in
- * @param keyProvider the {@link ProvidesKey}
- */
- public CellTablePhaseAnimation(CellTable<T> cellTable, T value,
- ProvidesKey<T> keyProvider) {
- super(value, keyProvider);
- this.cellTable = cellTable;
- }
-
- @Override
- protected T getDisplayedItem(int index) {
- return cellTable.getDisplayedItem(index);
- }
-
- @Override
- protected List<T> getDisplayedItems() {
- return cellTable.getDisplayedItems();
- }
-
- @Override
- protected Element getRowElement(int index) {
- return cellTable.getRowElement(index);
- }
- }
-
- private final Object key;
- private final ProvidesKey<T> keyProvider;
- private int lastRowIndex = -1;
-
- /**
- * Construct a new {@link CellTablePhaseAnimation}.
- *
- * @param value the value to phase in
- * @param keyProvider the {@link ProvidesKey}
- */
- public PhaseAnimation(T value, ProvidesKey<T> keyProvider) {
- this.key = keyProvider.getKey(value);
- this.keyProvider = keyProvider;
- }
-
- /**
- * Run the animation using the default duration.
- */
- public void run() {
- run(DEFAULT_DURATION);
- }
-
- /**
- * Get the item at the specified index.
- *
- * @param index the index
- * @return the item
- */
- protected abstract T getDisplayedItem(int index);
-
- /**
- * Get a list of all displayed items.
- *
- * @return the list of items
- */
- protected abstract List<T> getDisplayedItems();
-
- /**
- * Get the row element at the specified index.
- *
- * @param index the row index
- * @return the element
- */
- protected abstract Element getRowElement(int index);
-
- @Override
- protected void onComplete() {
- Element elem = getItemElement();
- if (elem != null) {
- elem.getStyle().clearBackgroundColor();
- }
- }
-
- @Override
- protected void onUpdate(double progress) {
- Element elem = getItemElement();
- if (elem != null) {
- int r = 255;
- int g = 200 + (int) (55.0 * progress);
- int b = 0 + (int) (255.0 * progress);
- elem.getStyle().setBackgroundColor("rgb(" + r + "," + g + "," + b + ")");
- }
- }
-
- /**
- * Get the {@link Element} of the value within the table.
- *
- * @return the element, or null if not found
- */
- private Element getItemElement() {
- // Check if the cached row index is still valid.
- if (lastRowIndex >= 0) {
- T value = getDisplayedItem(lastRowIndex);
- if (value == null || !key.equals(keyProvider.getKey(value))) {
- lastRowIndex = -1;
- }
- }
-
- // Find the index of the row element.
- if (lastRowIndex < 0) {
- List<T> items = getDisplayedItems();
- for (int i = 0; i < items.size(); i++) {
- T item = items.get(i);
- if (item != null && key.equals(keyProvider.getKey(item))) {
- lastRowIndex = i;
- break;
- }
- }
- }
-
- // Return the row element.
- return lastRowIndex < 0 ? null : getRowElement(lastRowIndex);
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/SortableHeader.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/SortableHeader.java
deleted file mode 100644
index 9d964e9..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/SortableHeader.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.expenses.gwt.client;
-
-import com.google.gwt.cell.client.ClickableTextCell;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.resources.client.ClientBundle;
-import com.google.gwt.resources.client.ImageResource;
-import com.google.gwt.user.cellview.client.Header;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-
-/**
- * A {@link Header} subclass that maintains sorting state and displays an icon
- * to indicate the sort direction.
- */
-public class SortableHeader extends Header<String> {
-
- /**
- * Image resources.
- */
- public static interface Resources extends ClientBundle {
-
- ImageResource downArrow();
-
- ImageResource upArrow();
- }
-
- private static final Resources RESOURCES = GWT.create(Resources.class);
- private static final int IMAGE_WIDTH = 16;
- private static final String DOWN_ARROW = makeImage(RESOURCES.downArrow());
- private static final String UP_ARROW = makeImage(RESOURCES.upArrow());
-
- private static String makeImage(ImageResource resource) {
- AbstractImagePrototype proto = AbstractImagePrototype.create(resource);
- return proto.getHTML().replace("style='",
- "style='position:absolute;right:0px;top:0px;");
- }
-
- private boolean reverseSort = false;
- private boolean sorted = false;
- private String text;
-
- SortableHeader(String text) {
- super(new ClickableTextCell());
- this.text = text;
- }
-
- public boolean getReverseSort() {
- return reverseSort;
- }
-
- @Override
- public String getValue() {
- return text;
- }
-
- @Override
- public void render(StringBuilder sb) {
- int imageWidth = IMAGE_WIDTH;
- sb.append("<div style='position:relative;cursor:hand;cursor:pointer;");
- sb.append("padding-right:");
- sb.append(imageWidth);
- sb.append("px;'>");
- if (sorted) {
- if (reverseSort) {
- sb.append(DOWN_ARROW);
- } else {
- sb.append(UP_ARROW);
- }
- } else {
- sb.append("<div style='position:absolute;display:none;'></div>");
- }
- sb.append("<div>");
- sb.append(text);
- sb.append("</div></div>");
- }
-
- public void setReverseSort(boolean reverseSort) {
- this.reverseSort = reverseSort;
- }
-
- public void setSorted(boolean sorted) {
- this.sorted = sorted;
- }
-
- public void toggleReverseSort() {
- this.reverseSort = !this.reverseSort;
- }
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerBottomLeft.png b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerBottomLeft.png
deleted file mode 100644
index ba3dbed..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerBottomLeft.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerBottomRight.png b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerBottomRight.png
deleted file mode 100644
index a216064..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerBottomRight.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerTopLeft.png b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerTopLeft.png
deleted file mode 100644
index ed5d8c0..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerTopLeft.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerTopRight.png b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerTopRight.png
deleted file mode 100644
index 77691bb..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/cornerTopRight.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/desktop.css b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/desktop.css
deleted file mode 100644
index 7dbb16b..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/desktop.css
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Applied to the nine box around the breadcrumb. */
-.breadcrumbBar {
- padding: 15px 15px 0px;
-}
-
-.breadcrumbCorner {
- height: 4px;
- width: 4px;
-}
-
-@sprite .breadcrumbCornerTopRight {
- gwt-image: 'cornerTopRight';
-}
-
-@sprite .breadcrumbCornerTopLeft {
- gwt-image: 'cornerTopLeft';
-}
-
-@sprite .breadcrumbCornerBottomRight {
- gwt-image: 'cornerBottomRight';
-}
-
-@sprite .breadcrumbCornerBottomLeft {
- gwt-image: 'cornerBottomLeft';
-}
-
-.breadcrumbBorder {
- background: #d7dde8;
-}
-
-.breadcrumbBorderInner {
- height: 1px;
- width: 1px;
- overflow: hidden;
-}
-
-.breadcrumb {
- padding-left: 5px;
- color: #4b4a4a;
- font-size: 130%;
- font-weight: bold;
-}
-
-/* Applied to the main table. */
-.table {
- border: 0px;
-}
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/downArrow.png b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/downArrow.png
deleted file mode 100644
index fd4012c..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/downArrow.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/leftArrow.png b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/leftArrow.png
deleted file mode 100644
index fa973c9..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/leftArrow.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/logo.png b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/logo.png
deleted file mode 100644
index 42013ee..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/logo.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/pendingNotes.gif b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/pendingNotes.gif
deleted file mode 100644
index 2021700..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/pendingNotes.gif
+++ /dev/null
Binary files differ
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/upArrow.png b/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/upArrow.png
deleted file mode 100644
index a336947..0000000
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/upArrow.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/war/Expenses.html b/bikeshed/war/Expenses.html
deleted file mode 100644
index 1e18be9..0000000
--- a/bikeshed/war/Expenses.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!doctype html>
-
-<!-- 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 -->
-<!-- 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. License for the specific language governing permissions and -->
-<!-- limitations under the License. -->
-
-<html>
- <head>
- <meta http-equiv="content-type" content="text/html; charset=UTF-8">
- <meta name="apple-mobile-web-app-capable" content="yes">
- <meta name="viewport" content="width=device-width, user-scalable=no">
-
- <title>Expenses</title>
-
- <style>
- body {
- font-family: Arial, sans-serif;
- }
-
- .item {
- border-bottom: 1px solid #ccc;
- padding: 0.5em;
- font-size: 16px;
- font-weight: bold;
- }
- </style>
-
- <script type="text/javascript" language="javascript" src="expenses/expenses.nocache.js"></script>
- <script type="text/javascript" language="javascript" src="json2.js"></script>
- </head>
-
- <body>
- <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>
- </body>
-</html>
diff --git a/bikeshed/war/ExpensesMobile.html b/bikeshed/war/ExpensesMobile.html
deleted file mode 100644
index 0d6f6e5..0000000
--- a/bikeshed/war/ExpensesMobile.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!doctype html>
-
-<!-- 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 -->
-<!-- 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. License for the specific language governing permissions and -->
-<!-- limitations under the License. -->
-
-<html>
- <head>
- <meta http-equiv="content-type" content="text/html; charset=UTF-8">
- <meta name="apple-mobile-web-app-capable" content="yes">
- <meta name="viewport" content="width=device-width, user-scalable=no">
-
- <title>Expenses</title>
-
- <style>
- body {
- font-family: Arial, sans-serif;
- }
-
- .item {
- border-bottom: 1px solid #ccc;
- padding: 0.5em;
- font-size: 16px;
- font-weight: bold;
- }
- </style>
-
- <script type="text/javascript" language="javascript" src="expensesMobile/expensesMobile.nocache.js"></script>
- <script type="text/javascript" language="javascript" src="json2.js"></script>
- </head>
-
- <body>
- <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>
- </body>
-</html>
diff --git a/bikeshed/war/bg.png b/bikeshed/war/bg.png
deleted file mode 100644
index 7617246..0000000
--- a/bikeshed/war/bg.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/war/blueborder.png b/bikeshed/war/blueborder.png
deleted file mode 100644
index 092791e..0000000
--- a/bikeshed/war/blueborder.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/war/border.png b/bikeshed/war/border.png
deleted file mode 100644
index 6338b88..0000000
--- a/bikeshed/war/border.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/war/hsplitter-grip.png b/bikeshed/war/hsplitter-grip.png
deleted file mode 100644
index cdacbba..0000000
--- a/bikeshed/war/hsplitter-grip.png
+++ /dev/null
Binary files differ
diff --git a/bikeshed/war/vsplitter-grip.png b/bikeshed/war/vsplitter-grip.png
deleted file mode 100644
index 8a152bf..0000000
--- a/bikeshed/war/vsplitter-grip.png
+++ /dev/null
Binary files differ