--- /dev/null
+package com.vaadin.tests.tickets;\r
+\r
+import java.util.Calendar;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+import java.util.Random;\r
+import java.util.Set;\r
+\r
+import com.vaadin.Application;\r
+import com.vaadin.data.Container;\r
+import com.vaadin.data.Validator;\r
+import com.vaadin.data.util.BeanItemContainer;\r
+import com.vaadin.ui.ComboBox;\r
+import com.vaadin.ui.Component;\r
+import com.vaadin.ui.DateField;\r
+import com.vaadin.ui.DefaultFieldFactory;\r
+import com.vaadin.ui.Field;\r
+import com.vaadin.ui.FormLayout;\r
+import com.vaadin.ui.Layout;\r
+import com.vaadin.ui.ListSelect;\r
+import com.vaadin.ui.Panel;\r
+import com.vaadin.ui.Table;\r
+import com.vaadin.ui.TextField;\r
+import com.vaadin.ui.VerticalLayout;\r
+import com.vaadin.ui.Window;\r
+\r
+/**\r
+ * Table layout is very slow in Firefox 3.0.10 when the table contains\r
+ * components.\r
+ * \r
+ * This is adapted from the HbnContainer example application WorkoutLog.\r
+ * \r
+ * Other browsers are much faster.\r
+ */\r
+public class Ticket2998 extends Application {\r
+ private Table table;\r
+ private WorkoutEditor editor = new WorkoutEditor(this);\r
+ private VerticalLayout mainLayout;\r
+\r
+ public class Workout {\r
+ private Long id;\r
+ private Date date = new Date();\r
+ private String title = " -- new workout -- ";\r
+ private float kilometers;\r
+\r
+ private String trainingType;\r
+\r
+ private Set<String> secondaryTypes;\r
+\r
+ public Workout() {\r
+ }\r
+\r
+ public Long getId() {\r
+ return id;\r
+ }\r
+\r
+ public Date getDate() {\r
+ return date;\r
+ }\r
+\r
+ public void setDate(Date date) {\r
+ this.date = date;\r
+ }\r
+\r
+ public String getTitle() {\r
+ return title;\r
+ }\r
+\r
+ public void setTitle(String title) {\r
+ this.title = title;\r
+ }\r
+\r
+ public float getKilometers() {\r
+ return kilometers;\r
+ }\r
+\r
+ public void setKilometers(float kilometers) {\r
+ this.kilometers = kilometers;\r
+ }\r
+\r
+ public String getTrainingType() {\r
+ return trainingType;\r
+ }\r
+\r
+ public void setTrainingType(String trainingType) {\r
+ this.trainingType = trainingType;\r
+ }\r
+\r
+ public void setSecondaryTypes(Set<String> secondaryTypes) {\r
+ this.secondaryTypes = secondaryTypes;\r
+ }\r
+\r
+ public Set<String> getSecondaryTypes() {\r
+ return secondaryTypes;\r
+ }\r
+\r
+ }\r
+\r
+ public class WorkoutEditor extends Window {\r
+\r
+ private DateField date = new DateField("Date");\r
+ private TextField kilomiters = new TextField("Kilometers");\r
+ private TextField title = new TextField("Title/note");\r
+\r
+ private Workout run;\r
+ private Ticket2998 workoutLog;\r
+\r
+ public WorkoutEditor(Ticket2998 app) {\r
+ super("Edit workout");\r
+ workoutLog = app;\r
+ Layout main = new VerticalLayout();\r
+ setLayout(main);\r
+ main.setSizeUndefined();\r
+ main.setStyleName(Panel.STYLE_LIGHT);\r
+\r
+ FormLayout form = new FormLayout();\r
+ form.setSizeUndefined();\r
+ date.setResolution(DateField.RESOLUTION_MIN);\r
+ form.addComponent(date);\r
+ form.addComponent(kilomiters);\r
+ form.addComponent(title);\r
+ main.addComponent(form);\r
+\r
+ }\r
+\r
+ public void loadRun(Workout run) {\r
+ if (run == null) {\r
+ close();\r
+ } else {\r
+ date.setValue(run.getDate());\r
+ kilomiters.setValue(run.getKilometers());\r
+ title.setValue(run.getTitle());\r
+ if (getParent() == null) {\r
+ workoutLog.getMainWindow().addWindow(this);\r
+ }\r
+ kilomiters.focus();\r
+ this.run = run;\r
+ }\r
+ }\r
+ }\r
+\r
+ public class MyFieldFactory extends DefaultFieldFactory {\r
+\r
+ private BeanItemContainer<String> trainingTypes;\r
+\r
+ public MyFieldFactory(Ticket2998 app) {\r
+ trainingTypes = new BeanItemContainer<String>(String.class);\r
+ }\r
+\r
+ @Override\r
+ public Field createField(Container container, Object itemId,\r
+ Object propertyId, Component uiContext) {\r
+\r
+ /*\r
+ * trainingType is manyToOne relation, give it a combobox\r
+ */\r
+ if (propertyId.equals("trainingType")) {\r
+ return getTrainingTypeComboboxFor(itemId);\r
+ }\r
+\r
+ /*\r
+ * Secondarytypes is manyToMany relation, give it a multiselect list\r
+ */\r
+ if (propertyId.equals("secondaryTypes")) {\r
+ return getSecondaryTypesList(itemId);\r
+ }\r
+\r
+ final Field f = super.createField(container, itemId, propertyId,\r
+ uiContext);\r
+ if (f != null) {\r
+ if (f instanceof TextField) {\r
+ TextField tf = (TextField) f;\r
+ tf.setWidth("100%");\r
+ }\r
+ if (propertyId.equals("kilometers")) {\r
+ f.setWidth("4em");\r
+ f.addValidator(new Validator() {\r
+ public boolean isValid(Object value) {\r
+ try {\r
+ @SuppressWarnings("unused")\r
+ float f = Float.parseFloat((String) value);\r
+ return true;\r
+ } catch (Exception e) {\r
+ f.getWindow().showNotification(\r
+ "Bad number value");\r
+ f.setValue(0);\r
+ return false;\r
+ }\r
+ }\r
+\r
+ public void validate(Object value)\r
+ throws InvalidValueException {\r
+ // TODO Auto-generated method stub\r
+\r
+ }\r
+ });\r
+ }\r
+ if (propertyId.equals("date")) {\r
+ ((DateField) f).setResolution(DateField.RESOLUTION_MIN);\r
+ }\r
+ }\r
+ return f;\r
+\r
+ }\r
+\r
+ private Map<Object, ListSelect> workoutIdToList = new HashMap<Object, ListSelect>();\r
+\r
+ private Field getSecondaryTypesList(Object itemId) {\r
+ ListSelect list = workoutIdToList.get(itemId);\r
+ if (list == null) {\r
+ list = new ListSelect();\r
+ list.setMultiSelect(true);\r
+ list.addItem("Item1");\r
+ list.addItem("Item2");\r
+ list.addItem("Item3");\r
+ list.addItem("Item4");\r
+ list.addItem("Item5");\r
+ // list.setContainerDataSource(trainingTypes);\r
+ list.setRows(4);\r
+ workoutIdToList.put(itemId, list);\r
+ }\r
+ return list;\r
+ }\r
+\r
+ private Map<Object, ComboBox> workoutIdToCombobox = new HashMap<Object, ComboBox>();\r
+\r
+ private Field getTrainingTypeComboboxFor(Object itemId) {\r
+ ComboBox cb = workoutIdToCombobox.get(itemId);\r
+ if (cb == null) {\r
+ final ComboBox cb2 = new ComboBox();\r
+ cb2.addItem("value1");\r
+ cb2.addItem("value2");\r
+ cb2.addItem("value3");\r
+ cb2.addItem("value4");\r
+ cb2.setNewItemsAllowed(true);\r
+\r
+ workoutIdToCombobox.put(itemId, cb2);\r
+ cb = cb2;\r
+ }\r
+ return cb;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void init() {\r
+ buildView();\r
+ setTheme("reindeer");\r
+ }\r
+\r
+ /**\r
+ * Builds a simple view for application with Table and a row of buttons\r
+ * below it.\r
+ */\r
+ private void buildView() {\r
+\r
+ final Window w = new Window("Workout Log");\r
+\r
+ // set theme and some layout stuff\r
+ setMainWindow(w);\r
+ w.getLayout().setSizeFull();\r
+ w.getLayout().setMargin(false);\r
+\r
+ Panel p = new Panel("Workout Log");\r
+ p.setStyleName(Panel.STYLE_LIGHT);\r
+ w.addComponent(p);\r
+ mainLayout = new VerticalLayout();\r
+ p.setLayout(mainLayout);\r
+\r
+ populateAndConfigureTable();\r
+\r
+ mainLayout.addComponent(table);\r
+\r
+ // make table consume all extra space\r
+ p.setSizeFull();\r
+ mainLayout.setSizeFull();\r
+ mainLayout.setExpandRatio(table, 1);\r
+ table.setSizeFull();\r
+ }\r
+\r
+ protected void populateAndConfigureTable() {\r
+ table = new Table();\r
+\r
+ table.setWidth("100%");\r
+ table.setSelectable(true);\r
+ table.setImmediate(true);\r
+ table.setColumnCollapsingAllowed(true);\r
+ table.setColumnWidth("date", 200);\r
+ table.setColumnWidth("kilometers", 100);\r
+ // table.addListener(this);\r
+ table.setTableFieldFactory(new MyFieldFactory(this));\r
+\r
+ loadWorkouts();\r
+\r
+ table.setEditable(true);\r
+ }\r
+\r
+ /**\r
+ * Loads container to Table\r
+ */\r
+ protected void loadWorkouts() {\r
+ final BeanItemContainer<Workout> cont;\r
+ // Use plain HbnContainer\r
+ cont = new BeanItemContainer<Workout>(Workout.class);\r
+ table.setContainerDataSource(cont);\r
+\r
+ // insert some sample data\r
+ Calendar c = Calendar.getInstance();\r
+ c.set(Calendar.MILLISECOND, 0);\r
+ c.set(Calendar.SECOND, 0);\r
+ c.set(Calendar.MINUTE, 0);\r
+\r
+ String[] titles = new String[] { "A short easy one", "intervals",\r
+ "very long", "just shaking legs after work",\r
+ "long one with Paul", "test run" };\r
+\r
+ c.add(Calendar.DATE, -1000);\r
+\r
+ Random rnd = new Random();\r
+\r
+ Workout r;\r
+\r
+ for (int i = 0; i < 1000; i++) {\r
+ r = new Workout();\r
+ c.set(Calendar.HOUR_OF_DAY,\r
+ 12 + (rnd.nextInt(11) - rnd.nextInt(11)));\r
+ r.setDate(c.getTime());\r
+ r.setTitle(titles[rnd.nextInt(titles.length)]);\r
+ r.setKilometers(Math.round(rnd.nextFloat() * 30));\r
+ r.setTrainingType("tt");\r
+ c.add(Calendar.DATE, 1);\r
+ cont.addBean(r);\r
+ }\r
+ }\r
+\r
+}\r