package com.constellio.app.ui.framework.components.table; import com.constellio.app.ui.framework.buttons.SelectDeselectAllButton; import com.constellio.app.ui.framework.containers.ContainerAdapter; import com.vaadin.data.Container; import com.vaadin.data.Property; import com.vaadin.data.util.AbstractProperty; import com.vaadin.data.util.ObjectProperty; import com.vaadin.ui.Alignment; import com.vaadin.ui.CheckBox; import com.vaadin.ui.Table; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.themes.ValoTheme; import java.util.*; import static com.constellio.app.ui.i18n.i18n.$; public abstract class SelectionTableAdapter extends VerticalLayout { public static final String SELECT_PROPERTY_ID = "select"; protected SelectDeselectAllButton toggleButton; protected ContainerAdapter<?> dataSourceAdapter; protected Map<Object, Property<?>> itemSelectProperties = new HashMap<>(); protected Table table; public SelectionTableAdapter() { this(null); } public SelectionTableAdapter(Table table) { setSpacing(true); setTable(table); } public Table getTable() { return table; } @SuppressWarnings({ "unchecked", "rawtypes" }) public void setTable(Table table) { this.table = table; if (table != null) { removeAllComponents(); boolean allItemsSelected = isAllItemsSelected(); toggleButton = new SelectDeselectAllButton($("selectAll"), $("deselectAll"), !allItemsSelected) { @Override protected void onSelectAll(ClickEvent event) { SelectionTableAdapter.this.selectAll(); updateVisibleCheckBoxes(); } @Override protected void onDeselectAll(ClickEvent event) { SelectionTableAdapter.this.deselectAll(); updateVisibleCheckBoxes(); } }; toggleButton.addStyleName(ValoTheme.BUTTON_BORDERLESS); toggleButton.addStyleName(ValoTheme.BUTTON_LINK); if (table.size() == 0) { toggleButton.setVisible(false); } Container tableDataSource = table.getContainerDataSource(); dataSourceAdapter = new ContainerAdapter(tableDataSource) { @Override public Collection<?> getContainerPropertyIds() { List<Object> propertyIds = new ArrayList<>(super.getContainerPropertyIds()); propertyIds.add(0, SELECT_PROPERTY_ID); return propertyIds; } @Override public Property getContainerProperty(final Object itemId, Object propertyId) { Property<?> property; if (SELECT_PROPERTY_ID.equals(propertyId)) { property = itemSelectProperties.get(itemId); if (property == null) { Property<?> selectProperty = itemSelectProperties.get(itemId); selectProperty = new AbstractProperty<Boolean>() { @Override public Boolean getValue() { return itemId != null ? isSelected(itemId) : null; } @Override public void setValue(Boolean newValue) throws com.vaadin.data.Property.ReadOnlyException { if (itemId != null) { boolean selected = Boolean.TRUE.equals(newValue); setSelected(itemId, selected); } } @Override public Class<? extends Boolean> getType() { return Boolean.class; } }; CheckBox checkBox = new SelectionCheckBox(); checkBox.setPropertyDataSource(selectProperty); property = new ObjectProperty<CheckBox>(checkBox); itemSelectProperties.put(itemId, property); } } else { property = super.getContainerProperty(itemId, propertyId); } return property; } @Override public Class getType(Object propertyId) { Class<?> propertyType; if (SELECT_PROPERTY_ID.equals(propertyId)) { propertyType = CheckBox.class; } else { propertyType = super.getType(propertyId); } return propertyType; } }; List<Object> oldVisibleColumns = Arrays.asList(table.getVisibleColumns()); table.setContainerDataSource(dataSourceAdapter); table.setColumnHeader(SELECT_PROPERTY_ID, ""); table.setColumnWidth(SELECT_PROPERTY_ID, 44); table.setColumnCollapsible(SELECT_PROPERTY_ID, false); List<Object> newVisibleColumns = new ArrayList<>(oldVisibleColumns); if (!newVisibleColumns.contains(SELECT_PROPERTY_ID)) { newVisibleColumns.add(0, SELECT_PROPERTY_ID); } table.setVisibleColumns(newVisibleColumns.toArray(new Object[0])); setWidth("100%"); addComponents(toggleButton, table); setExpandRatio(table, 1); setComponentAlignment(toggleButton, Alignment.TOP_LEFT); } } protected void updateVisibleCheckBoxes() { for (Object visibleItemId : SelectionTableAdapter.this.table.getVisibleItemIds()) { setChecked(visibleItemId, isSelected(visibleItemId)); } } public void refresh() { dataSourceAdapter.fireItemSetChange(); } public SelectDeselectAllButton getToggleButton() { return toggleButton; } public ContainerAdapter<?> getContainerAdapter() { return dataSourceAdapter; } private SelectionCheckBox getCheckBox(Object itemId) { return (SelectionCheckBox) dataSourceAdapter.getContainerProperty(itemId, SELECT_PROPERTY_ID).getValue(); } protected boolean isChecked(Object itemId) { SelectionCheckBox checkBox = getCheckBox(itemId); return checkBox != null ? checkBox.getInternalValue() : null; } protected void setChecked(Object itemId, boolean checked) { SelectionCheckBox checkBox = getCheckBox(itemId); if (checkBox != null) { checkBox.setInternalValue(checked); } adjustSelectAllButton(checked); } // public void adjustSelectAllButton() { // adjustSelectAllButton(toggleButton.isSelectAllMode()); // } public void adjustSelectAllButton(boolean checked) { // boolean selectAllMode = toggleButton.isSelectAllMode(); // if (checked && selectAllMode && isAllItemsSelected()) { // toggleButton.setSelectAllMode(false); // } else if (!checked && !selectAllMode && isAllItemsUnselected()) { // toggleButton.setSelectAllMode(true); // } } protected boolean isAllItemsSelectedByItemId() { boolean allItemsSelected; if (table != null) { Collection<?> itemIds = table.getItemIds(); allItemsSelected = !itemIds.isEmpty(); for (Object itemId : itemIds) { if (!isSelected(itemId)) { allItemsSelected = false; break; } } } else { allItemsSelected = false; } return allItemsSelected; } protected boolean isAllItemsDeselectedByItemId() { boolean allItemsUnselected; if (table != null) { Collection<?> itemIds = table.getItemIds(); allItemsUnselected = !itemIds.isEmpty(); for (Object itemId : itemIds) { if (isSelected(itemId)) { allItemsUnselected = false; break; } } } else { allItemsUnselected = false; } return allItemsUnselected; } public void selectAllByItemId() { if (table != null) { for (Object itemId : table.getItemIds()) { CheckBox checkBox = getCheckBox(itemId); if (checkBox != null && !Boolean.TRUE.equals(checkBox.getValue())) { checkBox.setValue(true); } } } } public void deselectAllByItemId() { if (table != null) { for (Object itemId : table.getItemIds()) { CheckBox checkBox = getCheckBox(itemId); if (checkBox != null && !Boolean.FALSE.equals(checkBox.getValue())) { checkBox.setValue(false); } } } } public abstract void selectAll(); public abstract void deselectAll(); public abstract boolean isAllItemsSelected(); public abstract boolean isAllItemsDeselected(); public abstract boolean isSelected(Object itemId); public abstract void setSelected(Object itemId, boolean selected); private static class SelectionCheckBox extends CheckBox { @Override public Boolean getInternalValue() { return super.getInternalValue(); } @Override public void setInternalValue(Boolean newValue) { super.setInternalValue(newValue); } } public void refreshUI() { dataSourceAdapter.fireItemSetChange(); } }