diff flys-client/src/main/java/org/dive4elements/river/client/client/ui/LocationDistancePanel.java @ 5834:f507086aa94b

Repaired internal references.
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 12:31:32 +0200
parents flys-client/src/main/java/de/intevation/flys/client/client/ui/LocationDistancePanel.java@b296d435fc69
children 821a02bbfb4e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/org/dive4elements/river/client/client/ui/LocationDistancePanel.java	Thu Apr 25 12:31:32 2013 +0200
@@ -0,0 +1,1439 @@
+package de.intevation.flys.client.client.ui;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.NumberFormat;
+
+import com.smartgwt.client.data.AdvancedCriteria;
+import com.smartgwt.client.data.Criteria;
+import com.smartgwt.client.data.Criterion;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.types.Alignment;
+import com.smartgwt.client.types.ListGridFieldType;
+import com.smartgwt.client.types.OperatorId;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.FormItem;
+import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
+import com.smartgwt.client.widgets.form.fields.SelectItem;
+import com.smartgwt.client.widgets.form.fields.StaticTextItem;
+import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
+import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
+import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
+import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
+import com.smartgwt.client.widgets.grid.CellFormatter;
+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.CellClickEvent;
+import com.smartgwt.client.widgets.grid.events.CellClickHandler;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.tab.Tab;
+import com.smartgwt.client.widgets.tab.TabSet;
+import com.smartgwt.client.widgets.tab.events.TabSelectedEvent;
+import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
+
+import de.intevation.flys.client.client.Config;
+import de.intevation.flys.client.client.FLYSConstants;
+import de.intevation.flys.client.client.event.FilterHandler;
+import de.intevation.flys.client.client.event.RangeFilterEvent;
+import de.intevation.flys.client.client.event.StringFilterEvent;
+import de.intevation.flys.client.client.services.DistanceInfoService;
+import de.intevation.flys.client.client.services.DistanceInfoServiceAsync;
+import de.intevation.flys.client.client.ui.range.DistanceInfoDataSource;
+import de.intevation.flys.client.shared.model.ArtifactDescription;
+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 java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+
+/**
+ * This UIProvider creates a widget to enter locations or a distance.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class LocationDistancePanel
+extends      AbstractUIProvider
+implements   ChangeHandler, BlurHandler, FilterHandler
+{
+    private static final long serialVersionUID = -10820092176039372L;
+
+    /** The message class that provides i18n strings. */
+    protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
+
+    /** The DistanceInfoService used to retrieve locations about rivers. */
+    protected DistanceInfoServiceAsync distanceInfoService =
+        GWT.create(DistanceInfoService.class);
+
+    public static final String FIELD_MODE = "mode";
+
+    /** The constant name of the input field to enter the start of a distance.*/
+    public static final String FIELD_FROM = "from";
+
+    /** The constant name of the input field to enter the end of a distance.*/
+    public static final String FIELD_TO = "to";
+
+    /** The constant name of the input field to enter locations.*/
+    public static final String FIELD_VALUE_LOCATION = "location";
+
+    /** The constant name of the input field to enter distance.*/
+    public static final String FIELD_VALUE_DISTANCE = "distance";
+
+    /** The constant name of the input field to enter the step width of a
+     * distance.*/
+    public static final String FIELD_WIDTH = "width";
+
+    public static final int WIDTH = 250;
+
+
+    /** The radio group for input mode selection.*/
+    protected DynamicForm mode;
+
+    /** A container that will contain the location or the distance panel.*/
+    protected HLayout container;
+
+    /** The min value for a distance.*/
+    protected double min;
+
+    /** The max value for a distance.*/
+    protected double max;
+
+    /** The 'from' value entered in the distance mode.*/
+    protected double from;
+
+    /** The 'to' value entered in the distance mode.*/
+    protected double to;
+
+    /** The 'step' value entered in the distance mode.*/
+    protected double step;
+
+    /** The values entered in the location mode.*/
+    protected double[] values;
+
+    /** The input panel for locations. */
+    protected DoubleArrayPanel locationPanel;
+
+    /** The input panel for distances. */
+    protected DoubleRangePanel distancePanel;
+
+    /** The tab set containing the location and distance table. */
+    protected TabSet inputTables;
+
+    /** The distance table. */
+    protected ListGrid distanceTable;
+
+    /** The locations table. */
+    protected ListGrid locationsTable;
+
+    /** The locations table for distance input. */
+    protected ListGrid locationDistanceTable;
+
+    /** The table data. */
+    protected DistanceInfoObject[] tableData;
+
+    /** The table filter.*/
+    protected TableFilter filterDescription;
+    protected RangeTableFilter filterRange;
+
+    /** The Combobox for table filter criteria. */
+    protected SelectItem filterCriteria;
+    protected StaticTextItem filterResultCount;
+    protected ListGrid currentFiltered;
+
+    /**
+     * Creates a new LocationDistancePanel instance.
+     */
+    public LocationDistancePanel() {
+        distanceTable  = new ListGrid();
+        distanceTable.setAutoFetchData(true);
+
+        locationsTable = new ListGrid();
+        locationsTable.setAutoFetchData(true);
+
+        locationDistanceTable = new ListGrid();
+        locationDistanceTable.setAutoFetchData(true);
+
+        locationDistanceTable.setShowHeaderContextMenu(false);
+        distanceTable.setShowHeaderContextMenu(false);
+        locationsTable.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.
+     */
+    @Override
+    public Canvas create(DataList data) {
+        VLayout layout = new VLayout();
+        layout.setMembersMargin(10);
+
+        Label label   = new Label(MESSAGES.location_distance_state());
+        Canvas widget = createWidget(data);
+        Canvas submit = getNextButton();
+        createDistanceInputPanel();
+
+        initDefaults(data);
+
+        createLocationTableDistance ();
+        createDistanceTable();
+        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 distance values.
+     */
+    protected void createDistanceTable() {
+
+        String baseUrl = GWT.getHostPageBaseURL();
+
+        distanceTable.setWidth100();
+        distanceTable.setShowRecordComponents(true);
+        distanceTable.setShowRecordComponentsByCell(true);
+        distanceTable.setHeight100();
+        distanceTable.setEmptyMessage(MESSAGES.empty_filter());
+        distanceTable.setCanReorderFields(false);
+
+        CellFormatter cf = new CellFormatter() {
+            @Override
+            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();
+                    }
+            }
+        };
+
+        ListGridField addDistance = new ListGridField ("", "");
+        addDistance.setType (ListGridFieldType.ICON);
+        addDistance.setWidth (20);
+        addDistance.addRecordClickHandler (new RecordClickHandler () {
+            @Override
+            public void onRecordClick (RecordClickEvent e) {
+                if (!isLocationMode ()) {
+                    Record r = e.getRecord();
+                    try {
+                        double min = Double.parseDouble(r.getAttribute("from"));
+                        double max = Double.parseDouble(r.getAttribute("to"));
+                        setDistanceValues(min, max);
+                    }
+                    catch(NumberFormatException nfe) {
+                        // Is there anything to do?
+                    }
+                }
+                else {
+                    double[] selected;
+                    Record r = e.getRecord();
+                    double min = 0, max = 0;
+                    try {
+                        min = Double.parseDouble(r.getAttribute("from"));
+                        max = Double.parseDouble(r.getAttribute("to"));
+                    }
+                    catch(NumberFormatException nfe) {
+                        // Is there anything to do?
+                    }
+                    if (getLocationValues() != null) {
+                        double[] val = getLocationValues();
+                        selected = new double[val.length + 2];
+                        for(int i = 0; i < val.length; i++){
+                            selected[i] = val[i];
+                        }
+                        selected[val.length] = min;
+                        selected[val.length + 1] = max;
+                    }
+                    else {
+                        selected = new double[2];
+                        selected[0] = min;
+                        selected[1] = max;
+                    }
+                setLocationValues(selected);
+                }
+            }
+        });
+        addDistance.setCellIcon(baseUrl + MESSAGES.markerGreen());
+
+        ListGridField ddescr = new ListGridField("description",
+                MESSAGES.description());
+        ddescr.setType(ListGridFieldType.TEXT);
+        ddescr.setWidth("*");
+        ListGridField from = new ListGridField("from", MESSAGES.from());
+        from.setCellFormatter(cf);
+
+        from.setWidth("12%");
+        ListGridField to = new ListGridField("to", MESSAGES.to());
+        to.setType(ListGridFieldType.FLOAT);
+        to.setCellFormatter(cf);
+
+        to.setWidth("12%");
+        to.setAlign(Alignment.LEFT);
+        ListGridField dside = new ListGridField("riverside",
+                MESSAGES.riverside());
+        dside.setType(ListGridFieldType.TEXT);
+        dside.setWidth("12%");
+
+        ListGridField bottom =
+            new ListGridField("bottom", MESSAGES.bottom_edge());
+        bottom.setType(ListGridFieldType.TEXT);
+        bottom.setWidth("10%");
+        bottom.setCellFormatter(cf);
+
+        ListGridField top =
+            new ListGridField("top", MESSAGES.top_edge());
+        top.setType(ListGridFieldType.TEXT);
+        top.setWidth("10%");
+        top.setCellFormatter(cf);
+
+        distanceTable.setFields(
+            addDistance, ddescr, from, to, dside, bottom, top);
+    }
+
+
+    /**
+     * This method creates a table that contains the location values.
+     */
+    protected void createLocationTable() {
+
+        String baseUrl = GWT.getHostPageBaseURL();
+
+        locationsTable.setWidth100();
+        locationsTable.setShowRecordComponents(true);
+        locationsTable.setShowRecordComponentsByCell(true);
+        locationsTable.setHeight100();
+        locationsTable.setEmptyMessage(MESSAGES.empty_filter());
+        locationsTable.setCanReorderFields(false);
+
+        CellFormatter cf = new CellFormatter() {
+            @Override
+            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();
+                    }
+                }
+            };
+
+
+
+        ListGridField addLocation = new ListGridField ("", "");
+        addLocation.setType (ListGridFieldType.ICON);
+        addLocation.setWidth (20);
+
+        addLocation.addRecordClickHandler (new RecordClickHandler () {
+            @Override
+            public void onRecordClick (RecordClickEvent e) {
+                Record record = e.getRecord();
+                double[] selected;
+                if (getLocationValues() != null) {
+                    double[] val = getLocationValues();
+                    selected = new double[val.length + 1];
+                    for(int i = 0; i < val.length; i++){
+                        selected[i] = val[i];
+                    }
+                    try {
+                        selected[val.length] =
+                            Double.parseDouble(record.getAttribute("from"));
+                    }
+                    catch(NumberFormatException nfe) {
+                        // Is there anything to do here?
+                    }
+                }
+                else {
+                    selected = new double[1];
+                    selected[0] =
+                        Double.parseDouble(record.getAttribute("from"));
+                }
+                setLocationValues(selected);
+            }
+        });
+        addLocation.setCellIcon (baseUrl + MESSAGES.markerGreen ());
+
+        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("12%");
+        ListGridField loc = new ListGridField("from", MESSAGES.locations());
+        loc.setAlign(Alignment.LEFT);
+        loc.setType(ListGridFieldType.FLOAT);
+        loc.setWidth("12%");
+        loc.setCellFormatter(cf);
+
+        ListGridField bottom =
+            new ListGridField("bottom", MESSAGES.bottom_edge());
+        bottom.setType(ListGridFieldType.TEXT);
+        bottom.setWidth("10%");
+        bottom.setCellFormatter(cf);
+
+        ListGridField top =
+            new ListGridField("top", MESSAGES.top_edge());
+        top.setType(ListGridFieldType.TEXT);
+        top.setWidth("10%");
+        top.setCellFormatter(cf);
+
+        locationsTable.setFields(addLocation, ldescr, loc, lside, bottom, top);
+    }
+
+
+    /**
+     * This method creates a table that contains the location values.
+     */
+    protected void createLocationTableDistance (){
+
+        String baseUrl = GWT.getHostPageBaseURL();
+
+        locationDistanceTable.setWidth100();
+        locationDistanceTable.setShowRecordComponents(true);
+        locationDistanceTable.setShowRecordComponentsByCell(true);
+        locationDistanceTable.setHeight100();
+        locationDistanceTable.setEmptyMessage(MESSAGES.empty_filter());
+        locationDistanceTable.setCanReorderFields(false);
+
+        CellFormatter cf = new CellFormatter() {
+            @Override
+            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();
+                    }
+            }
+        };
+
+        ListGridField addfrom = new ListGridField ("from", MESSAGES.from());
+        addfrom.setType (ListGridFieldType.ICON);
+        addfrom.setWidth (30);
+        addfrom.setCellIcon(baseUrl + MESSAGES.markerGreen());
+
+        ListGridField addto2 = new ListGridField ("to", MESSAGES.to());
+        addto2.setType (ListGridFieldType.ICON);
+        addto2.setWidth (30);
+        addto2.setCellIcon(baseUrl + MESSAGES.markerRed());
+
+        locationDistanceTable.addCellClickHandler (new CellClickHandler () {
+            @Override
+            public void onCellClick (CellClickEvent e) {
+                if (e.getColNum() == 0) {
+                    Record r = e.getRecord ();
+                    try {
+                        double fromvalue =
+                             Double.parseDouble(r.getAttribute("from"));
+                        double tovalue = getTo ();
+                        setDistanceValues (fromvalue, tovalue);
+                    }
+                    catch(NumberFormatException nfe) {
+                        // Is there anything to do in here?
+                    }
+                }
+                else if (e.getColNum() == 1) {
+                    Record r = e.getRecord ();
+                    try {
+                        double fromvalue = getFrom ();
+                        double tovalue =
+                            Double.parseDouble(r.getAttribute("from"));
+                        setDistanceValues (fromvalue, tovalue);
+                    }
+                    catch(NumberFormatException nfe) {
+                        // Is there anything to do in here?
+                    }
+                }
+            }
+        });
+        ListGridField bottom =
+            new ListGridField("bottom", MESSAGES.bottom_edge());
+        bottom.setType(ListGridFieldType.TEXT);
+        bottom.setWidth("10%");
+        bottom.setCellFormatter(cf);
+
+        ListGridField top =
+            new ListGridField("top", MESSAGES.top_edge());
+        top.setType(ListGridFieldType.TEXT);
+        top.setWidth("10%");
+        top.setCellFormatter(cf);
+
+        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("12%");
+        ListGridField loc = new ListGridField("from", MESSAGES.locations());
+        loc.setType(ListGridFieldType.FLOAT);
+        loc.setAlign(Alignment.LEFT);
+        loc.setWidth("12%");
+        loc.setCellFormatter(cf);
+
+        locationDistanceTable.setFields(
+            addfrom, addto2, ldescr, loc, lside, bottom, top);
+    }
+
+
+    @Override
+    public Canvas createOld(DataList dataList) {
+        List<Data> items = dataList.getAll();
+
+        Data       dMode  = getData(items, "ld_mode");
+        DataItem[] dItems = dMode.getItems();
+
+        boolean rangeMode = true;
+        if (dItems != null && dItems[0] != null) {
+            rangeMode = FIELD_VALUE_DISTANCE.equals(dItems[0].getStringValue());
+        }
+
+        HLayout layout = new HLayout();
+        layout.setWidth("400px");
+
+        Label   label  = new Label(dataList.getLabel());
+        label.setWidth("200px");
+
+        Canvas back = getBackButton(dataList.getState());
+
+        layout.addMember(label);
+
+        if (rangeMode) {
+            layout.addMember(getOldRangeSelection(dataList));
+        }
+        else {
+            layout.addMember(getOldLocationSelection(dataList));
+        }
+
+        layout.addMember(back);
+
+        return layout;
+    }
+
+
+    /**
+     * Creates a label for the selected range.
+     *
+     * @param dataList The DataList containing all values for this state.
+     *
+     * @return A label displaying the selected values.
+     */
+    protected Label getOldRangeSelection(DataList dataList) {
+        List<Data> items = dataList.getAll();
+
+        Data dFrom = getData(items, "ld_from");
+        Data dTo   = getData(items, "ld_to");
+        Data dStep = getData(items, "ld_step");
+
+        DataItem[] from = dFrom.getItems();
+        DataItem[] to   = dTo.getItems();
+        DataItem[] step = dStep.getItems();
+
+        StringBuilder sb = new StringBuilder();
+        sb.append(from[0].getLabel());
+        sb.append(" " + MESSAGES.unitFrom() + " ");
+        sb.append(to[0].getLabel());
+        sb.append(" " + MESSAGES.unitTo() + " ");
+        sb.append(step[0].getLabel());
+        sb.append(" " + MESSAGES.unitWidth());
+
+        Label selected = new Label(sb.toString());
+        selected.setWidth("130px");
+
+        return selected;
+    }
+
+
+    /**
+     * Creates a label for the selected locations.
+     *
+     * @param dataList The DataList containing all values for this state.
+     *
+     * @return A label displaying the selected values.
+     */
+    protected Label getOldLocationSelection(DataList dataList) {
+        List<Data> items = dataList.getAll();
+
+        Data       dLocations = getData(items, "ld_locations");
+        DataItem[] lItems     = dLocations.getItems();
+
+        String[] splitted = lItems[0].getStringValue().split(" ");
+        String value = "";
+        for (int i = 0; i < splitted.length; i++) {
+            try {
+                NumberFormat nf = NumberFormat.getDecimalFormat();
+                double dv = Double.parseDouble(splitted[i]);
+                value += nf.format(dv) + " ";
+            }
+            catch(NumberFormatException nfe) {
+                value += splitted[i] + " ";
+            }
+        }
+
+        Label selected = new Label(value);
+        selected.setWidth(130);
+
+        return selected;
+    }
+
+
+    /**
+     * 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 m = getData(list.getAll(), "ld_mode");
+        Data l = getData(list.getAll(), "ld_locations");
+        Data f = getData(list.getAll(), "ld_from");
+        Data t = getData(list.getAll(), "ld_to");
+        Data s = getData(list.getAll(), "ld_step");
+
+        DataItem[] fItems = f.getItems();
+        DataItem[] tItems = t.getItems();
+        DataItem[] sItems = s.getItems();
+
+        min  = Double.valueOf(fItems[0].getStringValue());
+        max  = Double.valueOf(tItems[0].getStringValue());
+        step = Double.valueOf(sItems[0].getStringValue());
+
+        DataItem   mDef   = m.getDefault();
+        DataItem   lDef   = l.getDefault();
+        DataItem   fDef   = f.getDefault();
+        DataItem   tDef   = t.getDefault();
+        DataItem   sDef   = s.getDefault();
+
+        String mDefValue = mDef != null ? mDef.getStringValue() : null;
+        String theMode = mDefValue != null && mDefValue.length() > 0
+            ? mDef.getStringValue()
+            : FIELD_VALUE_DISTANCE;
+
+        mode.setValue(FIELD_MODE, theMode);
+
+        String fDefValue = fDef != null ? fDef.getStringValue() : null;
+        setFrom(fDefValue != null && fDefValue.length() > 0
+            ? Double.valueOf(fDef.getStringValue())
+            : min);
+
+        String tDefValue = tDef != null ? tDef.getStringValue() : null;
+        setTo(tDefValue != null && tDefValue.length() > 0
+            ? Double.valueOf(tDef.getStringValue())
+            : max);
+
+        String sDefValue = sDef != null ? sDef.getStringValue() : null;
+        setStep(sDefValue != null && sDefValue.length() > 0
+            ? Double.valueOf(sDef.getStringValue())
+            : step);
+
+        if (lDef != null) {
+            String lDefValue = lDef != null ? lDef.getStringValue() : null;
+
+            if (lDefValue != null && lDefValue.length() > 0) {
+                setLocationValues(lDef.getStringValue());
+            }
+        }
+
+        if (theMode.equals(FIELD_VALUE_DISTANCE)) {
+            enableDistancePanel();
+            inputTables.selectTab(1);
+        }
+        currentFiltered = (ListGrid)inputTables.getSelectedTab().getPane();
+    }
+
+
+    protected Canvas createWidget(DataList data) {
+        VLayout layout       = new VLayout();
+        container            = new HLayout();
+        Canvas checkboxPanel = createRadioButtonPanel();
+
+        // the initial view will display the location input mode
+        locationPanel = new DoubleArrayPanel(
+                MESSAGES.unitLocation(),
+                getLocationValues(),
+                this);
+        container.addMember(locationPanel);
+
+        layout.addMember(checkboxPanel);
+        layout.addMember(container);
+
+        container.setMembersMargin(30);
+
+        inputTables   = new TabSet();
+        inputTables.addTabSelectedHandler(new TabSelectedHandler() {
+            @Override
+            public void onTabSelected(TabSelectedEvent evt) {
+                filterDescription.clear();
+                filterRange.clear();
+                filterResultCount.setValue("");
+
+                Canvas c = evt.getTabPane();
+                if(c instanceof ListGrid) {
+                    currentFiltered = (ListGrid)c;
+                }
+            }
+        });
+
+        Tab locations = new Tab(MESSAGES.locations());
+        Tab distances = new Tab(MESSAGES.distance());
+
+        inputTables.setWidth100();
+        inputTables.setHeight100();
+
+        locations.setPane(locationDistanceTable);
+        distances.setPane(distanceTable);
+
+        inputTables.addTab(locations);
+        inputTables.addTab(distances);
+
+        filterResultCount = new StaticTextItem(MESSAGES.resultCount());
+        filterResultCount.setTitleAlign(Alignment.LEFT);
+        filterResultCount.setTitleStyle("color: #000");
+
+        filterDescription = new TableFilter();
+        filterDescription.setHeight("30px");
+        filterDescription.addFilterHandler(this);
+
+        filterRange = new RangeTableFilter();
+        filterRange.setHeight("30px");
+        filterRange.addFilterHandler(this);
+        filterRange.setVisible(false);
+
+        filterCriteria = new SelectItem();
+        filterCriteria.setShowTitle(false);
+        filterCriteria.setWidth(100);
+        filterCriteria.addChangedHandler(new ChangedHandler() {
+            @Override
+            public void onChanged(ChangedEvent e) {
+                if(e.getValue().toString().equals("range")) {
+                    filterRange.setVisible(true);
+                    filterDescription.setVisible(false);
+                    filterDescription.clear();
+                    filterResultCount.setValue("");
+                }
+                else {
+                    filterRange.setVisible(false);
+                    filterRange.clear();
+                    filterDescription.setVisible(true);
+                    filterResultCount.setValue("");
+                }
+            }
+        });
+
+        LinkedHashMap<String, String> filterMap =
+            new LinkedHashMap<String, String>();
+        filterMap.put("description", MESSAGES.description());
+        filterMap.put("range", MESSAGES.range());
+        filterCriteria.setValueMap(filterMap);
+        filterCriteria.setValue("description");
+
+        DynamicForm form = new DynamicForm();
+        form.setFields(filterCriteria);
+        inputTables.setHeight("*");
+        DynamicForm form2 = new DynamicForm();
+        form2.setFields(filterResultCount);
+
+        VLayout helper = new VLayout();
+        HLayout filterLayout = new HLayout();
+
+        filterLayout.addMember(form);
+        filterLayout.addMember(filterDescription);
+        filterLayout.addMember(filterRange);
+        filterLayout.setHeight("30px");
+        helper.addMember(inputTables);
+        helper.addMember(filterLayout);
+        helper.addMember(form2);
+        helper.setHeight100();
+        helper.setWidth100();
+
+        helperContainer.addMember(helper);
+        filterLayout.setWidth("200");
+
+        return layout;
+    }
+
+
+    @Override
+    public void onFilterCriteriaChanged(StringFilterEvent event) {
+        String search = event.getFilter();
+
+        if (search != null && search.length() > 0) {
+            Criteria c = new Criteria("description", search);
+
+            locationsTable.filterData(c);
+            distanceTable.filterData(c);
+            locationDistanceTable.filterData(c);
+            filterResultCount.setValue(currentFiltered.getRecords().length);
+        }
+        else {
+            locationsTable.clearCriteria();
+            distanceTable.clearCriteria();
+            locationDistanceTable.clearCriteria();
+            filterResultCount.setValue("");
+        }
+    }
+
+
+    @Override
+    public void onFilterCriteriaChanged(RangeFilterEvent event) {
+        Float from = event.getFrom() - 0.001f;
+        Float to = event.getTo() + 0.001f;
+        GWT.log("filtering range: " + from + " to " + to);
+
+
+        Criterion combinedFilter = null;
+        Criterion locationFilter = null;
+        if (from.equals(Float.NaN) && to.equals(Float.NaN)) {
+            locationsTable.clearCriteria();
+            distanceTable.clearCriteria();
+            locationDistanceTable.clearCriteria();
+            filterResultCount.setValue("");
+            return;
+        }
+        else if (from.equals(Float.NaN)) {
+            combinedFilter = new Criterion("to", OperatorId.LESS_OR_EQUAL, to);
+            locationFilter =
+                new Criterion("from", OperatorId.LESS_OR_EQUAL, to);
+            locationsTable.filterData(locationFilter);
+            distanceTable.filterData(combinedFilter);
+            locationDistanceTable.filterData(combinedFilter);
+            filterResultCount.setValue(currentFiltered.getRecords().length);
+            return;
+        }
+        else if (to.equals(Float.NaN)) {
+            combinedFilter =
+                new Criterion("from", OperatorId.GREATER_OR_EQUAL, from);
+             locationsTable.filterData(combinedFilter);
+            distanceTable.filterData(combinedFilter);
+            locationDistanceTable.filterData(combinedFilter);
+        }
+        else {
+            AdvancedCriteria c1 =
+                new AdvancedCriteria(OperatorId.AND, new Criterion[] {
+                    new Criterion("from", OperatorId.GREATER_OR_EQUAL, from),
+                    new Criterion("from", OperatorId.LESS_OR_EQUAL, to)
+                });
+
+            AdvancedCriteria c2 =
+                new AdvancedCriteria(OperatorId.AND, new Criterion[] {
+                    new Criterion("to", OperatorId.GREATER_OR_EQUAL, from),
+                    new Criterion("to", OperatorId.LESS_OR_EQUAL, to)
+                });
+
+            AdvancedCriteria c3 =
+                new AdvancedCriteria(OperatorId.AND, new Criterion[] {
+                    new Criterion("from", OperatorId.LESS_OR_EQUAL, to),
+                    new Criterion("to", OperatorId.GREATER_OR_EQUAL, from)
+                });
+
+            combinedFilter =
+                new AdvancedCriteria(OperatorId.OR, new Criterion[] {
+                    c1, c2, c3
+                });
+        }
+        locationsTable.filterData(combinedFilter);
+        distanceTable.filterData(combinedFilter);
+        locationDistanceTable.filterData(combinedFilter);
+        filterResultCount.setValue(currentFiltered.getRecords().length);
+    }
+
+
+    @Override
+    public List<String> validate() {
+        if (isLocationMode()) {
+            return validateLocations();
+        }
+        else {
+            return validateRange();
+        }
+    }
+
+
+    protected List<String> validateLocations() {
+        List<String> errors = new ArrayList<String>();
+        NumberFormat nf     = NumberFormat.getDecimalFormat();
+
+        try {
+            saveLocationValues(locationPanel);
+        }
+        catch (Exception e) {
+            errors.add(MESSAGES.wrongFormat());
+        }
+
+        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;
+    }
+
+
+    protected List<String> validateRange() {
+        List<String> errors = new ArrayList<String>();
+        NumberFormat nf     = NumberFormat.getDecimalFormat();
+
+        try {
+            saveDistanceValues(distancePanel);
+        }
+        catch (Exception e) {
+            errors.add(MESSAGES.wrongFormat());
+        }
+
+        double from = getFrom();
+        double to   = getTo();
+        double step = getStep();
+
+        if (from < min || from > max) {
+            String tmp = MESSAGES.error_validate_lower_range();
+            tmp = tmp.replace("$1", nf.format(from));
+            tmp = tmp.replace("$2", nf.format(min));
+            errors.add(tmp);
+            from = min;
+        }
+
+        if (to < min || to > max) {
+            String tmp = MESSAGES.error_validate_upper_range();
+            tmp = tmp.replace("$1", nf.format(to));
+            tmp = tmp.replace("$2", nf.format(max));
+            errors.add(tmp);
+            to = max;
+        }
+
+        if (!errors.isEmpty()) {
+            distancePanel.setValues(from, to, step);
+        }
+
+        return errors;
+    }
+
+
+    /**
+     * This method returns the selected data.
+     *
+     * @return the selected/inserted data.
+     */
+    @Override
+    public Data[] getData() {
+        List<Data> data = new ArrayList<Data>();
+
+        // If we have entered a value and click right afterwards on the
+        // 'next' button, the BlurEvent is not fired, and the values are not
+        // saved. So, we gonna save those values explicitly.
+        if (isLocationMode()) {
+            Canvas member = container.getMember(0);
+            if (member instanceof DoubleArrayPanel) {
+                DoubleArrayPanel form = (DoubleArrayPanel) member;
+                saveLocationValues(form);
+            }
+
+            Data dLocations = getDataLocations();
+            DataItem dFrom  = new DefaultDataItem("ld_from", "ld_from", "");
+            DataItem dTo    = new DefaultDataItem("ld_to", "ld_to", "");
+            DataItem dStep  = new DefaultDataItem("ld_step", "ld_step", "");
+
+            data.add(dLocations);
+            data.add(new DefaultData(
+                "ld_from", null, null, new DataItem[] { dFrom } ));
+            data.add(new DefaultData(
+                "ld_to", null, null, new DataItem[] { dTo } ));
+            data.add(new DefaultData(
+                "ld_step", null, null, new DataItem[] { dStep } ));
+        }
+        else {
+            Canvas member = container.getMember(0);
+            if (member instanceof DoubleRangePanel) {
+                DoubleRangePanel form = (DoubleRangePanel) member;
+                saveDistanceValues(form);
+            }
+
+            Data dFrom   = getDataFrom();
+            Data dTo     = getDataTo();
+            Data dStep   = getDataStep();
+            DataItem loc = new DefaultDataItem("ld_locations", "ld_locations","");
+
+            data.add(dFrom);
+            data.add(dTo);
+            data.add(dStep);
+            data.add(new DefaultData(
+                "ld_locations", null, null, new DataItem[] { loc } ));
+        }
+
+        Data dMode = getDataMode();
+        if (dMode != null) {
+            data.add(dMode);
+        }
+
+        return data.toArray(new Data[data.size()]);
+    }
+
+
+    /**
+     * Returns the Data object for the 'mode' attribute.
+     *
+     * @return the Data object for the 'mode' attribute.
+     */
+    protected Data getDataMode() {
+        String   value = mode.getValueAsString(FIELD_MODE);
+        DataItem item  = new DefaultDataItem("ld_mode", "ld_mode", value);
+        return new DefaultData("ld_mode", null, null, new DataItem[] { item });
+    }
+
+
+    protected Data getDataLocations() {
+        double[] locations = getLocationValues();
+        boolean  first     = true;
+
+        if (locations == null) {
+            return null;
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        for (double l: locations) {
+            if (!first) {
+                sb.append(" ");
+            }
+
+            sb.append(l);
+
+            first = false;
+        }
+
+        DataItem item = new DefaultDataItem(
+            "ld_locations",
+            "ld_locations",
+            sb.toString());
+
+        return new DefaultData(
+            "ld_locations",
+            null,
+            null,
+            new DataItem[] { item });
+    }
+
+
+    /**
+     * Returns the Data object for the 'from' attribute.
+     *
+     * @return the Data object for the 'from' attribute.
+     */
+    protected Data getDataFrom() {
+        String value  = Double.valueOf(getFrom()).toString();
+        DataItem item = new DefaultDataItem("ld_from", "ld_from", value);
+        return new DefaultData(
+            "ld_from", null, null, new DataItem[] { item });
+    }
+
+
+    /**
+     * Returns the Data object for the 'to' attribute.
+     *
+     * @return the Data object for the 'to' attribute.
+     */
+    protected Data getDataTo() {
+        String value  = Double.valueOf(getTo()).toString();
+        DataItem item = new DefaultDataItem("ld_to", "ld_to", value);
+        return new DefaultData(
+            "ld_to", null, null, new DataItem[] { item });
+    }
+
+
+    /**
+     * Returns the Data object for the 'step' attribute.
+     *
+     * @return the Data object for the 'step' attribute.
+     */
+    protected Data getDataStep() {
+        String value  = Double.valueOf(getStep()).toString();
+        DataItem item = new DefaultDataItem("ld_step","ld_step", value);
+        return new DefaultData(
+            "ld_step", null, null, new DataItem[] { item });
+    }
+
+
+    /**
+     * Determines the current input mode.
+     *
+     * @return true, if 'location' is the current input mode, otherwise false.
+     */
+    public boolean isLocationMode() {
+        String inputMode = mode.getValueAsString(FIELD_MODE);
+
+        return inputMode.equals(FIELD_VALUE_LOCATION) ? true : false;
+    }
+
+
+    /**
+     * Activates the location panel.
+     */
+    protected void enableLocationPanel() {
+        locationPanel = new DoubleArrayPanel(
+            MESSAGES.unitLocation(),
+            getLocationValues(),
+            this);
+
+        container.removeMembers(container.getMembers());
+        container.addMember(locationPanel);
+    }
+
+
+    /**
+     * Activates the distance panel.
+     */
+    protected void enableDistancePanel() {
+        distancePanel = new DoubleRangePanel(
+            MESSAGES.unitFrom(), MESSAGES.unitTo(), MESSAGES.unitWidth(),
+            getFrom(), getTo(), getStep(),
+            400,
+            this);
+
+        container.removeMembers(container.getMembers());
+        container.addMember(distancePanel);
+    }
+
+
+    /**
+     * This method switches the input mode between location and distance input.
+     *
+     * @param event The click event fired by a RadioButtonGroupItem.
+     */
+    @Override
+    public void onChange(ChangeEvent event) {
+        String value = (String) event.getValue();
+
+        if (value == null) {
+            return;
+        }
+        if (value.equals(FIELD_VALUE_LOCATION)) {
+            enableLocationPanel();
+            filterDescription.clear();
+            filterRange.clear();
+            filterResultCount.setValue("");
+
+            // Remove the tab containing the locationDistanceTable.
+            // The 'updateTab()' avoids the tab content to be destroyed.
+            inputTables.updateTab(0, null);
+            inputTables.removeTab(0);
+
+            // Create a new tab containing the locationTable
+            Tab t1 = new Tab (MESSAGES.locations());
+            t1.setPane(locationsTable);
+            inputTables.addTab(t1, 0);
+
+            // Bring this tab to front.
+            inputTables.selectTab(0);
+        }
+        else {
+            enableDistancePanel();
+            filterDescription.clear();
+            filterRange.clear();
+            filterResultCount.setValue("");
+
+            // Remove the tab containing the locationTable.
+            // The 'updateTab()' avoids the tab content to be destroyed.
+            inputTables.updateTab(0, null);
+            inputTables.removeTab(0);
+
+            // Create a new tab containing the locationDistanceTable.
+            Tab t1 = new Tab(MESSAGES.locations());
+            t1.setPane(locationDistanceTable);
+            inputTables.addTab(t1, 0);
+
+            // Bring the distanceTable tab to front.
+            inputTables.selectTab(1);
+        }
+    }
+
+
+    /**
+     * This method is used to validate the inserted data in the form fields.
+     *
+     * @param event The BlurEvent that gives information about the FormItem that
+     * has been modified and its value.
+     */
+    @Override
+    public void onBlur(BlurEvent event) {
+        FormItem item = event.getItem();
+        String  field = item.getFieldName();
+
+        if (field == null) {
+            return;
+        }
+
+        if (field.equals(DoubleArrayPanel.FIELD_NAME)) {
+            DoubleArrayPanel p = (DoubleArrayPanel) event.getForm();
+
+            saveLocationValue(p, item);
+        }
+        else {
+            DoubleRangePanel p = (DoubleRangePanel) event.getForm();
+
+            saveDistanceValue(p, item);
+        }
+    }
+
+
+
+    /**
+     * 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 all values entered in the distance mode.
+     *
+     * @param p The DoubleRangePanel.
+     */
+    protected void saveDistanceValues(DoubleRangePanel p) {
+        FormItem[] formItems = p.getFields();
+
+        for (FormItem item: formItems) {
+            saveDistanceValue(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));
+        }
+    }
+
+
+    /**
+     * Validates and stores value entered in the distance mode.
+     *
+     * @param p The DoubleRangePanel.
+     * @param item The item that needs to be validated.
+     */
+    protected void saveDistanceValue(DoubleRangePanel p, FormItem item) {
+        if (p.validateForm(item)) {
+            setFrom(p.getFrom());
+            setTo(p.getTo());
+            setStep(p.getStep());
+        }
+    }
+
+
+    /**
+     * This method creates the panel that contains the checkboxes to switch
+     * between the input mode 'location' and 'distance'.
+     *
+     * @return the checkbox panel.
+     */
+    protected Canvas createRadioButtonPanel() {
+        mode = new DynamicForm();
+
+        RadioGroupItem radio = new RadioGroupItem(FIELD_MODE);
+        radio.setShowTitle(false);
+        radio.setVertical(false);
+        radio.setWrap(false);
+
+        LinkedHashMap<String, String> values = new LinkedHashMap<String, String>();
+        values.put(FIELD_VALUE_LOCATION, MESSAGES.location());
+        values.put(FIELD_VALUE_DISTANCE, MESSAGES.distance());
+
+        LinkedHashMap<String, String> initial = new LinkedHashMap<String, String>();
+        initial.put(FIELD_MODE, FIELD_VALUE_DISTANCE);
+
+        radio.setValueMap(values);
+        radio.addChangeHandler(this);
+
+        mode.setFields(radio);
+        mode.setValues(initial);
+
+        return mode;
+    }
+
+
+    protected void createDistanceInputPanel() {
+        Config config = Config.getInstance();
+        String url    = config.getServerUrl();
+        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().endsWith("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();
+                        }
+                    }
+                }
+            }
+        }
+
+        distanceTable.setDataSource(new DistanceInfoDataSource(
+            url, river, "distances"));
+        locationsTable.setDataSource(new DistanceInfoDataSource(
+            url, river, "locations"));
+        locationDistanceTable.setDataSource(new DistanceInfoDataSource(
+            url, river, "locations"));
+    }
+
+
+    protected double getFrom() {
+        return from;
+    }
+
+
+    protected void setFrom(double from) {
+        this.from = from;
+    }
+
+
+    protected double getTo() {
+        return to;
+    }
+
+
+    protected void setTo(double to) {
+        this.to = to;
+    }
+
+
+    protected double getStep() {
+        return step;
+    }
+
+
+    protected void setStep(double step) {
+        this.step = step;
+    }
+
+
+    protected double[] getLocationValues() {
+        return values;
+    }
+
+
+    protected void setLocationValues(double[] values) {
+        this.values = values;
+        locationPanel.setValues(values);
+    }
+
+
+    protected void setLocationValues(String values) {
+        String[] vs = values.split(" ");
+
+        if (vs == null) {
+            return;
+        }
+
+        double[] ds  = new double[vs.length];
+        int      idx = 0;
+
+        for (String s: vs) {
+            try {
+                ds[idx++] = Double.valueOf(s);
+            }
+            catch (NumberFormatException nfe) {
+                // do nothing
+            }
+        }
+
+        setLocationValues(ds);
+    }
+
+
+    protected void setDistanceValues (double from, double to) {
+        setFrom(from);
+        setTo(to);
+        distancePanel.setValues(from, to, getStep());
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org