view flys-client/src/main/java/de/intevation/flys/client/client/ui/LocationDistancePanel.java @ 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
children 6bcd8e3f21a7
line wrap: on
line source
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 :

http://dive4elements.wald.intevation.org