changeset 1612:66671b69c7ea

Added new UIProvider to enter mutliple locations (yet only input view textfield possible). flys-client/trunk@3979 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Wed, 08 Feb 2012 16:24:39 +0000
parents 87572e476f7a
children 2eec6d55fcfa
files flys-client/ChangeLog flys-client/src/main/java/de/intevation/flys/client/client/ui/LocationPanel.java flys-client/src/main/java/de/intevation/flys/client/client/ui/MultipleLocationPanel.java flys-client/src/main/java/de/intevation/flys/client/client/ui/SingleLocationPanel.java flys-client/src/main/java/de/intevation/flys/client/client/ui/UIProviderFactory.java
diffstat 5 files changed, 372 insertions(+), 199 deletions(-) [+]
line wrap: on
line diff
--- a/flys-client/ChangeLog	Wed Feb 08 16:20:30 2012 +0000
+++ b/flys-client/ChangeLog	Wed Feb 08 16:24:39 2012 +0000
@@ -1,3 +1,24 @@
+2012-02-08	Felix Wolfsteller	<felix.wolfsteller@intevation.de>
+
+	New UIProvider to enter multiple locations (so far only via keyboard).
+
+	* src/main/java/de/intevation/flys/client/client/ui/MultipleLocationPanel.java,
+	  src/main/java/de/intevation/flys/client/client/ui/LocationPanel.java,
+	  src/main/java/de/intevation/flys/client/client/ui/SingleLocationPanel.java:
+	  Refactored. New UIProvider does allow and provide multiple values,
+	  which are whitespace separated in data item.
+
+	* src/main/java/de/intevation/flys/client/client/ui/UIProviderFactory.java:
+	  Serve the new UIProvider if somebody orders it.
+
+2012-02-08	Felix Wolfsteller	<felix.wolfsteller@intevation.de>
+
+	* src/main/java/de/intevation/flys/client/client/FLYSConstants_en.properties,
+	  src/main/java/de/intevation/flys/client/client/FLYSConstants.properties,
+	  src/main/java/de/intevation/flys/client/client/FLYSConstants_de.properties,
+	  src/main/java/de/intevation/flys/client/client/FLYSConstants.java: Added
+	  missing translation for "waterlevels" used in the datacage window.
+
 2012-02-08	Felix Wolfsteller	<felix.wolfsteller@intevation.de>
 
 	* src/main/java/de/intevation/flys/client/server/ChartInfoServiceImpl.java,
--- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/LocationPanel.java	Wed Feb 08 16:20:30 2012 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/LocationPanel.java	Wed Feb 08 16:24:39 2012 +0000
@@ -255,10 +255,6 @@
         double[] good   = new double[values.length];
         int      idx    = 0;
 
-        if (values.length > 1) {
-            errors.add(MSG.too_many_values());
-        }
-
         for (double value: values) {
             if (value < min || value > max) {
                 String tmp = MSG.error_validate_range();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/MultipleLocationPanel.java	Wed Feb 08 16:24:39 2012 +0000
@@ -0,0 +1,303 @@
+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.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+
+import com.smartgwt.client.data.Record;
+
+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.DistanceInfoObject;
+import de.intevation.flys.client.shared.model.RangeData;
+
+import de.intevation.flys.client.client.services.DistanceInfoService;
+import de.intevation.flys.client.client.services.DistanceInfoServiceAsync;
+import de.intevation.flys.client.client.Config;
+import de.intevation.flys.client.client.ui.range.DistanceInfoDataSource;
+
+
+/**
+ * This UIProvider creates a widget to enter a single location (km).
+ *
+ * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
+ */
+public class MultipleLocationPanel
+extends      LocationPanel
+implements   RecordClickHandler
+{
+    /** The DistanceInfoService used to retrieve locations about rivers. */
+    protected DistanceInfoServiceAsync distanceInfoService =
+        GWT.create(DistanceInfoService.class);
+
+    /** The table data. */
+    protected DistanceInfoObject[] tableData;
+
+    /** The input helper (usually right side, table to click on, values are
+     * then entered in the texfield. */
+    protected LocationPicker picker;
+
+    /**
+     * Creates a new LocationDistancePanel instance.
+     */
+    public MultipleLocationPanel() {
+        picker = new LocationPicker(this);
+    }
+
+
+    /**
+     * 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 mode specific panel.
+     *
+     * @param data The data that might be inserted.
+     *
+     * @return a panel.
+     */
+    @Override
+    public Canvas create(DataList data) {
+        findDataItemName(data);
+
+        VLayout layout = new VLayout();
+        layout.setMembersMargin(10);
+
+        Label label   = new Label(MSG.location ());
+        Canvas widget = createWidget(data);
+        Canvas submit = getNextButton();
+
+        initDefaults(data);
+
+        picker.createLocationTable();
+
+        widget.setHeight(50);
+        label.setHeight(25);
+
+        layout.addMember(label);
+        layout.addMember(widget);
+        layout.addMember(submit);
+
+        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);
+
+        // Compatibility with MinMax- DataItems:
+        RangeData rangeData = null;
+
+        for (int i = 0, n = list.size(); i < n; i++) {
+            Data tmp = list.get(i);
+
+            if (tmp instanceof RangeData) {
+                rangeData = (RangeData) tmp;
+            }
+        }
+
+        if (rangeData != null) {
+            min = Double.parseDouble(rangeData.getDefaultLower().toString());
+            max = Double.parseDouble(rangeData.getDefaultUpper().toString());
+            // catch ..?
+        }
+        else {
+            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(MSG.error_read_minmax_values());
+                min = -Double.MAX_VALUE;
+                max = Double.MAX_VALUE;
+            }
+        }
+
+        DataItem def = data.getDefault();
+        if (def != null) {
+            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
+            }
+        }
+    }
+
+
+    protected Canvas createWidget(DataList data) {
+        VLayout layout = new VLayout();
+        inputLayout    = new HLayout();
+
+        // The initial view will display the location input mode.
+        locationPanel = new DoubleArrayPanel(
+            MSG.unitLocation(),
+            getLocationValues(),
+            new BlurHandler(){public void onBlur(BlurEvent be) {}});
+
+        picker.getLocationTable().setAutoFetchData(true);
+
+        inputLayout.addMember(locationPanel);
+
+        layout.addMember(inputLayout);
+
+        inputLayout.setMembersMargin(30);
+
+        picker.prepareFilter();
+
+        helperContainer.addMember(picker.getLocationTable());
+        helperContainer.addMember(picker.getFilterLayout());
+        helperContainer.addMember(picker.getResultCountForm());
+        setPickerDataSource();
+        return layout;
+    }
+
+
+    /** Overridden to restrict to one entered value. */
+    @Override
+    public List<String> validate() {
+        List<String> errors = new ArrayList<String>();
+        NumberFormat nf     = NumberFormat.getDecimalFormat();
+
+        saveLocationValues(locationPanel);
+
+        if (!locationPanel.validateForm()) {
+            errors.add(MSG.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 = MSG.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[2];
+        boolean  first       = true;
+        String   valueString = "";
+
+        for (int i = 0; i < values.length; i++) {
+            if (!first) valueString += " ";
+            else first = false;
+            valueString += Double.valueOf(values[i]).toString();
+        }
+
+        data[0] = createDataArray(getDataItemName(), valueString);
+
+        data[1] = createDataArray("ld_mode", "locations");
+
+        return data;
+    }
+
+
+    /** Hook service to the listgrid with possible input values. */
+    protected void setPickerDataSource() {
+        Config config = Config.getInstance();
+        String url    = config.getServerUrl();
+        String river  = "";
+
+        ArtifactDescription adescr = artifact.getArtifactDescription();
+        DataList[] data = adescr.getOldData();
+
+        // Try to find a "river" data item to set the source for the
+        // list grid.
+        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") ||
+                    dl.getState().equals("state.chart.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;
+                        }
+                    }
+                }
+            }
+        }
+
+        picker.getLocationTable().setDataSource(new DistanceInfoDataSource(
+            url, river, "locations"));
+    }
+
+    // TODO allow multiple selections here or in LocationPanel
+    /**
+     * Callback when an item from the input helper was clicked.
+     * Set the respective km-value in the location value field.
+     * @param e event passed.
+     */
+    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);
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/SingleLocationPanel.java	Wed Feb 08 16:20:30 2012 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/SingleLocationPanel.java	Wed Feb 08 16:24:39 2012 +0000
@@ -1,54 +1,19 @@
 package de.intevation.flys.client.client.ui;
 
-import com.google.gwt.core.client.GWT;
-
-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.layout.HLayout;
-import com.smartgwt.client.widgets.layout.VLayout;
+import java.util.ArrayList;
+import java.util.List;
 
-import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
-import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+import com.google.gwt.i18n.client.NumberFormat;
 
-import com.smartgwt.client.data.Record;
-
-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.DistanceInfoObject;
-import de.intevation.flys.client.shared.model.RangeData;
-
-import de.intevation.flys.client.client.services.DistanceInfoService;
-import de.intevation.flys.client.client.services.DistanceInfoServiceAsync;
-import de.intevation.flys.client.client.Config;
-import de.intevation.flys.client.client.ui.range.DistanceInfoDataSource;
 
 
 /**
  * This UIProvider creates a widget to enter a single location (km).
- *
- * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
  */
 public class SingleLocationPanel
-extends      LocationPanel
-implements   RecordClickHandler
+extends      MultipleLocationPanel
 {
-    /** The DistanceInfoService used to retrieve locations about rivers. */
-    protected DistanceInfoServiceAsync distanceInfoService =
-        GWT.create(DistanceInfoService.class);
-
-    /** The table data. */
-    protected DistanceInfoObject[] tableData;
-
-    /** The input helper (usually right side, table to click on, values are
-     * then entered in the texfield. */
-    protected LocationPicker picker;
-
     /**
      * Creates a new LocationDistancePanel instance.
      */
@@ -57,122 +22,51 @@
     }
 
 
-    /**
-     * 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 mode specific panel.
-     *
-     * @param data The data that might be inserted.
-     *
-     * @return a panel.
-     */
+    /** Overridden to restrict to one entered value. */
     @Override
-    public Canvas create(DataList data) {
-        findDataItemName(data);
-
-        VLayout layout = new VLayout();
-        layout.setMembersMargin(10);
-
-        Label label   = new Label(MSG.location ());
-        Canvas widget = createWidget(data);
-        Canvas submit = getNextButton();
-
-        initDefaults(data);
-
-        picker.createLocationTable();
+    public List<String> validate() {
+        List<String> errors = new ArrayList<String>();
+        NumberFormat nf     = NumberFormat.getDecimalFormat();
 
-        widget.setHeight(50);
-        label.setHeight(25);
-
-        layout.addMember(label);
-        layout.addMember(widget);
-        layout.addMember(submit);
-
-        return layout;
-    }
-
+        saveLocationValues(locationPanel);
 
-    /**
-     * 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 (!locationPanel.validateForm()) {
+            errors.add(MSG.wrongFormat());
+            return errors;
+        }
 
-        // Compatibility with MinMax- DataItems:
-        RangeData rangeData = null;
+        double[] values = getLocationValues();
+        double[] good   = new double[values.length];
+        int      idx    = 0;
 
-        for (int i = 0, n = list.size(); i < n; i++) {
-            Data tmp = list.get(i);
+        // We want just one value to be allowed.
+        if (values.length > 1) {
+            errors.add(MSG.too_many_values());
+        }
 
-            if (tmp instanceof RangeData) {
-                rangeData = (RangeData) tmp;
+        for (double value: values) {
+            if (value < min || value > max) {
+                String tmp = MSG.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;
             }
         }
 
-        if (rangeData != null) {
-            min = Double.parseDouble(rangeData.getDefaultLower().toString());
-            max = Double.parseDouble(rangeData.getDefaultUpper().toString());
-            // catch ..?
-        }
-        else {
-            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(MSG.error_read_minmax_values());
-                min = -Double.MAX_VALUE;
-                max = Double.MAX_VALUE;
-            }
+        double[] justGood = new double[idx];
+        for (int i = 0; i < justGood.length; i++) {
+            justGood[i] = good[i];
         }
 
-        DataItem def = data.getDefault();
-        if (def != null) {
-            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
-            }
+        if (!errors.isEmpty()) {
+            locationPanel.setValues(justGood);
         }
-    }
-
-
-    protected Canvas createWidget(DataList data) {
-        VLayout layout = new VLayout();
-        inputLayout    = new HLayout();
 
-        // The initial view will display the location input mode.
-        locationPanel = new DoubleArrayPanel(
-            MSG.unitLocation(),
-            getLocationValues(),
-            new BlurHandler(){public void onBlur(BlurEvent be) {}});
-
-        picker.getLocationTable().setAutoFetchData(true);
-
-        inputLayout.addMember(locationPanel);
-
-        layout.addMember(inputLayout);
-
-        inputLayout.setMembersMargin(30);
-
-        picker.prepareFilter();
-
-        helperContainer.addMember(picker.getLocationTable());
-        helperContainer.addMember(picker.getFilterLayout());
-        helperContainer.addMember(picker.getResultCountForm());
-        setPickerDataSource();
-        return layout;
+        return errors;
     }
 
 
@@ -183,68 +77,17 @@
      */
     public Data[] getData() {
         saveLocationValues(locationPanel);
-        double[] values = getLocationValues();
+        double[] values      = getLocationValues();
         Data[] data = new Data[values.length+1];
 
         for (int i = 0; i < values.length; i++) {
             data[i] = createDataArray(getDataItemName(),
                 Double.valueOf(values[i]).toString());
         }
+
         data[values.length] = createDataArray("ld_mode", "locations");
 
         return data;
     }
-
-
-    /** Hook service to the listgrid with possible input values. */
-    protected void setPickerDataSource() {
-        Config config = Config.getInstance();
-        String url    = config.getServerUrl();
-        String river  = "";
-
-        ArtifactDescription adescr = artifact.getArtifactDescription();
-        DataList[] data = adescr.getOldData();
-
-        // Try to find a "river" data item to set the source for the
-        // list grid.
-        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") ||
-                    dl.getState().equals("state.chart.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;
-                        }
-                    }
-                }
-            }
-        }
-
-        picker.getLocationTable().setDataSource(new DistanceInfoDataSource(
-            url, river, "locations"));
-    }
-
-
-    /**
-     * Callback when an item from the input helper was clicked.
-     * Set the respective km-value in the location value field.
-     * @param e event passed.
-     */
-    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);
-    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/UIProviderFactory.java	Wed Feb 08 16:20:30 2012 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/UIProviderFactory.java	Wed Feb 08 16:24:39 2012 +0000
@@ -2,6 +2,13 @@
 
 import de.intevation.flys.client.shared.model.User;
 
+
+/**
+ * Depending on the provider the state declared, return a UIProvider.
+ *
+ * A UIProvider provides widgets and input helpers to guide input to an
+ * artifacts state.
+ */
 public class UIProviderFactory {
 
     private UIProviderFactory() {
@@ -20,6 +27,9 @@
         else if (uiProvider.equals("location_panel")) {
             return new SingleLocationPanel();
         }
+        else if (uiProvider.equals("multi_location_panel")) {
+            return new MultipleLocationPanel();
+        }
         else if (uiProvider.equals("distance_panel")) {
             return new DistancePanel();
         }

http://dive4elements.wald.intevation.org