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

com.vaadin.v7.client.connectors.MultiSelectionModelConnector Maven / Gradle / Ivy

There is a newer version: 8.27.3
Show newest version
/*
 * Copyright (C) 2000-2024 Vaadin Ltd
 *
 * This program is available under Vaadin Commercial License and Service Terms.
 *
 * See  for the full
 * license.
 */
package com.vaadin.v7.client.connectors;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

import com.google.gwt.user.client.ui.CheckBox;
import com.google.web.bindery.event.shared.HandlerRegistration;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.data.DataSource;
import com.vaadin.client.data.DataSource.RowHandle;
import com.vaadin.shared.Range;
import com.vaadin.shared.ui.Connect;
import com.vaadin.v7.client.renderers.ComplexRenderer;
import com.vaadin.v7.client.renderers.Renderer;
import com.vaadin.v7.client.widget.grid.DataAvailableEvent;
import com.vaadin.v7.client.widget.grid.DataAvailableHandler;
import com.vaadin.v7.client.widget.grid.events.SelectAllEvent;
import com.vaadin.v7.client.widget.grid.events.SelectAllHandler;
import com.vaadin.v7.client.widget.grid.selection.HasUserSelectionAllowed;
import com.vaadin.v7.client.widget.grid.selection.MultiSelectionRenderer;
import com.vaadin.v7.client.widget.grid.selection.SelectionModel;
import com.vaadin.v7.client.widget.grid.selection.SelectionModel.Multi;
import com.vaadin.v7.client.widget.grid.selection.SpaceSelectHandler;
import com.vaadin.v7.client.widgets.Grid;
import com.vaadin.v7.client.widgets.Grid.Column;
import com.vaadin.v7.client.widgets.Grid.HeaderCell;
import com.vaadin.v7.client.widgets.Grid.SelectionColumn;
import com.vaadin.v7.shared.ui.grid.GridState;
import com.vaadin.v7.shared.ui.grid.selection.MultiSelectionModelServerRpc;
import com.vaadin.v7.shared.ui.grid.selection.MultiSelectionModelState;
import com.vaadin.v7.ui.Grid.MultiSelectionModel;

import elemental.json.JsonObject;

/**
 * Connector for server-side {@link MultiSelectionModel}.
 *
 * @since 7.6
 * @author Vaadin Ltd
 */
@Connect(MultiSelectionModel.class)
public class MultiSelectionModelConnector extends
        AbstractSelectionModelConnector> {

    private Multi selectionModel = createSelectionModel();
    private SpaceSelectHandler spaceHandler;
    private HandlerRegistration readOnlyStateChangeHandlerRegistration;

    @Override
    protected void extend(ServerConnector target) {
        getGrid().setSelectionModel(selectionModel);
        spaceHandler = new SpaceSelectHandler(getGrid());
        readOnlyStateChangeHandlerRegistration = target.addStateChangeHandler(
                "readOnly", e -> updateUserSelectionAllowed());
    }

    @Override
    public void onUnregister() {
        spaceHandler.removeHandler();
        readOnlyStateChangeHandlerRegistration.removeHandler();

        super.onUnregister();
    }

    @Override
    protected Multi createSelectionModel() {
        return new MultiSelectionModel();
    }

    @Override
    public MultiSelectionModelState getState() {
        return (MultiSelectionModelState) super.getState();
    }

    @OnStateChange("allSelected")
    void updateSelectAllCheckbox() {
        if (selectionModel.getSelectionColumnRenderer() != null) {
            HeaderCell cell = getGrid().getDefaultHeaderRow()
                    .getCell(getGrid().getColumn(0));
            CheckBox widget = (CheckBox) cell.getWidget();
            widget.setValue(getState().allSelected, false);
        }
    }

    @OnStateChange("userSelectionAllowed")
    void updateUserSelectionAllowed() {
        if (selectionModel instanceof HasUserSelectionAllowed) {
            ((HasUserSelectionAllowed) selectionModel)
                    .setUserSelectionAllowed(getState().userSelectionAllowed);
        } else {
            getLogger().warning("userSelectionAllowed set to "
                    + getState().userSelectionAllowed
                    + " but the selection model does not implement "
                    + HasUserSelectionAllowed.class.getSimpleName());
        }
    }

    private static Logger getLogger() {
        return Logger.getLogger(MultiSelectionModelConnector.class.getName());
    }

    /**
     * The default multi selection model used for this connector.
     *
     */
    protected class MultiSelectionModel extends AbstractSelectionModel
            implements SelectionModel.Multi.Batched,
            HasUserSelectionAllowed {

        private ComplexRenderer renderer = null;
        private Set> selected = new HashSet>();
        private Set> deselected = new HashSet>();
        private HandlerRegistration selectAll;
        private HandlerRegistration dataAvailable;
        private Range availableRows;
        private boolean batchSelect = false;
        private boolean userSelectionAllowed = true;

        @Override
        public void setGrid(Grid grid) {
            super.setGrid(grid);
            if (grid != null) {
                renderer = createSelectionColumnRenderer(grid);
                selectAll = getGrid().addSelectAllHandler(
                        new SelectAllHandler() {

                            @Override
                            public void onSelectAll(
                                    SelectAllEvent event) {
                                selectAll();
                            }
                        });
                dataAvailable = getGrid()
                        .addDataAvailableHandler(new DataAvailableHandler() {

                            @Override
                            public void onDataAvailable(
                                    DataAvailableEvent event) {
                                availableRows = event.getAvailableRows();
                            }
                        });
            } else if (renderer != null) {
                selectAll.removeHandler();
                dataAvailable.removeHandler();
                renderer = null;
            }
        }

        /**
         * Creates a selection column renderer. This method can be overridden to
         * use a custom renderer or use {@code null} to disable the selection
         * column.
         *
         * @param grid
         *            the grid for this selection model
         * @return selection column renderer or {@code null} if not needed
         */
        protected ComplexRenderer createSelectionColumnRenderer(
                Grid grid) {
            return new MultiSelectionRenderer(grid);
        }

        /**
         * Selects all available rows, sends request to server to select
         * everything.
         */
        public void selectAll() {
            assert !isBeingBatchSelected() : "Can't select all in middle of a batch selection.";

            DataSource dataSource = getGrid().getDataSource();
            for (int i = availableRows.getStart(); i < availableRows
                    .getEnd(); ++i) {
                final JsonObject row = dataSource.getRow(i);
                if (row != null) {
                    RowHandle handle = dataSource.getHandle(row);
                    markAsSelected(handle, true);
                }
            }

            getRpcProxy(MultiSelectionModelServerRpc.class).selectAll();
        }

        @Override
        public Renderer getSelectionColumnRenderer() {
            return renderer;
        }

        /**
         * {@inheritDoc}
         *
         * @return {@code false} if rows is empty, else {@code true}
         */
        @Override
        public boolean select(JsonObject... rows) {
            return select(Arrays.asList(rows));
        }

        /**
         * {@inheritDoc}
         *
         * @return {@code false} if rows is empty, else {@code true}
         */
        @Override
        public boolean deselect(JsonObject... rows) {
            return deselect(Arrays.asList(rows));
        }

        /**
         * {@inheritDoc}
         *
         * @return always {@code true}
         */
        @Override
        public boolean deselectAll() {
            assert !isBeingBatchSelected() : "Can't select all in middle of a batch selection.";

            DataSource dataSource = getGrid().getDataSource();
            for (int i = availableRows.getStart(); i < availableRows
                    .getEnd(); ++i) {
                final JsonObject row = dataSource.getRow(i);
                if (row != null) {
                    RowHandle handle = dataSource.getHandle(row);
                    markAsSelected(handle, false);
                }
            }

            getRpcProxy(MultiSelectionModelServerRpc.class).deselectAll();

            return true;
        }

        /**
         * {@inheritDoc}
         *
         * @return {@code false} if rows is empty, else {@code true}
         */
        @Override
        public boolean select(Collection rows) {
            if (rows.isEmpty()) {
                return false;
            }

            for (JsonObject row : rows) {
                RowHandle rowHandle = getRowHandle(row);
                if (markAsSelected(rowHandle, true)) {
                    selected.add(rowHandle);
                }
            }

            if (!isBeingBatchSelected()) {
                sendSelected();
            }
            return true;
        }

        /**
         * Marks the given row to be selected or deselected. Returns true if the
         * value actually changed.
         * 

* Note: If selection model is in batch select state, the row will be * pinned on select. * * @param row * row handle * @param selected * {@code true} if row should be selected; {@code false} if * not * @return {@code true} if selected status changed; {@code false} if not */ protected boolean markAsSelected(RowHandle row, boolean selected) { if (selected && !isSelected(row.getRow())) { row.getRow().put(GridState.JSONKEY_SELECTED, true); } else if (!selected && isSelected(row.getRow())) { row.getRow().remove(GridState.JSONKEY_SELECTED); } else { return false; } row.updateRow(); if (isBeingBatchSelected()) { row.pin(); } return true; } /** * {@inheritDoc} * * @return {@code false} if rows is empty, else {@code true} */ @Override public boolean deselect(Collection rows) { if (rows.isEmpty()) { return false; } for (JsonObject row : rows) { RowHandle rowHandle = getRowHandle(row); if (markAsSelected(rowHandle, false)) { deselected.add(rowHandle); } } if (!isBeingBatchSelected()) { sendDeselected(); } return true; } /** * Sends a deselect RPC call to server-side containing all deselected * rows. Unpins any pinned rows. */ private void sendDeselected() { getRpcProxy(MultiSelectionModelServerRpc.class) .deselect(getRowKeys(deselected)); if (isBeingBatchSelected()) { for (RowHandle row : deselected) { row.unpin(); } } deselected.clear(); } /** * Sends a select RPC call to server-side containing all selected rows. * Unpins any pinned rows. */ private void sendSelected() { getRpcProxy(MultiSelectionModelServerRpc.class) .select(getRowKeys(selected)); if (isBeingBatchSelected()) { for (RowHandle row : selected) { row.unpin(); } } selected.clear(); } private List getRowKeys(Set> handles) { List keys = new ArrayList(); for (RowHandle handle : handles) { keys.add(getRowKey(handle.getRow())); } return keys; } private Set getRows(Set> handles) { Set rows = new HashSet(); for (RowHandle handle : handles) { rows.add(handle.getRow()); } return rows; } @Override public void startBatchSelect() { assert selected.isEmpty() && deselected.isEmpty() : "Row caches were not clear."; batchSelect = true; } @Override public void commitBatchSelect() { assert batchSelect : "Not batch selecting."; if (!selected.isEmpty()) { sendSelected(); } if (!deselected.isEmpty()) { sendDeselected(); } batchSelect = false; } @Override public boolean isBeingBatchSelected() { return batchSelect; } @Override public Collection getSelectedRowsBatch() { return Collections.unmodifiableSet(getRows(selected)); } @Override public Collection getDeselectedRowsBatch() { return Collections.unmodifiableSet(getRows(deselected)); } @Override public boolean isUserSelectionAllowed() { return userSelectionAllowed; } @Override public void setUserSelectionAllowed(boolean userSelectionAllowed) { this.userSelectionAllowed = userSelectionAllowed && !getParent().isReadOnly(); for (Column c : getGrid().getColumns()) { if (c instanceof SelectionColumn) { ((SelectionColumn) c) .setUserSelectionAllowed(this.userSelectionAllowed); } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy