# HG changeset patch # User Ingo Weinzierl # Date 1300269461 0 # Node ID 87a44f8e25cc1e4acd1b6f55b1ea2f2b14a1ea59 # Parent 1458bc0a20e26045bbda8115d8caf945011af6bb 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 diff -r 1458bc0a20e2 -r 87a44f8e25cc flys-client/ChangeLog --- 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 + + * 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 * src/main/java/de/intevation/flys/client/client/ui/ParameterList.java: diff -r 1458bc0a20e2 -r 87a44f8e25cc flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages.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 : diff -r 1458bc0a20e2 -r 87a44f8e25cc flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages_de.properties --- 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 diff -r 1458bc0a20e2 -r 87a44f8e25cc flys-client/src/main/java/de/intevation/flys/client/client/FLYSMessages_en.properties --- 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 diff -r 1458bc0a20e2 -r 87a44f8e25cc flys-client/src/main/java/de/intevation/flys/client/client/ui/AbstractUIProvider.java --- /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 Ingo Weinzierl + */ +public abstract class AbstractUIProvider +implements UIProvider, HasStepForwardHandlers, ClickHandler +{ + /** The StepForwardHandlers.*/ + protected List forwardHandlers; + + + /** + * Creates a new UIProvider instance of this class. + */ + public AbstractUIProvider() { + forwardHandlers = new ArrayList(); + } + + + /** + * 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 data. + * + * @param data The data that should be displayed. + * + * @return a Canvas object that displays data. + */ + 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 : diff -r 1458bc0a20e2 -r 87a44f8e25cc flys-client/src/main/java/de/intevation/flys/client/client/ui/LocationDistancePanel.java --- /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 Ingo Weinzierl + */ +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 : diff -r 1458bc0a20e2 -r 87a44f8e25cc flys-client/src/main/java/de/intevation/flys/client/client/ui/UIProviderFactory.java --- 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(); }