view gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NaviChartOutputTab.java @ 9416:05405292a7ca

Navigationtheme panel now shows themes of dWt and WQ charts grayed out, if the current station is outside the valid range of the theme.
author gernotbelger
date Thu, 16 Aug 2018 16:28:03 +0200
parents abf14917be32
children
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 java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.dive4elements.river.client.client.Config;
import org.dive4elements.river.client.client.ui.CollectionView;
import org.dive4elements.river.client.shared.model.AbstractFixBunduArtifact;
import org.dive4elements.river.client.shared.model.Artifact;
import org.dive4elements.river.client.shared.model.Collection;
import org.dive4elements.river.client.shared.model.CollectionItem;
import org.dive4elements.river.client.shared.model.FixFilter;
import org.dive4elements.river.client.shared.model.OutputMode;
import org.dive4elements.river.client.shared.model.SINFOArtifact;

import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.NumberFormat;
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.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.KeyPressEvent;
import com.smartgwt.client.widgets.form.fields.events.KeyPressHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.tab.events.TabSelectedEvent;
import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;

/**
 * Tab representing and showing one Chart-output with a "navi" thing.
 *
 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
 */
public class NaviChartOutputTab extends ChartOutputTab implements TabSelectedHandler {
    private TextItem currentkm;

    private final NumberFormat kmFormat = NumberFormat.getDecimalFormat();

    private INaviChartStepper stepper;

    public NaviChartOutputTab(final String title, final Collection collection, final OutputMode mode, final CollectionView collectionView) {
        super(title, collection, mode, collectionView, new NaviChartRecordHandler(collectionView));

        this.stepper = new NilNaviChartStepper();

        this.right.removeChild(this.chart);
        this.right.addChild(createNaviChart());
        collectionView.registerTabHandler(this);
    }

    protected Canvas createNaviChart() {
        final Artifact art = this.collectionView.getArtifact();
        final VLayout root = new VLayout();
        root.setWidth100();
        root.setHeight100();

        final HLayout layout = new HLayout();
        layout.setAlign(Alignment.CENTER);

        final DynamicForm form = new DynamicForm();
        final Button lower = new Button("<<");
        lower.setWidth(30);
        final Button upper = new Button(">>");
        upper.setWidth(30);
        this.currentkm = new TextItem();
        this.currentkm.setWidth(60);
        this.currentkm.setShowTitle(false);

        form.setFields(this.currentkm);
        form.setWidth(60);

        this.stepper = createStepper(art);

        // Always jump to the from km when initialized.
        final double currentKm = this.stepper.getCurrentKm();
        this.collectionView.setCurrentKm(currentKm);
        this.currentkm.setValue(this.kmFormat.format(currentKm));

        lower.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(final ClickEvent ce) {
                updateChartDown();
            }
        });

        upper.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(final ClickEvent ce) {
                updateChartUp();
            }
        });

        this.currentkm.addKeyPressHandler(new KeyPressHandler() {
            @Override
            public void onKeyPress(final KeyPressEvent kpe) {

                if (!kpe.getKeyName().equals("Enter"))
                    return;

                if (kpe.getItem().getValue() != null) {
                    final String kmText = kpe.getItem().getValue().toString();
                    updateChartKm(kmText);
                }
            }
        });
        layout.addMember(lower);
        layout.addMember(form);
        layout.addMember(upper);

        root.addMember(this.chart);
        root.addMember(layout);
        return root;
    }

    private INaviChartStepper createStepper(final Artifact art) {

        if (art instanceof AbstractFixBunduArtifact) {
            final AbstractFixBunduArtifact fix = (AbstractFixBunduArtifact) art;
            final FixFilter fixFilter = fix.getFilter();

            final double fromKm = fixFilter.getLowerKm();
            final double toKm = fixFilter.getUpperKm();

            final String s = fix.getArtifactDescription().getDataValueAsString("ld_step");
            try {
                final double ds = Double.parseDouble(s);
                return new MinMaxStepNaviChartStepper(fromKm, toKm, ds);
            }
            catch (final NumberFormatException nfe) {
                return new MinMaxStepNaviChartStepper(fromKm, toKm, 100d);
            }
        } else if (art instanceof SINFOArtifact) {
            /* special case for SINFO-Flood-Duration */
            final SINFOArtifact sinfo = (SINFOArtifact) art;

            final CollectionItem item = this.collection.getItem(sinfo.getUuid());

            final Set<Double> validKms = sinfo.getValidDurationChartKms(item);
            return new DistinctValuesNaviChartStepper(validKms);
        } else {
            // Probably WINFOArtifact kind of artifact.

            double fromKm;
            double toKm;

            final double[] kmRange = art.getArtifactDescription().getKMRange();
            if (kmRange != null && kmRange.length == 2) {
                fromKm = kmRange[0];
                toKm = kmRange[1];
            } else {
                GWT.log("No KM range in description found.");
                return new NilNaviChartStepper();
            }

            final String ld_step = art.getArtifactDescription().getDataValueAsString("ld_step");
            try {
                final Double step = Double.valueOf(ld_step);
                return new MinMaxStepNaviChartStepper(fromKm, toKm, step);
            }
            catch (final Exception e) {
                GWT.log("No ld_steps data or not parsable.", e);
                return new MinMaxStepNaviChartStepper(fromKm, toKm, 100d);
            }
        }
    }

    protected void updateChartKm(final String kmText) {

        NaviChartOutputTab.this.tbarPanel.deselectControls();

        try {
            final double d = this.kmFormat.parse(kmText);

            final double validCurrentKm = this.stepper.setValidCurrentKm(d);
            updateCurrentKm(validCurrentKm);
        }
        catch (final NumberFormatException e) {
            SC.warn("Invalid value: " + kmText);
            // do nothing, but an error message would be nice
        }
    }

    /**
     * Callback when km-up-button is clicked.
     * Increases collectionViews KM and refreshes view.
     */
    protected void updateChartUp() {

        this.tbarPanel.deselectControls();

        final double nextKm = this.stepper.stepForward();
        updateCurrentKm(nextKm);
    }

    /**
     * Callback when km-down-button is clicked.
     * Decreases collectionViews KM and refreshes view.
     */
    protected void updateChartDown() {

        this.tbarPanel.deselectControls();

        final double prevKm = this.stepper.stepBackward();
        updateCurrentKm(prevKm);
    }

    private void updateCurrentKm(final double currentKm) {

        this.collectionView.setCurrentKm(currentKm);

        this.tbarPanel.updateLinks();

        updateChartPanel();
        updateChartInfo();

        this.currentkm.setValue(this.kmFormat.format(currentKm));
        this.tbarPanel.onZoom(null);

        updateThemePanel();
    }

    /**
     * Returns the existing chart panel.
     *
     * @return the existing chart panel.
     */
    @Override
    public Canvas getChartPanel() {
        return this.chart;
    }

    /**
     * Builds the URL that points to the chart image.
     *
     * @param width
     *            The width of the requested chart.
     * @param height
     *            The height of the requested chart.
     * @param xr
     *            Optional x range (used for zooming).
     * @param yr
     *            Optional y range (used for zooming).
     *
     * @return the URL to the chart image.
     */
    @Override
    protected String getImgUrl(final int width, final int height) {
        final Config config = Config.getInstance();

        String imgUrl = GWT.getModuleBaseURL();
        imgUrl += "chart";
        imgUrl += "?uuid=" + this.collection.identifier();
        imgUrl += "&type=" + this.mode.getName();
        imgUrl += "&locale=" + config.getLocale();
        imgUrl += "&timestamp=" + new Date().getTime();
        imgUrl += "&width=" + Integer.toString(width);
        imgUrl += "&height=" + Integer.toString(height - 40);

        final Number[] zoom = getZoomValues();

        if (zoom != null) {
            if (zoom[0].intValue() != 0 || zoom[1].intValue() != 1) {
                // a zoom range of 0-1 means displaying the whole range. In such
                // case we don't need to zoom.
                imgUrl += "&minx=" + zoom[0];
                imgUrl += "&maxx=" + zoom[1];
            }

            if (zoom[2].intValue() != 0 || zoom[3].intValue() != 1) {
                // a zoom range of 0-1 means displaying the whole range. In such
                // case we don't need to zoom.
                imgUrl += "&miny=" + zoom[2];
                imgUrl += "&maxy=" + zoom[3];
            }
        }

        if (this.collectionView.getCurrentKm() == -1) {
            // REMARK: this happens, because we get called from the constructor of our super class

            if (this.collectionView.getArtifact() instanceof AbstractFixBunduArtifact) {
                final AbstractFixBunduArtifact fix = (AbstractFixBunduArtifact) this.collectionView.getArtifact();
                this.collectionView.setCurrentKm(fix.getFilter().getLowerKm());
            }
            else
                this.collectionView.setCurrentKm(this.collectionView.getArtifact().getArtifactDescription().getKMRange()[0]);
        }

        if (this.collectionView.getCurrentKm() != -1) {
            imgUrl += "&currentKm=" + this.collectionView.getCurrentKm();
        }

        return imgUrl;
    }

    @Override
    public void onTabSelected(final TabSelectedEvent tse) {
        if (this.equals(tse.getTab())) {

            final double currentKm = this.collectionView.getCurrentKm();

            final double validCurrentKm = this.stepper.setValidCurrentKm(currentKm);
            updateCurrentKm(validCurrentKm);
        }
    }

    @Override
    public Map<String, String> getChartAttributes() {
        Map<String, String> attr = new HashMap<String, String>();

        attr = super.getChartAttributes();
        attr.put("km", String.valueOf(this.collectionView.getCurrentKm()));

        return attr;
    }

    /**
     * In contrast to supers implementation, include the currently selected
     * km in the url.
     */
    @Override
    public String getExportUrl(final int width, final int height, final String format) {
        String url = super.getExportUrl(width, height, format);
        if (this.collectionView.getCurrentKm() != -1) {
            url += "&currentKm=" + this.collectionView.getCurrentKm();
        }
        return url;
    }
}

http://dive4elements.wald.intevation.org