]> source.dussan.org Git - vaadin-framework.git/commitdiff
Generated column example for #1836.
authorMarko Grönroos <magi@iki.fi>
Thu, 7 Aug 2008 17:21:02 +0000 (17:21 +0000)
committerMarko Grönroos <magi@iki.fi>
Thu, 7 Aug 2008 17:21:02 +0000 (17:21 +0000)
svn changeset:5157/svn branch:trunk

WebContent/ITMILL/themes/example/styles.css
src/com/itmill/toolkit/demo/featurebrowser/GeneratedColumnExample.java [new file with mode: 0644]
src/com/itmill/toolkit/demo/featurebrowser/TableExample.java

index d923e575b1a5fd45db8aaa57247cd1ff1056673d..b68c9cc2bbf622915f12ed0a19dd7e6f13f1bcba 100644 (file)
@@ -6,6 +6,9 @@
        overflow:hidden;
 }
 
+/******************************************************************************
+ * For FormExample.java
+ ******************************************************************************/
 .i-form {
        border: 1px solid;
        margin: 10px;
 .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 (file)
index 0000000..26fd276
--- /dev/null
@@ -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<BeanItem> items;
+        Object           itemtemplate;
+        
+        public MyContainer(Object itemtemplate) {
+            this.itemtemplate = itemtemplate;
+            items = new Vector<BeanItem>(); // 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(); i++)
+                ids.add(Integer.valueOf(i));
+            return ids;
+        }
+
+        public Class getType(Object propertyId) {
+            return BeanItem.class;
+        }
+
+        public boolean removeAllItems() throws UnsupportedOperationException {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean removeContainerProperty(Object propertyId)
+                throws UnsupportedOperationException {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean removeItem(Object itemId)
+                throws UnsupportedOperationException {
+            throw new UnsupportedOperationException();
+        }
+
+        public int size() {
+            return items.size();
+        }
+
+        public Object addItemAt(int index) throws UnsupportedOperationException {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public Item addItemAt(int index, Object newItemId)
+                throws UnsupportedOperationException {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public Object getIdByIndex(int index) {
+            return Integer.valueOf(index);
+        }
+
+        public int indexOfId(Object itemId) {
+            return ((Integer)itemId).intValue();
+        }
+
+        public Object addItemAfter(Object previousItemId)
+                throws UnsupportedOperationException {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public Item addItemAfter(Object previousItemId, Object newItemId)
+                throws UnsupportedOperationException {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public Object firstItemId() {
+            return new Integer(0);
+        }
+
+        public boolean isFirstId(Object itemId) {
+            return ((Integer)itemId).intValue() == 0;
+        }
+
+        public boolean isLastId(Object itemId) {
+            return ((Integer)itemId).intValue() == (items.size()-1);
+        }
+
+        public Object lastItemId() {
+            return items.size()-1;
+        }
+
+        public Object nextItemId(Object itemId) {
+            int pos = indexOfId(itemId);
+            if (pos >= 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();
+    }
+}
index 625e94da68d0103a3f4e5492e390c033ed4ccfc0..cb87e799b07e89fe9312fe2050e99002f83ce2b5 100644 (file)
@@ -15,6 +15,7 @@ import com.itmill.toolkit.ui.Button;
 import com.itmill.toolkit.ui.CheckBox;\r
 import com.itmill.toolkit.ui.CustomComponent;\r
 import com.itmill.toolkit.ui.OrderedLayout;\r
+import com.itmill.toolkit.ui.TabSheet;\r
 import com.itmill.toolkit.ui.Table;\r
 import com.itmill.toolkit.ui.Button.ClickEvent;\r
 \r
@@ -50,10 +51,16 @@ public class TableExample extends CustomComponent implements Action.Handler,
     Button deselect;\r
 \r
     public TableExample() {\r
+        TabSheet root = new TabSheet();\r
+        root.setSizeFull();\r
+        setCompositionRoot(root);\r
+        setSizeFull();\r
+        \r
         // main layout\r
         final OrderedLayout main = new OrderedLayout();\r
+        root.addComponent(main);\r
+        main.setCaption("Basic Table");\r
         main.setMargin(true);\r
-        setCompositionRoot(main);\r
 \r
         // "source" table with bells & whistlesenabled\r
         source = new Table("All creatures");\r
@@ -120,6 +127,9 @@ public class TableExample extends CustomComponent implements Action.Handler,
         b.setImmediate(true);\r
         main.addComponent(b);\r
 \r
+        GeneratedColumnExample gencols = new GeneratedColumnExample();\r
+        gencols.setCaption("Generated Columns");\r
+        root.addComponent(gencols);\r
     }\r
 \r
     // set up the properties (columns)\r