From: Marko Grönroos Date: Thu, 7 Aug 2008 17:21:02 +0000 (+0000) Subject: Generated column example for #1836. X-Git-Tag: 6.7.0.beta1~4383 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b5f9e160c55cc525690b6c88ff0da680073b5a8e;p=vaadin-framework.git Generated column example for #1836. svn changeset:5157/svn branch:trunk --- diff --git a/WebContent/ITMILL/themes/example/styles.css b/WebContent/ITMILL/themes/example/styles.css index d923e575b1..b68c9cc2bb 100644 --- a/WebContent/ITMILL/themes/example/styles.css +++ b/WebContent/ITMILL/themes/example/styles.css @@ -6,6 +6,9 @@ overflow:hidden; } +/****************************************************************************** + * For FormExample.java + ******************************************************************************/ .i-form { border: 1px solid; margin: 10px; @@ -15,3 +18,23 @@ .i-orderedlayout-formroot td { vertical-align: top; } + +/****************************************************************************** + * For GeneratedColumnExample.java. + ******************************************************************************/ +/* Align columns generated with ValueColumnGenerator to right. */ +.i-label-column-type-value { + text-align: right; +} + +/* The total value column is displayed in bold. */ +.i-label-column-total { + font-weight: bold; + text-align: right; +} + +/* Display calculated values in blue color. */ +.i-label-column-price, .i-label-column-consumption, .i-label-column-dailycost { + color: blue; + text-align: right; +} \ No newline at end of file diff --git a/src/com/itmill/toolkit/demo/featurebrowser/GeneratedColumnExample.java b/src/com/itmill/toolkit/demo/featurebrowser/GeneratedColumnExample.java new file mode 100644 index 0000000000..26fd276f1f --- /dev/null +++ b/src/com/itmill/toolkit/demo/featurebrowser/GeneratedColumnExample.java @@ -0,0 +1,436 @@ +package com.itmill.toolkit.demo.featurebrowser; + +import java.util.Collection; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Vector; + +import com.itmill.toolkit.data.Container; +import com.itmill.toolkit.data.Item; +import com.itmill.toolkit.data.Property; +import com.itmill.toolkit.data.Container.Indexed; +import com.itmill.toolkit.data.util.BeanItem; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.CustomComponent; +import com.itmill.toolkit.ui.ExpandLayout; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Table; + +public class GeneratedColumnExample extends CustomComponent { + /** + * The business model: fill-up at a gas station. + */ + public class FillUp { + Date date; + double quantity; + double total; + + public FillUp() { + } + + public FillUp(int day, int month, int year, double quantity, double total) { + this.date = new GregorianCalendar(year,month-1,day).getTime(); + this.quantity = quantity; + this.total = total; + } + + /** Calculates price per unit of quantity (€/l). */ + public double price() { + if (quantity != 0.0) + return total/quantity; + else + return 0.0; + } + + /** Calculates average daily consumption between two fill-ups. */ + public double dailyConsumption(FillUp other) { + double difference_ms = date.getTime() - other.date.getTime(); + double days = difference_ms/1000/3600/24; + if (days < 0.5) + days = 1.0; // Avoid division by zero if two fill-ups on the same day. + return quantity/days; + } + + /** Calculates average daily consumption between two fill-ups. */ + public double dailyCost(FillUp other) { + return price() * dailyConsumption(other); + } + + // Getters and setters + + public Date getDate() { + return date; + } + public void setDate(Date date) { + this.date = date; + } + public double getQuantity() { + return quantity; + } + public void setQuantity(double quantity) { + this.quantity = quantity; + } + public double getTotal() { + return total; + } + public void setTotal(double total) { + this.total = total; + } + }; + + /** + * This is a custom container that allows adding BeanItems inside it. The + * BeanItem objects must be bound to an object. The item ID is an + * Integer from 0 to 99. + * + * Most of the interface methods are implemented with just dummy + * implementations, as they are not needed in this example. + */ + public class MyContainer implements Container,Indexed { + Vector items; + Object itemtemplate; + + public MyContainer(Object itemtemplate) { + this.itemtemplate = itemtemplate; + items = new Vector(); // Yeah this is just a test + } + + public boolean addContainerProperty(Object propertyId, Class type, + Object defaultValue) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + public Item addItem(Object itemId) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + public Object addItem() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * This addItem method is specific for this container and allows adding + * BeanItem objects. The BeanItems must be bound to MyBean objects. + */ + public void addItem(BeanItem item) throws UnsupportedOperationException { + items.add(item); + } + + public boolean containsId(Object itemId) { + if (itemId instanceof Integer) { + int pos = ((Integer)itemId).intValue(); + if (pos >= 0 && pos < items.size()) + return items.get(pos) != null; + } + return false; + } + + /** + * The Table will call this method to get the property objects for the + * columns. It uses the property objects to determine the data types of + * the columns. + */ + public Property getContainerProperty(Object itemId, Object propertyId) { + if (itemId instanceof Integer) { + int pos = ((Integer)itemId).intValue(); + if (pos >= 0 && pos < items.size()) { + Item item = items.get(pos); + + // The BeanItem provides the property objects for the items. + return item.getItemProperty(propertyId); + } + } + return null; + } + + /** Table calls this to get the column names. */ + public Collection getContainerPropertyIds() { + Item item = new BeanItem(itemtemplate); + + // The BeanItem knows how to get the property names from the bean. + return item.getItemPropertyIds(); + } + + public Item getItem(Object itemId) { + if (itemId instanceof Integer) { + int pos = ((Integer)itemId).intValue(); + if (pos >= 0 && pos < items.size()) + return items.get(pos); + } + return null; + } + + public Collection getItemIds() { + Vector ids = new Vector(items.size()); + for (int i=0; i= items.size()-1) + return null; + return getIdByIndex(pos+1); + } + + public Object prevItemId(Object itemId) { + int pos = indexOfId(itemId); + if (pos <= 0) + return null; + return getIdByIndex(pos-1); + } + } + + /** Formats the dates in a column containing Date objects. */ + class DateColumnGenerator implements Table.ColumnGenerator { + /** + * Generates the cell containing the Date value. The column is + * irrelevant in this use case. + */ + public Component generateCell(Table source, Object itemId, Object columnId) { + Property prop = source.getItem(itemId).getItemProperty(columnId); + if (prop.getType().equals(Date.class)) { + Label label = new Label(String.format("%tF", (Date)prop.getValue())); + label.addStyleName("column-type-date"); + return label; + } + + return null; + } + } + + /** Formats the value in a column containing Double objects. */ + class ValueColumnGenerator implements Table.ColumnGenerator { + String format; /** Format string for the Double values. */ + + /** Creates double value column formatter with the given format string. */ + public ValueColumnGenerator(String format) { + this.format = format; + } + + /** + * Generates the cell containing the Double value. The column is + * irrelevant in this use case. + */ + public Component generateCell(Table source, Object itemId, Object columnId) { + Property prop = source.getItem(itemId).getItemProperty(columnId); + if (prop.getType().equals(Double.class)) { + Label label = new Label(String.format(format, (Double) prop.getValue())); + + // Set styles for the column: one indicating that it's a value and a more + // specific one with the column name in it. This assumes that the column + // name is proper for CSS. + label.addStyleName("column-type-value"); + label.addStyleName("column-"+(String)columnId); + return label; + } + return null; + } + } + + /** Table column generator for calculating price column. */ + class PriceColumnGenerator implements Table.ColumnGenerator { + public Component generateCell(Table source, Object itemId, + Object columnId) { + // Retrieve the item. + BeanItem item = (BeanItem) source.getItem(itemId); + + // Retrieves the underlying POJO from the item. + FillUp fillup = (FillUp) item.getBean(); + + // Do the business logic + double price = fillup.price(); + + // Create the generated component for displaying the calcucated + // value. + Label label = new Label(String.format("%1.2f €", new Object[]{new Double(price)})); + + // We set the style here. You can't use a CellStyleGenerator for + // generated columns. + label.addStyleName("column-price"); + return label; + } + } + + /** Table column generator for calculating consumption column. */ + class ConsumptionColumnGenerator implements Table.ColumnGenerator { + /** + * Generates a cell containing value calculated from the item. + */ + public Component generateCell(Table source, Object itemId, Object columnId) { + Indexed indexedSource = (Indexed)source.getContainerDataSource(); + + // Can not calculate consumption for the first item. + if (indexedSource.isFirstId(itemId)) { + Label label = new Label("N/A"); + label.addStyleName("column-consumption"); + return label; + } + + // Index of the previous item. + Object prevItemId = indexedSource.indexOfId(indexedSource.prevItemId(itemId)); + + // Retrieve the POJOs. + FillUp fillup = (FillUp) ((BeanItem) indexedSource.getItem(itemId)).getBean(); + FillUp prev = (FillUp) ((BeanItem) source.getItem(prevItemId)).getBean();; + + // Do the business logic + return generateCell(fillup, prev); + } + + public Component generateCell(FillUp fillup, FillUp prev) { + double consumption = fillup.dailyConsumption(prev); + + // Generate the component for displaying the calculated value. + Label label = new Label(String.format("%3.2f l", new Object[]{new Double(consumption)})); + + // We set the style here. You can't use a CellStyleGenerator for + // generated columns. + label.addStyleName("column-consumption"); + return label; + } + } + + /** Table column generator for calculating daily cost column. */ + class DailyCostColumnGenerator extends ConsumptionColumnGenerator { + public Component generateCell(FillUp fillup, FillUp prev) { + double dailycost = fillup.dailyCost(prev); + + // Generate the component for displaying the calculated value. + Label label = new Label(String.format("%3.2f €", new Object[]{new Double(dailycost)})); + + // We set the style here. You can't use a CellStyleGenerator for + // generated columns. + label.addStyleName("column-dailycost"); + return label; + } + } + + public GeneratedColumnExample() { + final Table table = new Table(); + + // Define table columns. These include also the column for the generated + // column, because we want to set the column label to something + // different than the property ID. + table.addContainerProperty("date", Date.class, null, "Date", null, null); + table.addContainerProperty("quantity", Double.class, null, "Quantity (l)", null, null); + table.addContainerProperty("price", Double.class, null, "Price (€/l)", null, null); + table.addContainerProperty("total", Double.class, null, "Total (€)", null, null); + table.addContainerProperty("consumption", Double.class, null, "Consumption (l/day)", null, null); + table.addContainerProperty("dailycost", Double.class, null, "Daily Cost (€/day)", null, null); + + // Define the generated columns and their generators. + table.addGeneratedColumn("date", new DateColumnGenerator()); + table.addGeneratedColumn("quantity", new ValueColumnGenerator("%.2f l")); + table.addGeneratedColumn("price", new PriceColumnGenerator()); + table.addGeneratedColumn("total", new ValueColumnGenerator("%.2f €")); + table.addGeneratedColumn("consumption", new ConsumptionColumnGenerator()); + table.addGeneratedColumn("dailycost", new DailyCostColumnGenerator()); + + // Create a data source and bind it to the table. + MyContainer data = new MyContainer(new FillUp()); + table.setContainerDataSource(data); + + // Generated columns are automatically placed after property columns, so + // we have to set the order of the columns explicitly. + table.setVisibleColumns(new Object[]{"date","quantity","price","total","consumption", "dailycost"}); + + // Add some data. + data.addItem(new BeanItem(new FillUp(19, 2, 2005, 44.96, 51.21))); + data.addItem(new BeanItem(new FillUp(30, 3, 2005, 44.91, 53.67))); + data.addItem(new BeanItem(new FillUp(20, 4, 2005, 42.96, 49.06))); + data.addItem(new BeanItem(new FillUp(23, 5, 2005, 47.37, 55.28))); + data.addItem(new BeanItem(new FillUp(6, 6, 2005, 35.34, 41.52))); + data.addItem(new BeanItem(new FillUp(30, 6, 2005, 16.07, 20.00))); + data.addItem(new BeanItem(new FillUp(2, 7, 2005, 36.40, 36.19))); + data.addItem(new BeanItem(new FillUp(6, 7, 2005, 39.17, 50.90))); + data.addItem(new BeanItem(new FillUp(27, 7, 2005, 43.43, 53.03))); + data.addItem(new BeanItem(new FillUp(17, 8, 2005, 20, 29.18))); + data.addItem(new BeanItem(new FillUp(30, 8, 2005, 46.06, 59.09))); + data.addItem(new BeanItem(new FillUp(22, 9, 2005, 46.11, 60.36))); + data.addItem(new BeanItem(new FillUp(14, 10, 2005, 41.51, 50.19))); + data.addItem(new BeanItem(new FillUp(12, 11, 2005, 35.24, 40.00))); + data.addItem(new BeanItem(new FillUp(28, 11, 2005, 45.26, 53.27))); + + table.setHeight("100%"); + + ExpandLayout layout = new ExpandLayout(); + layout.addComponent(new Label("Table with column generators that format and calculate cell values.")); + layout.addComponent(table); + layout.addComponent(new Label("Columns displayed in blue are calculated. Others are simply formatted.")); + layout.expand(table); + layout.setSizeFull(); + setCompositionRoot(layout); + setSizeFull(); + } +} diff --git a/src/com/itmill/toolkit/demo/featurebrowser/TableExample.java b/src/com/itmill/toolkit/demo/featurebrowser/TableExample.java index 625e94da68..cb87e799b0 100644 --- a/src/com/itmill/toolkit/demo/featurebrowser/TableExample.java +++ b/src/com/itmill/toolkit/demo/featurebrowser/TableExample.java @@ -15,6 +15,7 @@ import com.itmill.toolkit.ui.Button; import com.itmill.toolkit.ui.CheckBox; import com.itmill.toolkit.ui.CustomComponent; import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.TabSheet; import com.itmill.toolkit.ui.Table; import com.itmill.toolkit.ui.Button.ClickEvent; @@ -50,10 +51,16 @@ public class TableExample extends CustomComponent implements Action.Handler, Button deselect; public TableExample() { + TabSheet root = new TabSheet(); + root.setSizeFull(); + setCompositionRoot(root); + setSizeFull(); + // main layout final OrderedLayout main = new OrderedLayout(); + root.addComponent(main); + main.setCaption("Basic Table"); main.setMargin(true); - setCompositionRoot(main); // "source" table with bells & whistlesenabled source = new Table("All creatures"); @@ -120,6 +127,9 @@ public class TableExample extends CustomComponent implements Action.Handler, b.setImmediate(true); main.addComponent(b); + GeneratedColumnExample gencols = new GeneratedColumnExample(); + gencols.setCaption("Generated Columns"); + root.addComponent(gencols); } // set up the properties (columns)