view gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartPropertiesEditor.java @ 7597:fca46ce8e4f5

(issue1225) Implement Magic labels. There is now a new value in the chartsettings "Suggested Label" which is hidden in the property editor. A suggested label is the label that combines the label's of all processors that wrote data to an axis. This suggested label is set as the label when the user has not overwritten the label.
author Andre Heinecke <aheinecke@intevation.de>
date Mon, 25 Nov 2013 14:58:14 +0100
parents 480fb71ab73f
children 8580f222dfb2
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */

package org.dive4elements.river.client.client.ui.chart;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.CheckboxItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
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.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
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 org.dive4elements.river.client.client.Config;
import org.dive4elements.river.client.client.FLYSConstants;
import org.dive4elements.river.client.client.services.CollectionAttributeService;
import org.dive4elements.river.client.client.services.CollectionAttributeServiceAsync;
import org.dive4elements.river.client.client.utils.DoubleValidator;
import org.dive4elements.river.client.client.utils.IntegerValidator;
import org.dive4elements.river.client.shared.model.BooleanProperty;
import org.dive4elements.river.client.shared.model.Collection;
import org.dive4elements.river.client.shared.model.DoubleProperty;
import org.dive4elements.river.client.shared.model.IntegerProperty;
import org.dive4elements.river.client.shared.model.OutputSettings;
import org.dive4elements.river.client.shared.model.Property;
import org.dive4elements.river.client.shared.model.PropertyGroup;
import org.dive4elements.river.client.shared.model.PropertySetting;
import org.dive4elements.river.client.shared.model.Settings;
import org.dive4elements.river.client.shared.model.StringProperty;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Dialog for the Chart-Properties, constructed from respective xml document.
 *
 * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
 */
public class ChartPropertiesEditor
extends      Window
implements   ClickHandler
{
    /** The interface that provides i18n messages. */
    protected FLYSConstants MSG = GWT.create(FLYSConstants.class);

    /** CollectionAttribute Update Service. */
    protected CollectionAttributeServiceAsync updater =
        GWT.create(CollectionAttributeService.class);

    /** The tab called the editor window. */
    protected ChartOutputTab tab;

    /** The tabset for chart properties. */
    protected TabSet tabs;

    /** The collection. */
    protected Collection collection;

    /** The cloned output settings. */
    protected OutputSettings settings;

    /** The original output settings. */
    protected OutputSettings origSettings;



    /**
     * Setup editor dialog.
     * @param callerTab The tab called the editor window.
     */
    public ChartPropertiesEditor(ChartOutputTab callerTab) {
        this.tab = callerTab;
        this.tabs = new TabSet();

        init();
    }


    /**
     * Initialize the editor window and its components.
     */
    protected void init() {
        setTitle(MSG.properties());
        setCanDragReposition(true);
        setCanDragResize(true);

        collection = tab.getCollectionView().getCollection();
        String outputName = tab.getOutputName();
        origSettings = (OutputSettings)collection.getSettings(outputName);

        settings = (OutputSettings)origSettings.clone();
        if (settings == null) {
            return;
        }
        List<String> list = settings.getCategories();

        for (int i = 0; i < list.size(); i++) {
            Tab t = new Tab(MSG.getString(list.get(i)));
            List<Property> props = settings.getSettings(list.get(i));
            List<Property> origProps = origSettings.getSettings(list.get(i));
            VLayout layout = new VLayout();
            for (int j = 0; j < props.size(); j++) {
                if (props.get(j) instanceof PropertyGroup) {
                    layout.addMember(generatePropertyGroup(props.get(j),
                                                           origProps.get(j)));
                }
                else if (props.get(j) instanceof PropertySetting) {
                    PropertySetting p = (PropertySetting)props.get(j);
                    if (p.getAttribute("display").equals("false")) {
                        continue;
                    }
                    layout.addMember(generatePropertySetting(props.get(j),
                                                             origProps.get(j)));
                }
            }
            t.setPane(layout);
            tabs.addTab(t);
        }

        Button accept = new Button(MSG.label_ok());
        Button cancel = new Button(MSG.label_cancel());
        cancel.addClickHandler(this);
        accept.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent e) {
                if(isDialogValid()) {
                    updateCollection();
                }
                else {
                    GWT.log("Dialog not valid");
                    SC.warn(MSG.error_dialog_not_valid());
                }
            }
        });

        HLayout buttons = new HLayout();
        buttons.addMember(accept);
        buttons.addMember(cancel);
        buttons.setAlign(Alignment.CENTER);
        buttons.setHeight(30);

        addItem(tabs);
        addItem(buttons);
        setWidth(380);
        setHeight(470);
        centerInPage();
    }


    /**
     * This method is called when the user aborts theming.
     * @param event The event.
     */
    @Override
    public void onClick(ClickEvent event) {
        this.destroy();
    }


    /**
     * Create a section from group (usually axis properties).
     */
    protected Canvas generatePropertyGroup(Property group, Property orig) {
        PropertyGroup pg = (PropertyGroup)group;
        PropertyGroup origPg = (PropertyGroup)orig;

        if (pg.getName().equals("axis")) {
            for (Property prop: origPg.getProperties()) {
                GWT.log("Found: " + prop.getName());
            }
            for (Property prop: pg.getProperties()) {
                GWT.log("Found new: " + prop.getName());
            }
            // Certain axis shall be skipped (W/Q-Diagrams cm-axis especially).
            String outputName = tab.getOutputName();
            if (outputName.equals("fix_wq_curve") || outputName.equals("computed_discharge_curve")
                || outputName.equals("extreme_wq_curve")) {
                String labelString = ((StringProperty)origPg.getPropertyByName("label")).getValue();
                if(labelString.equals("W [cm]")) {
                    VLayout layout = new VLayout();
                    layout.setHeight(0);
                    return layout;
                }
            }
            Label scale = new Label(MSG.scale() + " :");
            scale.setHeight(25);
            scale.setMargin(2);

            DynamicForm form1 = new DynamicForm();
            DynamicForm form2 = new DynamicForm();
            form2.setNumCols(6);

            StringProperty label =
                (StringProperty)pg.getPropertyByName("label");
            FormItem title = createStringProperty(label);
            title.setValue(
                ((StringProperty)origPg.getPropertyByName("label")).getValue());

            StringProperty suggestedLabel =
                (StringProperty)pg.getPropertyByName("suggested-label");
            FormItem sugLabel = null;

            if (suggestedLabel != null) {
                // X Axis does not have a suggested label
                // otherwise add an hidden property for suggestedLabel
                sugLabel = createStringProperty(suggestedLabel);
                sugLabel.setValue(
                    ((StringProperty)origPg.getPropertyByName("suggested-label")).getValue());
            }

            IntegerProperty fontsize =
                (IntegerProperty)pg.getPropertyByName("font-size");
            FormItem fs = createIntegerProperty(fontsize);
            fs.setValue(
                ((IntegerProperty)
                    origPg.getPropertyByName("font-size")).getValue());

            DoubleProperty upper =
                (DoubleProperty)pg.getPropertyByName("upper");
            final FormItem range1 = createDoubleProperty(upper);
            range1.setName("rangeupper");
            range1.setWidth(70);
            range1.setValue(
                ((DoubleProperty)
                    origPg.getPropertyByName("upper")).toUIString());

            DoubleProperty lower =
                (DoubleProperty)pg.getPropertyByName("lower");
            final FormItem range2 = createDoubleProperty(lower);
            range2.setName("rangelower");
            range2.setWidth(70);
            range2.setValue(
                ((DoubleProperty)
                    origPg.getPropertyByName("lower")).toUIString());

            BooleanProperty fixation =
                (BooleanProperty)pg.getPropertyByName("fixation");
            FormItem fix = createBooleanProperty(fixation);
            fix.setValue(((BooleanProperty)
                origPg.getPropertyByName("fixation")).getValue().booleanValue());

            fix.addChangedHandler(new ChangedHandler() {
                @Override
                public void onChanged(ChangedEvent e) {
                    if ((Boolean)e.getValue()) {
                        range1.enable();
                        range2.enable();
                    }
                    else {
                        range1.disable();
                        range2.disable();
                    }
                }
            });
            if (fix.getValue().toString().equals("true")) {
                range1.enable();
                range2.enable();
            }
            else {
                range1.disable();
                range2.disable();
            }

            form1.setFields(title, fs);
            form2.setFields(fix, range2, range1);

            HLayout scaleLayout = new HLayout();
            scaleLayout.setHeight(30);
            scaleLayout.addMember(scale);
            scaleLayout.addMember(form2);
            scaleLayout.setStyleName("property-dialog-axis");

            VLayout root = new VLayout();
            root.addMember(form1);
            root.addMember(scaleLayout);
            root.setHeight(90);

            return root;
        }
        return null;
    }


    /**
     * Generate a form with items for the properties/settings, preset with
     * values.
     */
    protected DynamicForm generatePropertySetting(
        Property setting,
        Property orig)
    {
        DynamicForm form = new DynamicForm();
        FormItem item = new FormItem();
        if (setting instanceof BooleanProperty) {
            item = createBooleanProperty((BooleanProperty)setting);
            item.setValue(((BooleanProperty)orig).getValue().booleanValue());
        }
        else if (setting instanceof DoubleProperty) {
            item = createDoubleProperty((DoubleProperty)setting);
            item.setValue(((DoubleProperty)orig).toUIString());
        }
        else if (setting instanceof IntegerProperty) {
            item = createIntegerProperty((IntegerProperty)setting);
            item.setValue(((IntegerProperty)orig).getValue());
        }
        else if (setting instanceof StringProperty) {
            StringProperty property = (StringProperty) setting;
            item = createStringProperty(property);
            item.setValue(((StringProperty)orig).getValue());
        }
        else {
            GWT.log("generatePropertySetting: unknown setting type.");
        }
        form.setFields(item);
        return form;
    }


    protected FormItem createStringProperty(final StringProperty sp) {
        String name = sp.getName();
        if (name.contains("-")) {
            name = name.replace("-", "_");
        }

        String choiceAttribute = sp.getAttribute("choice");

        if (choiceAttribute != null && choiceAttribute.equals("logo")) {
            SelectItem logoChooser = new SelectItem();
            logoChooser.setImageURLPrefix(GWT.getHostPageBaseURL() + "images/logo-");
            logoChooser.setValueIconHeight(50);
            logoChooser.setValueIconWidth(100);

            LinkedHashMap valueMap = new LinkedHashMap<String, String>();
            LinkedHashMap<String, String> valueIcons = new LinkedHashMap<String, String>();
            valueMap.put("none", MSG.getString("none"));
            /*
             If you want to add images, remember to change code in these places:
             flys-artifacts:
             XYChartGenerator.java
             Timeseries*Generator.java and
             in the flys-client projects Chart*Propert*Editor.java.
             Also, these images have to be put in
             flys-artifacts/src/main/resources/images/
             flys-client/src/main/webapp/images/
             */
            valueMap.put("BfG", "");
            valueMap.put("Intevation", "");
            valueIcons.put("BfG", "bfg.gif");
            valueIcons.put("Intevation", "intevation.png");
            logoChooser.setValueIcons(valueIcons);
            logoChooser.setValueMap(valueMap);
            logoChooser.setTitleStyle("color:#000;");
            logoChooser.setTitleAlign(Alignment.LEFT);
            logoChooser.setTitle(MSG.getString(name));
            logoChooser.setTitleAlign(Alignment.LEFT);
            logoChooser.addBlurHandler(new BlurHandler() {
                @Override
                public void onBlur(BlurEvent e) {
                    String val;
                    if (e.getItem().getValue() == null) {
                        val = "";
                    }
                    else {
                        val = e.getItem().getValue().toString();
                    }
                    sp.setValue(val);
                }
            });
            return logoChooser;
        }
        else if (choiceAttribute != null && choiceAttribute.equals("placeh")) {
            SelectItem placeChooser = new SelectItem();
            LinkedHashMap valueMap = new LinkedHashMap<String, String>();
            valueMap.put("right", MSG.getString("right"));
            valueMap.put("left", MSG.getString("left"));
            valueMap.put("center", MSG.getString("center"));
            placeChooser.setValueMap(valueMap);
            placeChooser.setTitleStyle("color:#000;");
            placeChooser.setTitleAlign(Alignment.LEFT);
            placeChooser.setTitle(MSG.getString(name));
            placeChooser.setTitleAlign(Alignment.LEFT);
            placeChooser.addBlurHandler(new BlurHandler() {
                @Override
                public void onBlur(BlurEvent e) {
                    String val;
                    if (e.getItem().getValue() == null) {
                        val = "";
                    }
                    else {
                        val = e.getItem().getValue().toString();
                    }
                    sp.setValue(val);
                }
            });
            return placeChooser;
        }
        else if (choiceAttribute != null && choiceAttribute.equals("placev")) {
            SelectItem placeChooser = new SelectItem();
            LinkedHashMap valueMap = new LinkedHashMap<String, String>();
            valueMap.put("top", MSG.getString("top"));
            valueMap.put("bottom", MSG.getString("bottom"));
            valueMap.put("center", MSG.getString("center"));
            placeChooser.setValueMap(valueMap);
            placeChooser.setTitleStyle("color:#000;");
            placeChooser.setTitleAlign(Alignment.LEFT);
            placeChooser.setTitle(MSG.getString(name));
            placeChooser.setTitleAlign(Alignment.LEFT);
            placeChooser.addBlurHandler(new BlurHandler() {
                @Override
                public void onBlur(BlurEvent e) {
                    String val;
                    if (e.getItem().getValue() == null) {
                        val = "";
                    }
                    else {
                        val = e.getItem().getValue().toString();
                    }
                    sp.setValue(val);
                }
            });
            return placeChooser;
        }

        TextItem item = new TextItem();
        item.setTitle(MSG.getString(name));
        item.setTitleAlign(Alignment.LEFT);
        item.addBlurHandler(new BlurHandler() {
            @Override
            public void onBlur(BlurEvent e) {
                String val;
                if (e.getItem().getValue() == null) {
                    val = "";
                }
                else {
                    val = e.getItem().getValue().toString();
                }
                sp.setValue(val);
            }
        });
        return item;
    }


    /**
     *
     */
    protected FormItem createBooleanProperty(final BooleanProperty bp) {
        String name = bp.getName();
        if (name.contains("-")) {
            name = name.replace("-", "_");
        }

        CheckboxItem item = new CheckboxItem("item", MSG.getString(name));
        item.setLabelAsTitle(true);
        item.setTitleStyle("color:#000;");
        item.setTitleAlign(Alignment.LEFT);
        item.addBlurHandler(new BlurHandler() {
            @Override
            public void onBlur(BlurEvent e) {
                String val;
                if (e.getItem().getValue() == null) {
                    val = "";
                }
                else {
                    val = e.getItem().getValue().toString();
                }
                bp.setValue(val);
            }
        });
        return item;
    }


    /**
     *
     */
    protected FormItem createDoubleProperty(final DoubleProperty dp) {
        String name = dp.getName();
        if (name.contains("-")) {
            name = name.replace("-", "_");
        }

        TextItem item = new TextItem();
        item.setTitle(MSG.getString(name));
        item.setTitleAlign(Alignment.LEFT);
        item.addBlurHandler(new BlurHandler() {
            @Override
            public void onBlur(BlurEvent e) {
                 DoubleValidator validator = new DoubleValidator();
                 Map errors = e.getForm().getErrors();
                 if(validator.validate(e.getItem(), errors)) {
                     dp.setValueFromUI(e.getItem().getValue().toString());
                 }
                 e.getForm().setErrors(errors, true);
            }
        });
        return item;
    }


    /**
     *
     */
    protected FormItem createIntegerProperty(final IntegerProperty ip) {
        String name = ip.getName();
        if (name.contains("-")) {
            name = name.replace("-", "_");
        }

        TextItem item = new TextItem();
        item.setTitle(MSG.getString(name));
        item.setTitleAlign(Alignment.LEFT);
        item.addBlurHandler(new BlurHandler() {
            @Override
            public void onBlur(BlurEvent e) {
                IntegerValidator validator = new IntegerValidator();
                Map errors = e.getForm().getErrors();
                if(validator.validate(e.getItem(), errors)) {
                    ip.setValue(e.getItem().getValue().toString());
                }
                e.getForm().setErrors(errors, true);
            }
        });
        return item;
    }


    protected void updateCollection() {
        final Config config = Config.getInstance();
        final String loc    = config.getLocale();

        GWT.log("PropertiesEditor.updateCollection via RPC now");

        Settings s = settings;
        collection.addSettings(this.tab.getOutputName(), s);
        updater.update(collection, loc, new AsyncCallback<Collection>() {
            @Override
            public void onFailure(Throwable caught) {
                GWT.log("Could not update collection attributes.");
                SC.warn(MSG.getString(caught.getMessage()));
            }
            @Override
            public void onSuccess(Collection collection) {
                updateChartTab();
            }
        });
    }

    protected void updateChartTab() {
        this.tab.updateChartInfo();
        this.tab.updateChartPanel();
        this.destroy();
    }


    protected boolean isDialogValid() {
        boolean valid = true;
        for (int i = 0; i < tabs.getNumTabs(); i++) {
            Tab t = tabs.getTab(i);
            Canvas container = t.getPane();
            Canvas[] children = container.getChildren();
            for (Canvas c: children) {
                valid = validateCanvas(c);
                if(!valid) {
                    return valid;
                }
            }
        }
        return valid;
    }


    protected boolean validateCanvas(Canvas c) {
        boolean valid = true;
        if(c instanceof DynamicForm) {
            DynamicForm f = (DynamicForm) c;
            FormItem up = f.getItem("rangeupper");
            FormItem lo = f.getItem("rangelower");

            if(up != null && lo != null &&
               !up.isDisabled() && !lo.isDisabled())
            {
                validateRange(f);
            }
            return !f.hasErrors();
        }
        else if(c.getChildren().length > 0) {
            for (Canvas child: c.getChildren()) {
                valid = validateCanvas(child);
                if(!valid) {
                    return valid;
                }
            }
        }
        return valid;
    }

    protected boolean validateRange(DynamicForm form) {
        Map errors = form.getErrors();
        FormItem up = form.getItem("rangeupper");
        FormItem lo = form.getItem("rangelower");

        String v1 = up.getValue().toString();
        String v2 = lo.getValue().toString();

        if(v1.equals(v2)) {
            errors.put(up.getFieldName(), MSG.wrongFormat());
            errors.put(lo.getFieldName(), MSG.wrongFormat());
            form.setErrors(errors, true);
            return false;
        }
        return true;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org