view flys-client/src/main/java/de/intevation/flys/client/client/ui/SingleLocationPanel.java @ 906:39acba4b5f0b

Added formatter for numeric columns that converts the decimal separator. (Issue200) flys-client/trunk@2758 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Raimund Renkert <raimund.renkert@intevation.de>
date Thu, 15 Sep 2011 14:48:31 +0000
parents dd702348b878
children 24d15c2e0da3
line wrap: on
line source
package de.intevation.flys.client.client.ui;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.NumberFormat;

import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;

import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
import com.smartgwt.client.widgets.grid.CellFormatter;

import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.types.ListGridFieldType;

import de.intevation.flys.client.shared.model.Data;
import de.intevation.flys.client.shared.model.DataItem;
import de.intevation.flys.client.shared.model.DataList;
import de.intevation.flys.client.shared.model.DefaultData;
import de.intevation.flys.client.shared.model.DefaultDataItem;
import de.intevation.flys.client.shared.model.DistanceInfoObject;
import de.intevation.flys.client.shared.model.ArtifactDescription;

import de.intevation.flys.client.client.services.DistanceInfoService;
import de.intevation.flys.client.client.services.DistanceInfoServiceAsync;
import de.intevation.flys.client.client.FLYSConstants;
import de.intevation.flys.client.client.FLYSImages;
import de.intevation.flys.client.client.Config;
import de.intevation.flys.client.client.ui.range.DistanceInfoDataSource;
import de.intevation.flys.client.client.event.FilterHandler;
import de.intevation.flys.client.client.event.StringFilterEvent;


/**
 * This UIProvider creates a widget to enter locations.
 *
 * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
 */
public class SingleLocationPanel
extends      AbstractUIProvider
implements   FilterHandler
{
    /** The message class that provides i18n strings.*/
    protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);

    /** The interface that provides the image resources. */
    private FLYSImages IMAGES = GWT.create(FLYSImages.class);

    /** The DistanceInfoService used to retrieve locations about rivers.*/
    protected DistanceInfoServiceAsync distanceInfoService =
        GWT.create(DistanceInfoService.class);

    /** A container that will contain the location or the distance panel.*/
    protected HLayout container;

    /** The minimal value that the user is allowed to enter.*/
    protected double min;

    /** The maximal value that the user is allowed to enter.*/
    protected double max;

    /** The values entered in the location mode.*/
    protected double[] values;

    /** The input panel for locations */
    protected DoubleArrayPanel locationPanel;

    /** The locations table */
    protected ListGrid locationTable;

    /** The table data. */
    protected DistanceInfoObject[] tableData;

    /**
     * Creates a new LocationDistancePanel instance.
     */
    public SingleLocationPanel() {
        locationTable = new ListGrid();
        locationTable.setShowHeaderContextMenu(false);
    }


    /**
     * This method creates a widget that contains a label, a panel with
     * checkboxes to switch the input mode between location and distance input,
     * and a the mode specific panel.
     *
     * @param data The data that might be inserted.
     *
     * @return a panel.
     */
    public Canvas create(DataList data) {
        VLayout layout = new VLayout();
        layout.setMembersMargin(10);

        Label label   = new Label(MESSAGES.location ());
        Canvas widget = createWidget(data);
        Canvas submit = getNextButton();

        initDefaults(data);

        createLocationTable();

        widget.setHeight(50);
        label.setHeight(25);

        layout.addMember(label);
        layout.addMember(widget);
        layout.addMember(submit);

        return layout;
    }


    /**
     * This method creates a table that contains the location values.
     */
    protected void createLocationTable() {
        GWT.log("---------- I WAS HERE ---------");
        locationTable.setWidth100();
        locationTable.setShowRecordComponents(true);
        locationTable.setShowRecordComponentsByCell(true);
        locationTable.setHeight100();
        locationTable.setEmptyMessage(MESSAGES.empty_filter());
        locationTable.setCanReorderFields(false);

        ListGridField addLocation = new ListGridField ("", "");
        addLocation.setType (ListGridFieldType.ICON);
        addLocation.setWidth (20);
        addLocation.addRecordClickHandler (new RecordClickHandler () {
            public void onRecordClick (RecordClickEvent e) {
                Record record = e.getRecord();
                double[] selected = new double[1];
                try {
                    selected[0] =
                        Double.parseDouble(record.getAttribute("from"));
                }
                catch(NumberFormatException nfe) {
                    // Is there anything else to do here?
                }
                setLocationValues(selected);
            }
        });
        addLocation.setCellIcon (IMAGES.markerGreen ().getURL ());

        ListGridField ldescr = new ListGridField("description",
                MESSAGES.description());
        ldescr.setType(ListGridFieldType.TEXT);
        ldescr.setWidth("*");
        ListGridField lside = new ListGridField("riverside",
                MESSAGES.riverside());
        lside.setType(ListGridFieldType.TEXT);
        lside.setWidth("10%");

        ListGridField loc = new ListGridField("from", MESSAGES.location());
        loc.setCellFormatter(new CellFormatter() {
            public String format(
                Object value,
                ListGridRecord record,
                int rowNum, int colNum) {
                    if (value == null) return null;
                    try {
                        NumberFormat nf;
                        double v = Double.parseDouble((String)value);
                        nf = NumberFormat.getFormat("###0.00##");
                        return nf.format(v);
                    }
                    catch (Exception e) {
                        return value.toString();
                    }
                }
            }
        );
        loc.setType(ListGridFieldType.FLOAT);

        loc.setWidth("10%");

        ListGridField bottom =
            new ListGridField("bottom", MESSAGES.bottom_edge());
        bottom.setType(ListGridFieldType.TEXT);
        bottom.setWidth("10%");

        ListGridField top =
            new ListGridField("top", MESSAGES.top_edge());
        top.setType(ListGridFieldType.TEXT);
        top.setWidth("10%");

        locationTable.setFields(
            addLocation, ldescr, loc, lside, bottom, top);
    }


    public Canvas createOld(DataList dataList) {
        List<Data> items = dataList.getAll();
        Data dLocation = getData(items, "ld_locations");
        DataItem[] loc = dLocation.getItems();

        HLayout layout = new HLayout();
        layout.setWidth("400px");

        Label   label  = new Label(dataList.getLabel());
        label.setWidth("200px");

        Canvas back = getBackButton(dataList.getState());

        Label selected = new Label(loc[0].getLabel());
        selected.setWidth("130px");

        layout.addMember(label);
        layout.addMember(selected);
        layout.addMember(back);

        return layout;
    }


    /**
     * This method reads the default values defined in the DataItems of the Data
     * objects in <i>list</i>.
     *
     * @param list The DataList container that stores the Data objects.
     */
    protected void initDefaults(DataList list) {
        Data data = list.get(0);

        if (data == null) {
            return;
        }

        DataItem[] items = data.getItems();
        DataItem   iMin  = getDataItem(items, "min");
        DataItem   iMax  = getDataItem(items, "max");

        try {
            min = Double.parseDouble(iMin.getStringValue());
            max = Double.parseDouble(iMax.getStringValue());
        }
        catch (NumberFormatException nfe) {
            SC.warn(MESSAGES.error_read_minmax_values());
            min = -Double.MAX_VALUE;
            max = Double.MAX_VALUE;
        }

        DataItem def   = data.getDefault();
        String   value = def.getStringValue();

        try {
            double d = Double.parseDouble(value);
            setLocationValues(new double[] { d } );
        }
        catch (NumberFormatException nfe) {
            // could not parse, dont know what to do else
        }
    }


    /**
     * This method greps the Data with name <i>name</i> from the list and
     * returns it.
     *
     * @param items A list of Data.
     * @param name The name of the Data that we are searching for.
     *
     * @return the Data with the name <i>name</i>.
     */
    protected Data getData(List<Data> data, String name) {
        for (Data d: data) {
            if (name.equals(d.getLabel())) {
                return d;
            }
        }

        return null;
    }


    protected Canvas createWidget(DataList data) {
        VLayout layout       = new VLayout();
        container            = new HLayout();

        // the initial view will display the location input mode
        locationPanel = new DoubleArrayPanel(
                MESSAGES.unitLocation(),
                getLocationValues(),
                new BlurHandler(){public void onBlur(BlurEvent be) {}});

        locationTable.setAutoFetchData(true);

        container.addMember(locationPanel);

        layout.addMember(container);

        container.setMembersMargin(30);

        TableFilter filter = new TableFilter();
        filter.setHeight("30px");
        filter.addFilterHandler(this);

        helperContainer.addMember(locationTable);
        helperContainer.addMember(filter);
        createInputPanel();
        return layout;
    }

    public void onFilterCriteriaChanged(StringFilterEvent event) {
        String search = event.getFilter();

        if (search != null && search.length() > 0) {
            Criteria c = new Criteria("description", search);
            locationTable.filterData(c);
        }
        else {
            // TODO Remove filter
        }
    }

    @Override
    public List<String> validate() {
        List<String> errors = new ArrayList<String>();
        NumberFormat nf     = NumberFormat.getDecimalFormat();

        saveLocationValues(locationPanel);

        if (!locationPanel.validateForm()) {
            errors.add(MESSAGES.wrongFormat());
            return errors;
        }

        double[] values = getLocationValues();
        double[] good   = new double[values.length];
        int      idx    = 0;

        for (double value: values) {
            if (value < min || value > max) {
                String tmp = MESSAGES.error_validate_range();
                tmp = tmp.replace("$1", nf.format(value));
                tmp = tmp.replace("$2", nf.format(min));
                tmp = tmp.replace("$3", nf.format(max));
                errors.add(tmp);
            }
            else {
                good[idx++] = value;
            }
        }

        double[] justGood = new double[idx];
        for (int i = 0; i < justGood.length; i++) {
            justGood[i] = good[i];
        }

        if (!errors.isEmpty()) {
            locationPanel.setValues(justGood);
        }

        return errors;
    }


    /**
     * This method returns the selected data.
     *
     * @return the selected/inserted data.
     */
    public Data[] getData() {
        saveLocationValues(locationPanel);
        double[] values = getLocationValues();
        Data[] data = new Data[values.length];
        DataItem item = new DefaultDataItem();
        for (int i = 0; i < values.length; i++) {
            item = new DefaultDataItem(
                "ld_locations",
                "ld_locations",
                Double.valueOf(values[i]).toString());
            data[i] = new DefaultData(
                "ld_locations",
                null,
                null,
                new DataItem[] {item});
        }
        return data;
    }




    /**
     * Validates and stores all values entered in the location mode.
     *
     * @param p The DoubleArrayPanel.
     */
    protected void saveLocationValues(DoubleArrayPanel p) {
        FormItem[] formItems = p.getFields();

        for (FormItem item: formItems) {
            if (item.getFieldName().equals(DoubleArrayPanel.FIELD_NAME)) {
                saveLocationValue(p, item);
            }
        }
    }


    /**
     * Validates and stores a value entered in the location mode.
     *
     * @param p The DoubleArrayPanel.
     * @param item The item that needs to be validated.
     */
    protected void saveLocationValue(DoubleArrayPanel p, FormItem item) {
        if (p.validateForm(item)) {
            setLocationValues(p.getInputValues(item));
        }
    }


    protected void createInputPanel() {
        Config config = Config.getInstance();
        String url    = config.getServerUrl();
        String locale = config.getLocale ();
        String river  = "";

        ArtifactDescription adescr = artifact.getArtifactDescription();
        DataList[] data = adescr.getOldData();

        if (data != null && data.length > 0) {
            for (int i = 0; i < data.length; i++) {
                DataList dl = data[i];
                if (dl.getState().equals("state.winfo.river")) {
                    for (int j = 0; j < dl.size(); j++) {
                        Data d = dl.get(j);
                        DataItem[] di = d.getItems();
                        if (di != null && di.length == 1) {
                           river = d.getItems()[0].getStringValue();
                           break;
                        }
                    }
                }
            }
        }

        locationTable.setDataSource(new DistanceInfoDataSource(
            url, river, "locations"));
    }


    protected double[] getLocationValues() {
        return values;
    }


    protected void setLocationValues(double[] values) {
        this.values = values;
        locationPanel.setValues(values);
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org