org.obiba.opal.web.gwt.app.client.ui.celltable.CheckboxColumn.java Source code

Java tutorial

Introduction

Here is the source code for org.obiba.opal.web.gwt.app.client.ui.celltable.CheckboxColumn.java

Source

/*
 * Copyright (c) 2013 OBiBa. All rights reserved.
 *
 * This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.obiba.opal.web.gwt.app.client.ui.celltable;

import java.util.LinkedList;
import java.util.List;

import org.obiba.opal.web.gwt.app.client.i18n.Translations;
import org.obiba.opal.web.gwt.app.client.i18n.TranslationsUtils;
import org.obiba.opal.web.gwt.app.client.ui.Table;

import com.github.gwtbootstrap.client.ui.Alert;
import com.github.gwtbootstrap.client.ui.base.IconAnchor;
import com.google.common.collect.Lists;
import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.Header;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SetSelectionModel;
import com.google.gwt.view.client.SingleSelectionModel;

public class CheckboxColumn<T> extends Column<T, Boolean> implements HasActionHandler<Integer> {

    private final Translations translations = GWT.create(Translations.class);

    private final SetSelectionModel<T> selectionModel;

    private final Display<T> display;

    private final boolean singleSelectionModel;

    private ActionHandler<Integer> actionHandler;

    /**
     * Construct a new column with check boxes and multi selection model.
     *
     * @param display
     */
    public CheckboxColumn(Display<T> display) {
        this(display, false);
    }

    /**
     * Construct a new column with check boxes and optional single or multi selection model.
     *
     * @param display
     * @param single
     */
    public CheckboxColumn(final Display<T> display, boolean single) {
        super(new CheckboxCell(true, true) {
            @Override
            public void render(Context context, Boolean value, SafeHtmlBuilder sb) {
                // check if forbidden or has conflict
                super.render(context, value, sb);

            }
        });
        this.display = display;
        singleSelectionModel = single;

        selectionModel = single ? new SingleSelectionModel<T>(new ProvidesKey<T>() {

            @Override
            public Object getKey(T item) {
                return display.getItemKey(item);
            }
        }) : new MultiSelectionModel<T>(new ProvidesKey<T>() {

            @Override
            public Object getKey(T item) {
                return display.getItemKey(item);
            }
        });

        setFieldUpdater(new FieldUpdater<T, Boolean>() {

            @Override
            public void update(int index, T object, Boolean value) {
                selectionModel.setSelected(object, value);
                // hide status message when deselecting an element
                // only redraw when the first checkbox is deselected
                int nbDeselected = 0;
                for (T v : display.getTable().getVisibleItems()) {
                    if (!selectionModel.isSelected(v)) {
                        nbDeselected++;
                    }
                }

                // Redraw table when selecting/deselecting the last/first checkbox
                if (singleSelectionModel || nbDeselected <= 1) {
                    display.getTable().redraw();
                }

                updateStatusAlert();
                doAction();
            }
        });

        addHandlers();
    }

    public SetSelectionModel<T> getSelectionModel() {
        return selectionModel;
    }

    private void addHandlers() {
        addClearSelectionHandler();
        addSelectAllHandler();
    }

    private void addClearSelectionHandler() {
        if (display.getClearSelection() == null)
            return;

        display.getClearSelection().addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                for (T tc : display.getDataProvider().getList()) {
                    selectionModel.setSelected(tc, false);
                }
                display.getTable().redraw();
                display.getClearSelection().setVisible(false);
            }
        });
    }

    private void addSelectAllHandler() {
        if (display.getSelectAll() == null)
            return;

        // init SelectAll and Clear Selection links
        display.getSelectAll().addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                for (T tc : display.getDataProvider().getList()) {
                    selectionModel.setSelected(tc, true);
                }

                display.getTable().redraw();
                updateStatusAlert();
                doAction();
            }
        });
    }

    public void clearSelection() {
        selectionModel.clear();
    }

    public void setSelected(T item, boolean selected) {
        selectionModel.setSelected(item, selected);
    }

    /**
     * @return List of items in the same order as they appear on screen
     */
    public List<T> getSelectedItems() {
        List<T> list = new LinkedList<T>();
        for (T tc : display.getDataProvider().getList()) {
            if (selectionModel.isSelected(tc)) {
                list.add(tc);
            }
        }
        return list;
    }

    @Override
    public Boolean getValue(T object) {
        // Get the value from the selection model.
        return selectionModel.isSelected(object);
    }

    public Header<Boolean> getCheckColumnHeader() {
        Header<Boolean> checkHeader = new Header<Boolean>(new CheckboxCell(true, true) {
            @Override
            public void render(Context context, Boolean value, SafeHtmlBuilder sb) {
                if (display.getDataProvider().getList().isEmpty()) {
                    sb.append(SafeHtmlUtils
                            .fromSafeConstant("<input type=\"checkbox\" tabindex=\"-1\" disabled=\"disabled\"/>"));
                } else {
                    super.render(context, value, sb);
                }

            }
        }) {

            @Override
            public Boolean getValue() {
                updateStatusAlert();
                if (display.getDataProvider().getList().isEmpty()) {
                    return false;
                }

                // Value of the header checkbox for the current page
                for (T tc : display.getTable().getVisibleItems()) {
                    if (!selectionModel.isSelected(tc)) {
                        return false;
                    }
                }

                return true;
            }
        };
        checkHeader.setUpdater(new ValueUpdater<Boolean>() {

            @Override
            public void update(Boolean value) {

                if (display.getDataProvider().getList().isEmpty())
                    return;

                for (T tc : display.getTable().getVisibleItems()) {
                    selectionModel.setSelected(tc, value);
                }

                doAction();

                display.getTable().redraw();
            }

        });

        return checkHeader;
    }

    private void updateStatusAlert() {

        if (display.getClearSelection() == null || display.getSelectAll() == null
                || display.getSelectAllStatus() == null)
            return;

        int selectedSize = selectionModel.getSelectedSet().size();

        boolean allSelected = selectedSize == display.getDataProvider().getList().size();

        if (display.getAlert() != null && selectedSize == 0) {
            display.getAlert().setVisible(false);
        } else if (allSelected) {
            updateStatusAlertWhenAllSelected(selectedSize);
        } else if (selectedSize > 0) {
            updateStatusAlertWhenNotAllSelected(selectedSize);
        }
    }

    private void updateStatusAlertWhenAllSelected(int currentSelected) {
        List<String> args = Lists.newArrayList();

        args.add(display.getNItemLabel(currentSelected));
        if (currentSelected > 1) {
            display.getSelectAllStatus()
                    .setText(TranslationsUtils.replaceArguments(translations.allItemsSelected(), args));
        } else {
            display.getSelectAllStatus()
                    .setText(TranslationsUtils.replaceArguments(translations.NItemSelected(), args));
        }

        display.getClearSelection().setVisible(true);
        display.getSelectAll().setVisible(false);
    }

    private void updateStatusAlertWhenNotAllSelected(int currentSelected) {
        List<String> args = Lists.newArrayList();

        args.add(display.getNItemLabel(currentSelected));
        if (currentSelected > 1) {
            display.getSelectAllStatus()
                    .setText(TranslationsUtils.replaceArguments(translations.NItemsSelected(), args));
        } else {
            display.getSelectAllStatus()
                    .setText(TranslationsUtils.replaceArguments(translations.NItemSelected(), args));
        }
        display.getSelectAll().setVisible(true);

        args.clear();
        args.add(display.getNItemLabel(display.getDataProvider().getList().size()));
        display.getSelectAll().setText(TranslationsUtils.replaceArguments(translations.selectAllNItems(), args));
        display.getClearSelection().setVisible(true);
    }

    private void doAction() {
        // Count the number of selected items on the current page.
        Integer nbSelected = selectionModel.getSelectedSet().size();

        if (display.getAlert() != null) {
            display.getAlert().setVisible(nbSelected > 0);
        }

        if (actionHandler != null) {
            actionHandler.doAction(nbSelected, "SELECT");
        }
    }

    @Override
    public void setActionHandler(ActionHandler<Integer> handler) {
        actionHandler = handler;
    }

    public interface Display<T> {
        /**
         * @return The displayed table
         */
        Table<T> getTable();

        /**
         * @param item
         * @return The unique key of the item
         */
        Object getItemKey(T item);

        /**
         * @return The link that displays the "clear selection" action
         */
        IconAnchor getClearSelection();

        /**
         * @return The link to select all items
         */
        IconAnchor getSelectAll();

        /**
         * @return The label to show that all items on the page are selected
         */
        HasText getSelectAllStatus();

        /**
         * @return The table data provider
         */
        ListDataProvider<T> getDataProvider();

        /**
         * @return The type name of item
         */
        String getNItemLabel(int nb);

        Alert getAlert();
    }
}