All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dominokit.domino.ui.datatable.plugins.SelectionPlugin Maven / Gradle / Ivy

There is a newer version: 1.0.139
Show newest version
package org.dominokit.domino.ui.datatable.plugins;

import elemental2.dom.DomGlobal;
import elemental2.dom.HTMLElement;
import elemental2.dom.MouseEvent;
import elemental2.dom.Node;
import jsinterop.base.Js;
import org.dominokit.domino.ui.datatable.*;
import org.dominokit.domino.ui.forms.CheckBox;
import org.dominokit.domino.ui.icons.BaseIcon;
import org.dominokit.domino.ui.icons.Icons;
import org.dominokit.domino.ui.keyboard.KeyboardEvents;
import org.dominokit.domino.ui.style.ColorScheme;
import org.dominokit.domino.ui.style.Style;
import org.dominokit.domino.ui.utils.Selectable;
import org.dominokit.domino.ui.utils.TextNode;
import org.jboss.elemento.IsElement;

import java.util.stream.Collectors;

import static java.util.Objects.nonNull;
import static java.util.Objects.requireNonNull;

public class SelectionPlugin implements DataTablePlugin {

    private ColorScheme colorScheme;
    private Selectable selectedRow;
    private HTMLElement singleSelectIndicator = Icons.ALL.check().element();
    private SelectionCondition selectionCondition = (table, row) -> true;
    private TableRow lastSelected;

    public SelectionPlugin() {
    }

    public SelectionPlugin(ColorScheme colorScheme) {
        this.colorScheme = colorScheme;
    }

    public SelectionPlugin(ColorScheme colorScheme, HTMLElement singleSelectIndicator) {
        this(colorScheme);
        this.singleSelectIndicator = singleSelectIndicator;
    }

    public SelectionPlugin(ColorScheme colorScheme, IsElement singleSelectIndicator) {
        this(colorScheme, singleSelectIndicator.element());
    }

    @Override
    public void onBeforeAddHeaders(DataTable dataTable) {
        dataTable.getTableConfig().insertColumnFirst(ColumnConfig.create("data-table-select-cm")
                .setSortable(false)
                .setWidth(dataTable.getTableConfig().isMultiSelect() ? "35px" : "40px")
                .styleCell(element -> Style.of(element)
                                           .setMaxWidth(dataTable.getTableConfig().isMultiSelect() ? "35px" : "40px")
                                           .setWidth(dataTable.getTableConfig().isMultiSelect() ? "35px" : "40px")
                )
                .setTooltipNode(DomGlobal.document.createTextNode("Select"))
                .setHeaderElement(columnTitle -> {
                    if (dataTable.getTableConfig().isMultiSelect()) {
                        return createMultiSelectHeader(dataTable);
                    } else {
                        return createSingleSelectHeader();
                    }
                })
                .setCellRenderer(cell -> {
                    if (selectionCondition.isAllowSelection(dataTable, cell.getTableRow())) {
                        if (dataTable.getTableConfig().isMultiSelect()) {
                            return createMultiSelectCell(dataTable, cell);
                        } else {
                            return createSingleSelectCell(dataTable, cell);
                        }
                    } else {
                        return TextNode.empty();
                    }

                }));
    }

    private Node createSingleSelectHeader() {
        return singleSelectIndicator.cloneNode(true);
    }

    private Node createSingleSelectCell(DataTable dataTable, CellRenderer.CellInfo cell) {
        HTMLElement clonedIndicator = Js.uncheckedCast(singleSelectIndicator.cloneNode(true));
        cell.getTableRow().element().addEventListener("click", evt -> {
            if (selectionCondition.isAllowSelection(dataTable, cell.getTableRow())) {
                if (cell.getTableRow().isSelected()) {
                    cell.getTableRow().deselect();
                } else {
                    cell.getTableRow().select();
                }
                dataTable.onSelectionChange(cell.getTableRow());
            }
        });
        cell.getTableRow().addSelectionHandler(selectable -> {
            if (selectionCondition.isAllowSelection(dataTable, cell.getTableRow())) {
                if (selectable.isSelected()) {
                    if (nonNull(selectedRow)) {
                        selectedRow.deselect();
                    }
                    Style.of(clonedIndicator).setDisplay("inline-block");
                    if (nonNull(colorScheme)) {
                        Style.of(((TableRow) selectable).element()).add(colorScheme.lighten_5().getBackground());
                    }
                    selectedRow = selectable;
                } else {
                    Style.of(clonedIndicator).setDisplay("none");
                    if (nonNull(colorScheme)) {
                        Style.of(((TableRow) selectable).element()).remove(colorScheme.lighten_5().getBackground());
                    }
                    selectedRow = null;
                }
            }
        });
        Style.of(clonedIndicator).setDisplay("none");
        return clonedIndicator;
    }

    private Node createMultiSelectCell(DataTable dataTable, CellRenderer.CellInfo cell) {
        CheckBox checkBox = createCheckBox();

        TableRow tableRow = cell.getTableRow();
        tableRow.addSelectionHandler(selectable -> {
            if (selectionCondition.isAllowSelection(dataTable, tableRow)) {
                if (selectable.isSelected()) {
                    checkBox.check(true);
                    if (nonNull(colorScheme)) {
                        Style.of(((TableRow) selectable).element()).add(colorScheme.lighten_5().getBackground());
                    }
                } else {
                    checkBox.uncheck(true);
                    if (nonNull(colorScheme)) {
                        Style.of(((TableRow) selectable).element()).remove(colorScheme.lighten_5().getBackground());
                    }
                }
            }
        });

        checkBox.addClickListener(evt -> {
            MouseEvent mouseEvent = Js.cast(evt);
            if (mouseEvent.shiftKey) {
                int startIndex = getStartSelectionIndex(dataTable);
                int endIndex = tableRow.getIndex();
                int increment = startIndex < endIndex ? 1 : -1;
                for (int i = startIndex; startIndex < endIndex ? i <= endIndex : i >= endIndex; i += increment) {
                    TableRow row = dataTable.getItems()
                            .get(i);
                    selectRow(dataTable, row);
                }
            } else {
                this.lastSelected = tableRow;
            }
        });
        checkBox.addChangeHandler(checked -> {
            if (selectionCondition.isAllowSelection(dataTable, tableRow)) {
                if (checked) {
                    selectRow(dataTable, tableRow);
                } else {
                    tableRow.deselect();
                    if (nonNull(colorScheme)) {
                        Style.of(tableRow.element()).remove(colorScheme.lighten_5().getBackground());
                    }
                    dataTable.onSelectionChange(tableRow);
                }
            }
        });
        return checkBox.element();
    }

    private int getStartSelectionIndex(DataTable dataTable) {
        if (nonNull(lastSelected)) {
            return lastSelected.getIndex();
        } else {
            if (dataTable.getSelectedItems().isEmpty()) {
                return 0;
            } else {
                return dataTable.getSelectedItems().get(0).getIndex();
            }
        }
    }

    private void selectRow(DataTable dataTable, TableRow tableRow) {
        tableRow.select();
        if (nonNull(colorScheme)) {
            Style.of(tableRow.element()).add(colorScheme.lighten_5().getBackground());
        }
        dataTable.onSelectionChange(tableRow);
    }

    private void deselectRow(DataTable dataTable, TableRow tableRow) {
        tableRow.deselect();
        if (nonNull(colorScheme)) {
            Style.of(tableRow.element()).remove(colorScheme.lighten_5().getBackground());
        }
        dataTable.onSelectionChange(tableRow);
    }

    private Node createMultiSelectHeader(DataTable dataTable) {
        CheckBox checkBox = createCheckBox();
        checkBox.addChangeHandler(checked -> {
            if (checked) {
                dataTable.selectAll(selectionCondition);
            } else {
                dataTable.deselectAll(selectionCondition);
            }
        });

        dataTable.addSelectionListener((selectedRows, selectedRecords) -> {
            if (selectedRows.size() != dataTable.getItems()
                    .stream()
                    .filter(tableRow -> selectionCondition.isAllowSelection(dataTable, tableRow))
                    .count()) {
                checkBox.uncheck(true);
            } else {
                checkBox.check(true);
            }
        });
        return checkBox.element();
    }

    public SelectionPlugin setSingleSelectIcon(BaseIcon singleSelectIcon) {
        return this;
    }

    private CheckBox createCheckBox() {
        CheckBox checkBox = CheckBox.create();
        if (nonNull(colorScheme)) {
            checkBox.setColor(colorScheme.color());
        }
        Style.of(checkBox).add(DataTableStyles.SELECT_CHECKBOX);
        return checkBox;
    }

    public SelectionPlugin setSelectionCondition(SelectionCondition selectionCondition) {
        if (nonNull(selectionCondition)) {
            this.selectionCondition = selectionCondition;
        }
        return this;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy