ilarkesto.gwt.client.desktop.fields.AEditableMultiSelectionField.java Source code

Java tutorial

Introduction

Here is the source code for ilarkesto.gwt.client.desktop.fields.AEditableMultiSelectionField.java

Source

/*
 * Copyright 2011 Witoslaw Koczewsi <wi@koczewski.de>
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero
 * General Public License as published by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program. If not,
 * see <http://www.gnu.org/licenses/>.
 */
package ilarkesto.gwt.client.desktop.fields;

import ilarkesto.core.base.Str;
import ilarkesto.gwt.client.AAction;
import ilarkesto.gwt.client.desktop.AObjectTable;
import ilarkesto.gwt.client.desktop.ActionButton;
import ilarkesto.gwt.client.desktop.BuilderPanel;
import ilarkesto.gwt.client.desktop.Colors;
import ilarkesto.gwt.client.desktop.Widgets;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public abstract class AEditableMultiSelectionField extends AEditableField {

    private boolean showAsTable = false;

    private Map<String, CheckBox> checkboxes;

    private ItemsTable table;

    public abstract void applyValue(List<String> selectedKeys);

    public abstract String getValueForKey(String key);

    public abstract Collection<String> createOptionKeys();

    public abstract Collection<String> getSelectedOptionKeys();

    public String getDisplayValueForKey(String key) {
        return getValueForKey(key);
    }

    @Override
    public boolean isValueSet() {
        Collection<String> keys = getSelectedOptionKeys();
        return keys != null && !keys.isEmpty();
    }

    @Override
    public void trySubmit() throws RuntimeException {
        List<String> selectedKeys = table == null ? getSelectedKeysFromCheckboxes() : table.getSelectedKeys();
        applyValue(selectedKeys);
    }

    private List<String> getSelectedKeysFromCheckboxes() {
        List<String> selectedKeys = new ArrayList<String>();
        for (Map.Entry<String, CheckBox> entry : checkboxes.entrySet()) {
            String key = entry.getKey();
            CheckBox checkBox = entry.getValue();
            if (checkBox.getValue().booleanValue())
                selectedKeys.add(key);
        }
        return selectedKeys;
    }

    @Override
    public IsWidget createEditorWidget() {
        Collection<String> optionKeys = createOptionKeys();
        if (isShowAsTable(optionKeys)) {
            table = createItemsTable(optionKeys);
            return table;
        }
        return createCheckboxesEditorWidget(optionKeys);
    }

    protected ItemsTable createItemsTable(Collection<String> optionKeys) {
        return new ItemsTable(optionKeys);
    }

    protected boolean isShowAsTable(Collection<String> optionKeys) {
        return showAsTable || optionKeys.size() >= 23;
    }

    public AEditableMultiSelectionField setShowAsTable(boolean showAsTable) {
        this.showAsTable = showAsTable;
        return this;
    }

    private IsWidget createCheckboxesEditorWidget(Collection<String> optionKeys) {
        checkboxes = new LinkedHashMap<String, CheckBox>();

        boolean horizontal = isHorizontal();
        Panel panel = horizontal ? new FlowPanel() : new VerticalPanel();

        Collection<String> selectedKeys = getSelectedOptionKeys();

        int inRow = 0;

        for (String key : optionKeys) {
            String label = getTextForOption(getValueForKey(key));
            CheckBox checkBox = new CheckBox(label);
            checkBox.getElement().setId(getId() + "_checkbox_" + key);
            checkBox.setValue(selectedKeys.contains(key));
            if (getEditVetoMessage() == null) {
            } else {
                checkBox.setEnabled(false);
                checkBox.setTitle(getEditVetoMessage());
            }
            updateStyle(checkBox);
            checkBox.addValueChangeHandler(new CheckboxChangeHandler(checkBox));
            if (horizontal) {
                Style style = checkBox.getElement().getStyle();
                style.setProperty("minWidth", "100px");
                style.setDisplay(Display.BLOCK);
                style.setFloat(com.google.gwt.dom.client.Style.Float.LEFT);
                style.setWidth(220, Unit.PX);
                style.setMarginRight(Widgets.defaultSpacing, Unit.PX);
            }
            checkboxes.put(key, checkBox);
            panel.add(checkBox);
            inRow++;
            if (horizontal && inRow >= 3) {
                panel.add(new HTML("<br>"));
                inRow = 0;
            }
        }
        if (horizontal) {
            panel.add(Widgets.clear());
        }

        if (optionKeys.size() >= 10) {
            panel.add(new ActionButton(new SelectAllCheckboxesAction()));
            panel.add(new ActionButton(new DeselectAllCheckboxesAction()));
        }

        return panel;
    }

    private String getTextForOption(Object value) {
        return value == null ? "" : value.toString();
    }

    private void updateStyle(CheckBox checkBox) {
        Style style = checkBox.getElement().getStyle();
        if (checkBox.getValue().booleanValue()) {
            style.setColor("#000");
        } else {
            style.setColor("#666");
        }
    }

    protected boolean isHorizontal() {
        return true;
    }

    @Override
    public IsWidget createDisplayWidget() {
        return new Label(createDisplayText());
    }

    protected String createDisplayText() {
        Collection<String> selectedKeys = getSelectedOptionKeys();
        List<String> values = new ArrayList<String>(selectedKeys.size());
        for (String key : selectedKeys) {
            String itemText = getDisplayValueForKey(key);
            values.add(itemText);
        }
        return isDisplayMultiline(values) ? Str.concat(values, "\n", "* ", null) : Str.concat(values, ", ");
    }

    protected boolean isDisplayMultiline(List<String> values) {
        return values.size() > 1 && Str.getTotalLength(values) >= 120;
    }

    public class ItemsTable extends AObjectTable<Item> {

        private ArrayList<Item> items;

        public ItemsTable(Collection<String> optionKeys) {
            Collection<String> selectedKeys = getSelectedOptionKeys();
            items = new ArrayList<Item>(optionKeys.size());
            for (String key : optionKeys) {
                Item item = new Item(key, getValueForKey(key));
                items.add(item);
                if (selectedKeys.contains(item.key))
                    item.selected = true;
            }
        }

        @Override
        protected void init(BuilderPanel wrapper) {
            super.init(wrapper);
            wrapper.createTitle("", new SelectAllInTableAction(), new DeselectAllInTableAction());

            add(new AColumn() {

                @Override
                public Widget getCellWidget(Item o) {
                    if (!o.selected)
                        return null;
                    return Widgets.icon("checked", 32);
                }

                @Override
                protected boolean isTrimmed() {
                    return true;
                }

                @Override
                public TextBox getFilterWidget() {
                    return null;
                }

            });

            initColumns();

        }

        protected void initColumns() {
            add(new AColumn() {

                @Override
                public Object getCellValue(Item o) {
                    return getTextForOption(o.value);
                }

            });
        }

        @Override
        protected Collection<Item> getObjects() {
            return items;
        }

        @Override
        protected void onClick(Item object, int column) {
            if (getEditVetoMessage() != null)
                return;
            object.selected = !object.selected;
            update();
        }

        @Override
        protected boolean isClickable() {
            return getEditVetoMessage() == null;
        }

        @Override
        protected boolean isColumnFilteringEnabled() {
            return items.size() > 42;
        }

        public List<String> getSelectedKeys() {
            ArrayList<String> ret = new ArrayList<String>();
            for (Item item : items) {
                if (item.selected)
                    ret.add(item.key);
            }
            return ret;
        }

        @Override
        protected String getRowColor(Item o) {
            if (o.selected)
                return Colors.googlePurple;
            return Colors.greyedText;
        }

        class SelectAllInTableAction extends AAction {

            @Override
            public String getLabel() {
                return "Alle auswhlen";
            }

            @Override
            protected String getIconName() {
                return "select_all";
            }

            @Override
            protected void onExecute() {
                for (Item item : items) {
                    item.selected = true;
                }
                ItemsTable.this.update();
            }
        }

        class DeselectAllInTableAction extends AAction {

            @Override
            public String getLabel() {
                return "Keine auswhlen";
            }

            @Override
            protected String getIconName() {
                return "deselect_all";
            }

            @Override
            protected void onExecute() {
                for (Item item : items) {
                    item.selected = false;
                }
                ItemsTable.this.update();
            }

        }
    }

    public static class Item {

        private String key;
        private Object value;
        private boolean selected;

        public Item(String key, Object value) {
            super();
            this.key = key;
            this.value = value;
        }

        public String getKey() {
            return key;
        }

        public Object getValue() {
            return value;
        }

        public boolean isSelected() {
            return selected;
        }

        public <T> T getValue(Class<T> valueType) {
            return (T) value;
        }

    }

    class SelectAllCheckboxesAction extends AAction {

        @Override
        public String getLabel() {
            return "Alle auswhlen";
        }

        @Override
        protected String getIconName() {
            return "select_all";
        }

        @Override
        protected void onExecute() {
            Boolean value = true;
            for (CheckBox checkbox : checkboxes.values()) {
                checkbox.setValue(value);
            }
        }
    }

    class DeselectAllCheckboxesAction extends AAction {

        @Override
        public String getLabel() {
            return "Keine auswhlen";
        }

        @Override
        protected String getIconName() {
            return "deselect_all";
        }

        @Override
        protected void onExecute() {
            Boolean value = false;
            for (CheckBox checkbox : checkboxes.values()) {
                checkbox.setValue(value);
            }
        }

    }

    class CheckboxChangeHandler implements ValueChangeHandler<Boolean> {

        private CheckBox checkBox;

        public CheckboxChangeHandler(CheckBox checkBox) {
            super();
            this.checkBox = checkBox;
        }

        @Override
        public void onValueChange(ValueChangeEvent<Boolean> event) {
            updateStyle(checkBox);
        }
    }

}