view gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterMatrix.java @ 9390:f575ff573cbb

"Name der Peilung" columname minfo.
author gernotbelger
date Thu, 09 Aug 2018 15:22:31 +0200
parents 5e38e2924c07
children 2da486c7c05f
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */

package org.dive4elements.river.client.client.ui;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dive4elements.river.client.client.FLYSConstants;
import org.dive4elements.river.client.shared.model.DataItem;
import org.dive4elements.river.client.shared.model.IntegerOptionsData;
import org.dive4elements.river.client.shared.model.MultiAttributeData;
import org.dive4elements.river.client.shared.model.MultiDataItem;
import org.dive4elements.river.client.shared.model.StringOptionsData;

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.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Widget;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;

/**
 * Some parameters take the form of on/off options that can also be seen
 * as a matrix.
 *
 * This class helps to survive the underlying objects and create a visual
 * representation of this matrix. Later can happen in two ways to overcome
 * shortcomings of GWT/SmartGWT combination.
 */
public class ParameterMatrix {

    protected ListGrid listGrid = null;

    public static class Column implements Serializable {

        private static final long serialVersionUID = -3493426383086860118L;

        protected String name;
        protected Map<String, String> values;

        private Column() {
            this.values = new HashMap<String, String>();
        }

        public Column(final String name) {
            this();
            this.name = name;
        }

        public void addValue(final String label, final String value) {
            this.values.put(label, value);
        }

        public String getValue(final String label) {
            return this.values.get(label);
        }
    } // end of class Column

    /** The message class that provides i18n strings. */
    protected FLYSConstants MESSAGE = GWT.create(FLYSConstants.class);

    public static final int CELL_HEIGHT = 25;

    private final Map<String, Column> columns;
    private final List<String> columnNames;
    private final List<String> valueNames;
    private final Map<String, List<String>> attributes;

    /** Maps column names to list of rows' first fields. */
    private final Map<String, List<String>> selected;
    private final String itemname;

    public ParameterMatrix(final String itemnameColTitle) {
        super();
        this.itemname = itemnameColTitle;
        this.columns = new HashMap<String, Column>();
        this.columnNames = new ArrayList<String>();
        this.valueNames = new ArrayList<String>();
        this.selected = new HashMap<String, List<String>>();
        this.attributes = new HashMap<String, List<String>>();
    }

    public void addColumn(final IntegerOptionsData group) {
        final String groupTitle = group.getLabel();

        final Column col = new Column(groupTitle);
        final DataItem[] items = group.getItems();

        if (items == null) {
            GWT.log("No items found in StringOptionsData '" + groupTitle + "'");
            return;
        }

        for (final DataItem item : items) {
            final String title = item.getLabel();

            if (this.valueNames.indexOf(title) < 0) {
                this.valueNames.add(title);
            }

            col.addValue(item.getLabel(), item.getStringValue());
        }

        this.columnNames.add(groupTitle);
        this.columns.put(groupTitle, col);
    }

    public List<String> getColumnNames() {
        return this.columnNames;
    }

    public void addColumn(final StringOptionsData options) {
        final String groupTitle = options.getLabel();

        final Column col = new Column(groupTitle);
        final DataItem[] items = options.getItems();

        if (items == null) {
            GWT.log("No items found in StringOptionsData '" + groupTitle + "'");
            return;
        }

        for (final DataItem item : items) {
            final String title = item.getLabel();

            if (this.valueNames.indexOf(title) < 0) {
                this.valueNames.add(title);
            }

            col.addValue(item.getLabel(), item.getStringValue());
        }

        this.columnNames.add(groupTitle);
        this.columns.put(groupTitle, col);
    }

    public void addColumn(final MultiAttributeData options) {
        GWT.log("Add Columns for MultiAttribute data");
        final String groupTitle = options.getLabel();

        final Column col = new Column(groupTitle);
        final DataItem[] items = options.getItems();

        if (items == null) {
            GWT.log("No items found in StringOptionsData '" + groupTitle + "'");
            return;
        }

        final MultiDataItem mItem = (MultiDataItem) items[0];
        for (final Map.Entry<String, String> entry : mItem.getValue().entrySet()) {
            if (entry.getKey().equals("art:value") || entry.getKey().equals("art:label")) {
                continue;
            }
            this.attributes.put(entry.getKey(), new ArrayList<String>());
        }
        for (final DataItem item : items) {
            GWT.log("multidataitem: " + item.getLabel());
            final String title = item.getLabel();

            if (this.valueNames.indexOf(title) < 0) {
                this.valueNames.add(title);
            }
            final MultiDataItem mi = (MultiDataItem) item;
            final Map<String, String> vs = mi.getValue();
            for (final Map.Entry<String, String> e : vs.entrySet()) {
                if (e.getKey().equals("art:value") || e.getKey().equals("art:label")) {
                    continue;
                }
                final List<String> data = this.attributes.get(e.getKey());
                data.add(e.getValue());
            }
            col.addValue(item.getLabel(), mi.getValue().get("art:value"));
        }

        this.columnNames.add(groupTitle);
        this.columns.put(groupTitle, col);
    }

    public Widget createParameterGrid() {
        this.listGrid = new ListGrid();
        this.listGrid.setShowAllRecords(true);
        this.listGrid.setWrapCells(true);
        this.listGrid.setShowHeaderContextMenu(false);
        this.listGrid.setCanReorderFields(false);
        // listGrid.setCanSort(false);
        // listGrid.setAutoFitData(Autofit.VERTICAL);
        this.listGrid.setFixedRecordHeights(false);
        // TODO: Then also need "autofit" (when wrapping)

        final ListGridField itemNameField = new ListGridField("itemname", this.itemname);
        final ArrayList<ListGridField> fields = new ArrayList<ListGridField>();
        fields.add(itemNameField);

        for (final Map.Entry<String, List<String>> entry : this.attributes.entrySet()) {
            final ListGridField attrField = new ListGridField(entry.getKey(), this.MESSAGE.getString(entry.getKey()));
            fields.add(attrField);
        }

        for (int i = 0, n = this.columnNames.size(); i < n; i++) {
            final ListGridField field = new ListGridField(this.columnNames.get(i), this.MESSAGE.getString(this.columnNames.get(i)));
            field.setType(ListGridFieldType.BOOLEAN);
            field.setCanEdit(true);
            fields.add(field);
            this.selected.put(this.columnNames.get(i), new ArrayList<String>());
        }

        final ListGridField[] fieldsArray = fields.toArray(new ListGridField[fields.size()]);
        this.listGrid.setFields(fieldsArray);

        final int nVals = this.valueNames.size();

        final ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>();
        for (int j = 0; j < nVals; j++) {
            final String valueName = this.valueNames.get(j);
            final ListGridRecord record = new ListGridRecord();
            record.setAttribute("itemname", valueName);
            for (int i = 0, n = this.columnNames.size(); i < n; i++) {
                final String columnName = this.columnNames.get(i);
                final Column col = this.columns.get(columnName);
                final String value = col.getValue(valueName);
                record.setAttribute(columnName, false);
                record.setAttribute(columnName + "-value", value);
            }
            for (final Map.Entry<String, List<String>> entry : this.attributes.entrySet()) {
                record.setAttribute(entry.getKey(), entry.getValue().get(j));
            }
            records.add(record);
        }

        this.listGrid.setData(records.toArray(new ListGridRecord[records.size()]));

        return this.listGrid;

    }

    /**
     * Returns a widget with matrix of checkboxes and labels.
     *
     * @param asListGrid
     *            if true, use a ListGrid (for inclusion in SmartGWT
     *            containers, avoiding scrollbar-issues.
     */
    public Widget create(final boolean asListGrid) {
        if (asListGrid) {
            return createParameterGrid();
        }
        final Grid grid = new Grid(this.valueNames.size() + 1, this.columnNames.size() + 1);

        for (int i = 0, n = this.columnNames.size(); i < n; i++) {
            final String columnName = this.columnNames.get(i);
            final Column col = this.columns.get(columnName);

            this.selected.put(columnName, new ArrayList<String>());

            grid.setWidget(0, i + 1, createLabel(this.MESSAGE.getString(columnName)));

            for (int j = 0, o = this.valueNames.size(); j < o; j++) {
                final String valueName = this.valueNames.get(j);
                final String value = col.getValue(valueName);

                if (i == 0) {
                    grid.setWidget(j + 1, 0, createLabel(valueName));
                }

                if (value != null && value.length() > 0) {
                    grid.setWidget(j + 1, i + 1, createCheckBox(columnName, value));
                }
            }
        }

        return grid;
    }

    /** Creates label with given text. */
    protected Label createLabel(final String text) {
        final Label label = new Label(text);
        label.setHeight(CELL_HEIGHT);

        return label;
    }

    /** Create Checkbox for column/value. */
    protected Canvas createCheckBox(final String colName, final String value) {
        final CheckBox box = new CheckBox();
        box.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(final ClickEvent event) {
                final Map<String, List<String>> selection = getSelection();

                final List<String> values = selection.get(colName);
                if (values.indexOf(value) >= 0) {
                    values.remove(value);
                } else {
                    values.add(value);
                }
            }
        });

        final Canvas c = new Canvas();
        c.addChild(box);
        return c;
    }

    public Map<String, List<String>> getSelection() {
        if (this.listGrid == null) {
            return this.selected;
        }

        final ListGridRecord[] records = this.listGrid.getRecords();
        final Map<String, List<String>> result = new HashMap<String, List<String>>();
        for (final ListGridRecord record : records) {
            for (int i = 0, n = this.columnNames.size(); i < n; i++) {
                final String columnName = this.columnNames.get(i);
                if (Boolean.valueOf(record.getAttribute(columnName)) == true) {
                    if (result.containsKey(columnName)) {
                        result.get(columnName).add(record.getAttribute(columnName + "-value"));
                    } else {
                        final List<String> items = new ArrayList<String>();
                        items.add(record.getAttribute(columnName + "-value"));
                        result.put(columnName, items);
                    }
                }
            }
        }
        return result;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org