changeset 41:87a44f8e25cc

Added a new widget that enables the user to enter a location or a distance in a single step. flys-client/trunk@1482 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Wed, 16 Mar 2011 09:57:41 +0000
parents 1458bc0a20e2
children ba7df4a24ae0
files flys-client/ChangeLog flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages.java flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages_de.properties flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages_en.properties flys-client/src/main/java/de/intevation/flys/client/client/ui/AbstractUIProvider.java flys-client/src/main/java/de/intevation/flys/client/client/ui/LocationDistancePanel.java flys-client/src/main/java/de/intevation/flys/client/client/ui/UIProviderFactory.java
diffstat 7 files changed, 501 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/flys-client/ChangeLog	Tue Mar 15 14:55:47 2011 +0000
+++ b/flys-client/ChangeLog	Wed Mar 16 09:57:41 2011 +0000
@@ -1,3 +1,24 @@
+2011-03-16  Ingo Weinzierl <ingo@intevation.de>
+
+	* src/main/java/de/intevation/flys/client/client/FLYSMessages_en.properties,
+	  src/main/java/de/intevation/flys/client/client/FLYSMessages_de.properties,
+	  src/main/java/de/intevation/flys/client/client/FLYSMessages.java: Added
+	  i18n strings used in the LocationDistancePanel.
+
+	* src/main/java/de/intevation/flys/client/client/ui/AbstractUIProvider.java:
+	  New. This abstract class implements the UIProvider and the
+	  HasStepForwardHandlers interface and its necessary methods. These two
+	  things are required by each concrete UIProvider, so this class should be
+	  the base class for further concrete UIProviders.
+
+	* src/main/java/de/intevation/flys/client/client/ui/LocationDistancePanel.java:
+	  New. A UIProvider that enables the user to enter locations or a
+	  distance.
+
+	* src/main/java/de/intevation/flys/client/client/ui/UIProviderFactory.java:
+	  States with a uiprovider attribute set to 'location_distance_panel' use
+	  the LocationDistancePanel for user input.
+
 2011-03-15  Ingo Weinzierl <ingo@intevation.de>
 
 	* src/main/java/de/intevation/flys/client/client/ui/ParameterList.java:
--- a/flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages.java	Tue Mar 15 14:55:47 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages.java	Wed Mar 16 09:57:41 2011 +0000
@@ -70,5 +70,29 @@
 
     @DefaultMessage("Next")
     String next();
+
+    @DefaultMessage("Choose calculation location/distance")
+    String location_distance_state();
+
+    @DefaultMessage("Location")
+    String location();
+
+    @DefaultMessage("Distance")
+    String distance();
+
+    @DefaultMessage("km")
+    String unitFrom();
+
+    @DefaultMessage("km a")
+    String unitTo();
+
+    @DefaultMessage("m")
+    String unitWidth();
+
+    @DefaultMessage("km")
+    String unitLocation();
+
+    @DefaultMessage("Wrong format")
+    String wrongFormat();
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages_de.properties	Tue Mar 15 14:55:47 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages_de.properties	Wed Mar 16 09:57:41 2011 +0000
@@ -19,3 +19,11 @@
 map = Karte
 fix = Fixierungsanalyse
 next = Weiter
+location_distance_state = Berechnungsort/strecke wählen
+location = Ort
+distance = Strecke
+unitFrom = km
+unitTo = km a
+unitWidth = m
+unitLocation = km
+wrongFormat = Falsches Format
--- a/flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages_en.properties	Tue Mar 15 14:55:47 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages_en.properties	Wed Mar 16 09:57:41 2011 +0000
@@ -19,3 +19,11 @@
 map = Map
 fix = TODO FIX ANALYSE TODO
 next = Next
+location_distance_state = Choose calculation location/distance
+location = Location
+distance = Distance
+unitFrom = km
+unitTo = km a
+unitWidth = m
+unitLocation = km
+wrongFormat = Wrong format
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/AbstractUIProvider.java	Wed Mar 16 09:57:41 2011 +0000
@@ -0,0 +1,96 @@
+package de.intevation.flys.client.client.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gwt.core.client.GWT;
+
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+
+import de.intevation.flys.client.client.event.HasStepForwardHandlers;
+import de.intevation.flys.client.client.event.StepForwardEvent;
+import de.intevation.flys.client.client.event.StepForwardHandler;
+import de.intevation.flys.client.shared.model.Data;
+
+
+/**
+ * An abstract UIProvider that provides some basic methods.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public abstract class AbstractUIProvider
+implements   UIProvider, HasStepForwardHandlers, ClickHandler
+{
+    /** The StepForwardHandlers.*/
+    protected List<StepForwardHandler> forwardHandlers;
+
+
+    /**
+     * Creates a new UIProvider instance of this class.
+     */
+    public AbstractUIProvider() {
+        forwardHandlers = new ArrayList<StepForwardHandler>();
+    }
+
+
+    /**
+     * Appends a StepForwardHandler that wants to listen to StepForwardEvents.
+     *
+     * @param handler A new StepForwardHandler.
+     */
+    public void addStepForwardHandler(StepForwardHandler handler) {
+        if (handler != null) {
+            forwardHandlers.add(handler);
+        }
+    }
+
+
+    /**
+     * This method is called after the user has clicked on the 'next' button to
+     * step to the next state.
+     *
+     * @param e The StepForwardEvent.
+     */
+    protected void fireStepForwardEvent(StepForwardEvent e) {
+        GWT.log("AbstractUIProvider - fireStepForwardEvent() handlers: " + forwardHandlers.size());
+        for (StepForwardHandler handler: forwardHandlers) {
+            handler.onStepForward(e);
+        }
+    }
+
+
+    /**
+     * This method is used to listen to click events on the 'next' button. The
+     * fireStepForwardEvent() method is called here.
+     *
+     * @param e The click event.
+     */
+    public void onClick(ClickEvent e) {
+        Data[] data = getData();
+
+        fireStepForwardEvent(new StepForwardEvent(data));
+    }
+
+
+    /**
+     * This method needs to be implemented by concrete subclasses. It should
+     * create a new Canvas object with a representation of <i>data</i>.
+     *
+     * @param data The data that should be displayed.
+     *
+     * @return a Canvas object that displays <i>data</i>.
+     */
+    public abstract Canvas create(Data data);
+
+
+    /**
+     * This method needs to be implemented by concrete subclasses. It should
+     * return the selected data.
+     *
+     * @return the selected data.
+     */
+    protected abstract Data[] getData();
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/LocationDistancePanel.java	Wed Mar 16 09:57:41 2011 +0000
@@ -0,0 +1,341 @@
+package de.intevation.flys.client.client.ui;
+
+import java.util.Map;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.NumberFormat;
+
+import com.smartgwt.client.types.TitleOrientation;
+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.events.BlurHandler;
+import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
+import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
+import com.smartgwt.client.widgets.form.fields.FormItem;
+import com.smartgwt.client.widgets.form.fields.FloatItem;
+import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+
+import de.intevation.flys.client.shared.model.Data;
+import de.intevation.flys.client.client.FLYSMessages;
+
+
+/**
+ * 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
+{
+    /** The message class that provides i18n strings.*/
+    protected FLYSMessages MESSAGES = GWT.create(FLYSMessages.class);
+
+
+    /** The constant name of the input field to enter locations.*/
+    public static final String FIELD_LOCATION = "location";
+
+    /** 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 the step width of a
+     * distance.*/
+    public static final String FIELD_WIDTH = "width";
+
+
+    /** The radio group for input mode selection.*/
+    protected RadioGroupItem radio;
+
+    /** A container that will contain the location or the distance panel.*/
+    protected HLayout container;
+
+
+    /**
+     * Creates a new LocationDistancePanel instance.
+     */
+    public LocationDistancePanel() {
+    }
+
+
+    /**
+     * 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(Data data) {
+        VLayout layout = new VLayout();
+
+        Label label          = new Label(MESSAGES.location_distance_state());
+        container            = new HLayout();
+        Canvas checkboxPanel = createRadioButtonPanel();
+
+        label.setHeight(25);
+
+        layout.addMember(label);
+        layout.addMember(checkboxPanel);
+        layout.addMember(container);
+
+        // TODO Add a table on the right to select locations by mouse click
+
+        return layout;
+    }
+
+
+    /**
+     * This method returns the selected data.
+     *
+     * @return the selected/inserted data.
+     */
+    public Data[] getData() {
+        // TODO Implement me
+
+        return null;
+    }
+
+
+    /**
+     * This method switches the input mode between location and distance input.
+     *
+     * @param event The click event fired by a RadioButtonGroupItem.
+     */
+    public void onChange(ChangeEvent event) {
+        String value = (String) event.getValue();
+
+        if (value == null) {
+            return;
+        }
+
+        if (value.equals(MESSAGES.location())) {
+            // TODO Insert correct values
+            Canvas locationPanel = createLocationPanel(new double[] {1.7, 2.5});
+            container.removeMembers(container.getMembers());
+            container.addMember(locationPanel);
+        }
+        else if (value.equals(MESSAGES.distance())){
+            // TODO Insert correct values
+            Canvas distancePanel = createDistancePanel(1.0, 3.4, 100);
+            container.removeMembers(container.getMembers());
+            container.addMember(distancePanel);
+        }
+    }
+
+
+    /**
+     * 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.
+     */
+    public void onBlur(BlurEvent event) {
+        FormItem item = event.getItem();
+        String  field = item.getFieldName();
+
+        if (field == null) {
+            return;
+        }
+
+        if (field.equals(FIELD_LOCATION)) {
+            validateLocation(event.getForm(), item);
+        }
+        else if (field.equals(FIELD_FROM)) {
+            validateDistance(event.getForm(), item);
+        }
+        else if (field.equals(FIELD_TO)) {
+            validateDistance(event.getForm(), item);
+        }
+        else if (field.equals(FIELD_WIDTH)) {
+            validateDistance(event.getForm(), item);
+        }
+    }
+
+
+    /**
+     * This method validates the entered text in the location input field. If
+     * there are values that doesn't represent a valid location, an error is
+     * displayed.
+     *
+     * @param form The DynamicForm.
+     * @param item The FormItem.
+     */
+    protected void validateLocation(DynamicForm form, FormItem item) {
+        String   value = (String) item.getValue();
+        String[] parts = value.split(" ");
+
+        if (parts == null) {
+            return;
+        }
+
+        NumberFormat f = NumberFormat.getDecimalFormat();
+        Map errors     = form.getErrors();
+
+        try {
+            for (String part: parts) {
+                double location = f.parse(part);
+
+                // TODO save the location
+            }
+
+            errors.remove(item.getFieldName());
+        }
+        catch (NumberFormatException nfe) {
+            errors.put(item.getFieldName(), MESSAGES.wrongFormat());
+        }
+
+        form.setErrors(errors, true);
+    }
+
+
+    /**
+     * This method validates the entered text in the distance input fields. If
+     * there are values that doesn't represent a valid float, an error is
+     * displayed.
+     *
+     * @param form The DynamicForm.
+     * @param item The FormItem.
+     */
+    protected void validateDistance(DynamicForm form, FormItem item) {
+        String v = (String) item.getValue();
+
+        NumberFormat f = NumberFormat.getDecimalFormat();
+        Map errors     = form.getErrors();
+
+        try {
+            double value = f.parse(v);
+
+            // TODO SAVE THE VALUE
+
+            errors.remove(item.getFieldName());
+        }
+        catch (NumberFormatException nfe) {
+            errors.put(item.getFieldName(), MESSAGES.wrongFormat());
+
+            item.focusInItem();
+        }
+
+        form.setErrors(errors, true);
+    }
+
+
+    /**
+     * 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() {
+        DynamicForm form = new DynamicForm();
+
+        radio = new RadioGroupItem("mode");
+        radio.setShowTitle(false);
+        radio.setVertical(false);
+        radio.setValueMap(MESSAGES.location(), MESSAGES.distance());
+
+        radio.addChangeHandler(this);
+
+        form.setFields(radio);
+
+        return form;
+    }
+
+
+    /**
+     * This method creates the location panel. It contains just a single input
+     * field.
+     *
+     * @param locations For each location a double value
+     *
+     * @return a panel with an input field.
+     */
+    protected Canvas createLocationPanel(double[] locations) {
+        TextItem ti = new TextItem(FIELD_LOCATION);
+
+        ti.setTitle(MESSAGES.unitLocation());
+        ti.addBlurHandler(this);
+
+        NumberFormat f = NumberFormat.getDecimalFormat();
+
+        StringBuilder text = new StringBuilder();
+        boolean firstItem  = true;
+
+        for (double loc: locations) {
+            if (!firstItem) {
+                text.append(" ");
+            }
+
+            text.append(f.format(loc));
+
+            firstItem = false;
+        }
+
+        ti.setValue(text.toString());
+
+        // TODO There is still a colon between the input field and the text -
+        // remove this colon!
+
+        DynamicForm form = new DynamicForm();
+        form.setFields(ti);
+        form.setTitleOrientation(TitleOrientation.RIGHT);
+        form.setNumCols(2);
+
+        return form;
+    }
+
+
+    /**
+     * This method creates the distance panel. It contains three input fields:
+     * one for a start, one for the end and one for a step width.
+     *
+     * @param start The start point.
+     * @param end   The end point.
+     * @param sw    The step width.
+     *
+     * @return a panel with three input fields.
+     */
+    protected Canvas createDistancePanel(double start,double end,double sw) {
+        FloatItem from  = new FloatItem(FIELD_FROM);
+        FloatItem to    = new FloatItem(FIELD_TO);
+        FloatItem width = new FloatItem(FIELD_WIDTH);
+
+        from.addBlurHandler(this);
+        to.addBlurHandler(this);
+        width.addBlurHandler(this);
+
+        // TODO There is still a colon between the input field and the text -
+        // remove this colon!
+
+        NumberFormat f = NumberFormat.getDecimalFormat();
+
+        from.setValue(f.format(start));
+        to.setValue(f.format(end));
+        width.setValue(f.format(sw));
+
+        from.setWidth(50);
+        to.setWidth(50);
+        width.setWidth(50);
+
+        from.setTitle(MESSAGES.unitFrom());
+        to.setTitle(MESSAGES.unitTo());
+        width.setTitle(MESSAGES.unitWidth());
+
+        DynamicForm form = new DynamicForm();
+        form.setFields(from, to, width);
+        form.setTitleOrientation(TitleOrientation.RIGHT);
+        form.setNumCols(6);
+        form.setFixedColWidths(false);
+
+        return form;
+    }
+}
+// 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	Tue Mar 15 14:55:47 2011 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/UIProviderFactory.java	Wed Mar 16 09:57:41 2011 +0000
@@ -12,6 +12,9 @@
         else if (uiProvider.equals("select_with_map")) {
             return new MapSelection();
         }
+        else if (uiProvider.equals("location_distance_panel")) {
+            return new LocationDistancePanel();
+        }
         else {
             return new SelectProvider();
         }

http://dive4elements.wald.intevation.org