package au.com.vaadinutils.fields; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import com.vaadin.data.Property; import com.vaadin.data.Validator.InvalidValueException; import com.vaadin.server.ErrorMessage; import com.vaadin.ui.CheckBox; import com.vaadin.ui.Table; public class TableCheckBoxSingleSelect extends Table { public static final String TABLE_CHECK_BOX_SELECT = "TableCheckBoxSelect"; private static final long serialVersionUID = -7559267854874304189L; private Set<ValueChangeListener> valueChangeListeners = new HashSet<ValueChangeListener>(); protected int containerSize = 0; private Object selectedId; public TableCheckBoxSingleSelect() { init(); setImmediate(true); } /** * call this method after adding your custom fields */ public void init() { this.addGeneratedColumn(TABLE_CHECK_BOX_SELECT, getGenerator()); super.setMultiSelect(false); super.setSelectable(false); } private Property.ValueChangeEvent getValueChangeEvent() { Property.ValueChangeEvent event = new Property.ValueChangeEvent() { /** * */ private static final long serialVersionUID = 3393822114324878273L; @SuppressWarnings("rawtypes") @Override public Property getProperty() { return new Property() { private static final long serialVersionUID = 8430716281101427107L; @Override public Object getValue() { return getSelectedItems(); } @Override public void setValue(Object newValue) throws ReadOnlyException { throw new RuntimeException("Not implemented"); } @Override public Class getType() { throw new RuntimeException("Not implemented"); } @Override public boolean isReadOnly() { return true; } @Override public void setReadOnly(boolean newStatus) { throw new RuntimeException("Not implemented"); } }; } }; return event; } public void setColumnHeaders(String... columnHeaders) { Set<String> cols = new LinkedHashSet<String>(); for (String col : columnHeaders) { cols.add(col); } cols.add(""); super.setColumnHeaders(cols.toArray(new String[] {})); } @Override public void setVisibleColumns(Object... visibleColumns) { if (visibleColumns.length > 0) { Set<Object> cols = new LinkedHashSet<Object>(); for (Object col : visibleColumns) { cols.add(col); } cols.add(TABLE_CHECK_BOX_SELECT); super.setVisibleColumns(cols.toArray()); } else { // during initialisation it comes through here empty and if we add // ours in npe's out super.setVisibleColumns(visibleColumns); } } /** * use setSelectedValue instead, this method gets called before * initialization */ @Deprecated public void setValue(Object value) { super.setValue(value); } public void setSelectedValue(Object value) { selectedId = value; this.refreshRowCache(); } @Override public boolean isMultiSelect() { return false; } @Override public void setSelectable(boolean s) { throw new RuntimeException("Dont call this!"); } @Override public boolean isSelectable() { return false; } public Object getSelectedItems() { Set<Object> tmp = new HashSet<>(); if (selectedId != null) { tmp.add(selectedId); } return tmp; } @Override public void addValueChangeListener(ValueChangeListener listener) { valueChangeListeners.add(listener); } /** * call getSelectedItems instead, can't use this method as Vaadins table * calls back to this method on a paint cycle, showing some items as * selected */ @Deprecated @Override public Object getValue() { return null; } private CheckBox selectedCheckBox; protected ColumnGenerator getGenerator() { return new ColumnGenerator() { private static final long serialVersionUID = -6659059346271729122L; @Override public Object generateCell(final Table source, final Object itemId, Object columnId) { final CheckBox checkbox = new CheckBox(); checkbox.setWidth("25"); checkbox.setHeight("20"); checkbox.setValue(itemId == selectedId); if (itemId == selectedId) { selectedCheckBox = checkbox; } checkbox.addValueChangeListener(new ValueChangeListener() { private static final long serialVersionUID = 9170497247408214336L; @Override public void valueChange(Property.ValueChangeEvent event) { if (selectedCheckBox != null) { selectedCheckBox.setValue(false); } if ((Boolean) event.getProperty().getValue() == true) { selectedId = itemId; selectedCheckBox = checkbox; } else { selectedCheckBox = null; selectedId = null; } notifyValueChange(); } }); checkbox.setImmediate(true); return checkbox; } }; } protected void notifyValueChange() { for (ValueChangeListener listener : valueChangeListeners) { listener.valueChange(getValueChangeEvent()); } this.validateField(); } private boolean validateField() { boolean valid = false; try { setComponentError(null); validate(); valid = true; } catch (final InvalidValueException e) { setComponentError(new ErrorMessage() { private static final long serialVersionUID = -2976235476811651668L; @Override public String getFormattedHtmlMessage() { return e.getHtmlMessage(); } @Override public ErrorLevel getErrorLevel() { return ErrorLevel.ERROR; } }); } return valid; } public void deselectAll() { if (selectedCheckBox != null) { selectedCheckBox.setValue(false); } selectedCheckBox = null; selectedId = null; notifyValueChange(); } // public void addSelectionListener(SelectionListener listener) // { // markedIds.addSelectionListener(listener); // // } }