view gwt-client/src/main/java/org/dive4elements/river/client/client/ui/fixation/FixationPanel.java @ 9256:6c24c857ccf9

fixation refactoring and inputItem behaviour to interfaces
author gernotbelger
date Fri, 13 Jul 2018 12:04:21 +0200
parents 9be51f776798
children 1a7cfeb1ff89
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.fixation;

import java.util.Date;
import java.util.HashMap;

import org.dive4elements.river.client.client.Config;
import org.dive4elements.river.client.client.FLYSConstants;
import org.dive4elements.river.client.client.services.FixingsOverviewService;
import org.dive4elements.river.client.client.services.FixingsOverviewServiceAsync;
import org.dive4elements.river.client.client.ui.AbstractUIProvider;
import org.dive4elements.river.client.shared.model.AbstractFixBunduArtifact;
import org.dive4elements.river.client.shared.model.DataList;
import org.dive4elements.river.client.shared.model.FixFilter;
import org.dive4elements.river.client.shared.model.FixingsOverviewInfo;

import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.URL;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
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.HTMLPane;
import com.smartgwt.client.widgets.Img;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.ResizedEvent;
import com.smartgwt.client.widgets.events.ResizedHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.TextItem;
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;

/**
 * This UIProvider creates helper panel for fixation analysis without input
 * elements.
 *
 * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
 */
public abstract class FixationPanel extends AbstractUIProvider implements ResizedHandler {
    private static final long serialVersionUID = -3667553404493415619L;

    protected static HashMap<String, FixationPanel> instances = new HashMap<String, FixationPanel>();

    /** The message class that provides i18n strings. */
    private final FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);

    private final FixingsOverviewServiceAsync overviewService = GWT.create(FixingsOverviewService.class);

    private String htmlOverview;
    private FixingsOverviewInfo fixInfo;
    private TabSet tabs;
    private Tab events;
    private Tab chart;
    private VLayout chartContainer;
    private Img chartImg;
    private TextItem kmText;

    private static final DateTimeFormat DTF = DateTimeFormat.getFormat("dd.MM.yyyy");

    public FixationPanel() {
        this.chartImg = new Img();
        this.htmlOverview = "";
    }

    /** Get the (master) artifact UUID. */
    private String getArtifactUuid() {
        return this.artifact.getUuid();
    }

    @Override
    public final Canvas create(final DataList list) {
        final VLayout layout = new VLayout();

        final Canvas helper = createHelper();
        this.helperContainer.addMember(helper);

        final Canvas submit = getNextButton();
        final Canvas widget = createWidget(list);

        layout.addMember(widget);
        layout.addMember(submit);
        return layout;
    }

    private Canvas createHelper() {
        final Config config = Config.getInstance();
        final String locale = config.getLocale();

        this.tabs = new TabSet();
        this.events = new Tab(this.MESSAGES.events());
        this.chart = new Tab(this.MESSAGES.kmchart());

        this.chartContainer = new VLayout();
        final Canvas scroll = createChartHelper();

        final VLayout layout = new VLayout();
        layout.addResizedHandler(this);
        layout.addMember(this.chartContainer);
        layout.addMember(scroll);
        layout.setAlign(Alignment.CENTER);
        this.chart.setPane(layout);

        final HTMLPane eventPane = new HTMLPane();

        // final String river = this.artifact.getArtifactDescription().getRiver();
        createCallback();

        final String callBack = "fixationCallback(this.checked, this.name)";

        if (this.artifact instanceof AbstractFixBunduArtifact == false)
            return this.chartContainer;

        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;

        this.overviewService.generateOverview(locale, this.artifact.getUuid(), getOverviewFilter(art.getFilter()),
                renderCheckboxes(), callBack, new AsyncCallback<FixingsOverviewInfo>() {
                    @Override
                    public void onFailure(final Throwable caught) {
                        GWT.log("Could not receive overview.");
                        SC.warn(caught.getMessage());
                    }

                    @Override
                    public void onSuccess(final FixingsOverviewInfo info) {
                        GWT.log("Successfully loaded overview.");
                        FixationPanel.this.fixInfo = info;
                        FixationPanel.this.htmlOverview = info.getHTML();
                        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) FixationPanel.this.artifact;
                        final FixFilter filter = art.getFilter();
                        filter.setRiver(info.getRiver());
                        if (filter.getCurrentKm() == -Double.MAX_VALUE || filter.getCurrentKm() == -1d) {
                            filter.setCurrentKm(filter.getLowerKm());
                            filter.setToKm(filter.getUpperKm());
                        }
                        if (FixationPanel.this.kmText != null) {
                            final NumberFormat nf = NumberFormat.getDecimalFormat();
                            try {
                                final double d = Double.valueOf(filter.getCurrentKm());
                                FixationPanel.this.kmText.setValue(nf.format(d));
                            }
                            catch (final NumberFormatException e) {
                                FixationPanel.this.kmText.setValue(filter.getCurrentKm());
                            }
                        }
                        eventPane.setContents(FixationPanel.this.htmlOverview);
                        updateChartTab(FixationPanel.this.fixInfo.getLowerKm());
                        FixationPanel.this.events.setPane(eventPane);
                        success(FixationPanel.this.fixInfo);
                    }
                });

        this.tabs.addTab(this.events);
        this.tabs.addTab(this.chart);

        return this.tabs;
    }

    private Canvas createChartHelper() {
        final DynamicForm form = new DynamicForm();
        final Button lower = new Button("<<");
        lower.setWidth(30);
        final Button upper = new Button(">>");
        upper.setWidth(30);
        this.kmText = new TextItem();
        this.kmText.setWidth(60);
        this.kmText.setShowTitle(false);

        form.setFields(this.kmText);
        form.setWidth(60);
        lower.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(final ClickEvent ce) {
                final FixFilter filter = updateChartTabLow();
                final NumberFormat nf = NumberFormat.getDecimalFormat();
                try {
                    final double d = Double.valueOf(filter.getCurrentKm());
                    FixationPanel.this.kmText.setValue(nf.format(d));
                }
                catch (final NumberFormatException e) {
                    FixationPanel.this.kmText.setValue(filter.getCurrentKm());
                }
            }
        });

        upper.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(final ClickEvent ce) {
                final FixFilter filter = updateChartTabUp();
                final NumberFormat nf = NumberFormat.getDecimalFormat();
                try {
                    final double d = Double.valueOf(filter.getCurrentKm());
                    FixationPanel.this.kmText.setValue(nf.format(d));
                }
                catch (final NumberFormatException e) {
                    FixationPanel.this.kmText.setValue(filter.getCurrentKm());
                }
            }
        });

        this.kmText.addChangedHandler(new ChangedHandler() {
            @Override
            public void onChanged(final ChangedEvent ce) {
                // TODO: get current value.
                if (ce.getItem().getValue() != null) {
                    final NumberFormat nf = NumberFormat.getDecimalFormat();
                    try {
                        final double d = nf.parse(ce.getItem().getValue().toString());
                        updateChartTab(d);
                    }
                    catch (final NumberFormatException nfe) {
                        // Do nothing.
                    }
                }
            }
        });

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

        layout.addMember(lower);
        layout.addMember(form);
        layout.addMember(upper);
        return layout;
    }

    private void updateChartTab(double km) {
        final Config config = Config.getInstance();
        final String locale = config.getLocale();

        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;

        // was soll das all
        if (this.fixInfo != null) {
            if (km < this.fixInfo.getLowerKm())
                km = this.fixInfo.getLowerKm();
            // if (km > this.fixInfo.getTo())
            // km = this.fixInfo.getTo();
        }

        final FixFilter filter = art.getFilter();

        if (km < filter.getLowerKm())
            km = filter.getLowerKm();
        if (km > filter.getUpperKm())
            km = filter.getUpperKm();

        filter.setCurrentKm(km);

        int hWidth = this.helperContainer.getWidth() - 12;
        int hHeight = this.helperContainer.getHeight() - 62;

        if ((int) (hHeight * 4f / 3) < hWidth) {
            hWidth = (int) (hHeight * 4f / 3);
        } else {
            hHeight = (int) (hWidth * 3f / 4);
        }

        final String imgUrl = URL.encode(GWT.getModuleBaseURL()
                + "fixings-km-chart"
                + "?locale=" + locale
                + "&filter=" + getChartFilter(filter, hWidth, hHeight));

        if (this.chartContainer.hasMember(this.chartImg)) {
            this.chartImg.setWidth(hWidth);
            this.chartImg.setHeight(hHeight);
            this.chartImg.setSrc(imgUrl);
        } else {
            this.chartImg = new Img(imgUrl, hWidth, hHeight);
            this.chartContainer.addMember(this.chartImg);
        }
    }

    private FixFilter updateChartTabLow() {
        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;

        final FixFilter filter = art.getFilter();

        final double curr = filter.getCurrentKm();
        if (curr > filter.getLowerKm()) {
            final double newVal = (curr - 0.1) * 10;
            final long round = Math.round(newVal);
            updateChartTab(((double) round) / 10);
        }
        return filter;
    }

    private FixFilter updateChartTabUp() {
        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;

        final FixFilter filter = art.getFilter();

        final double curr = filter.getCurrentKm();
        if (curr < filter.getUpperKm()) {
            final double newVal = (curr + 0.1) * 10;
            final long round = Math.round(newVal);
            updateChartTab(((double) round) / 10);
        }
        return filter;
    }

    @Override
    public final void onResized(final ResizedEvent re) {
        final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;

        updateChartTab(art.getFilter().getCurrentKm());
    }

    private native void createCallback() /*-{
        $wnd.fixationCallback = @org.dive4elements.river.client.client.ui.fixation.FixationPanel::helperCallback(ZLjava/lang/String;);
    }-*/;

    private static void helperCallback(final boolean checked, final String name) {
        final String[] parts = name.split(":");
        final String uuid = parts[0];
        final String cid = parts[1];

        final FixationPanel p = FixationPanel.getInstance(uuid);
        if (p != null) {
            p.setValues(cid, checked);
        }
    }

    private static FixationPanel getInstance(final String uuid) {
        return instances.get(uuid);
    }

    protected abstract Canvas createWidget(DataList data);

    protected abstract void setValues(String cid, boolean checked);

    protected abstract boolean renderCheckboxes();

    protected abstract void success(FixingsOverviewInfo fixInfo);

    /** Creates JSON string from filter. */
    private static String getOverviewFilter(final FixFilter filter) {
        final String river = filter.getRiver();

        if (river != null && river.length() > 0) {
            final JSONObject jfix = new JSONObject();
            final JSONObject jfilter = new JSONObject();
            final JSONObject jrName = new JSONObject();
            final JSONString jrValue = new JSONString(river);
            jrName.put("name", jrValue);
            jfilter.put("river", jrName);
            jfix.put("fixings", createFilter(filter, jfilter));
            return jfix.toString();
        }
        return "";
    }

    private String getChartFilter(final FixFilter filter, final int width, final int height) {
        final String river = filter.getRiver();
        final double currentKm = filter.getCurrentKm();
        final double fromKm = filter.getLowerKm();
        final double toKm = filter.getUpperKm();

        if (river != null && river.length() > 0 && currentKm >= fromKm && currentKm <= toKm) {
            final JSONObject jfix = new JSONObject();
            final JSONObject jfilter = new JSONObject();
            final JSONObject jrName = new JSONObject();
            final JSONString jrValue = new JSONString(river);
            final JSONObject jkm = new JSONObject();
            final JSONNumber jkmValue = new JSONNumber(currentKm);
            final JSONObject jextent = new JSONObject();
            final JSONNumber jwidth = new JSONNumber(width);
            final JSONNumber jheight = new JSONNumber(height);

            jkm.put("value", jkmValue);
            jrName.put("name", jrValue);
            jfilter.put("river", jrName);
            jfilter.put("km", jkm);
            jextent.put("width", jwidth);
            jextent.put("height", jheight);
            jfilter.put("extent", jextent);
            jfix.put("fixings", createFilter(filter, jfilter));
            return jfix.toString();
        }
        return "";
    }

    private static JSONObject createFilter(final FixFilter filter, final JSONObject root) {
        final double fromKm = filter.getLowerKm();
        final double toKm = filter.getUpperKm();
        final boolean hasDate = filter.hasDate();

        if (fromKm >= 0 && toKm >= 0 && fromKm <= toKm) {
            final JSONObject range = new JSONObject();
            final JSONObject fromtokm = new JSONObject();
            final JSONNumber f = new JSONNumber(fromKm);
            final JSONNumber t = new JSONNumber(toKm);
            fromtokm.put("from", f);
            fromtokm.put("to", t);
            root.put("range", fromtokm);
        }

        final JSONObject and = new JSONObject();
        if (hasDate) {
            final long fromDate = filter.getFromDate();
            final long toDate = filter.getToDate();

            final Date df = new Date(fromDate);
            final Date dt = new Date(toDate);

            final JSONObject daterange = new JSONObject();
            final JSONString f = new JSONString(DTF.format(df));
            final JSONString t = new JSONString(DTF.format(dt));

            daterange.put("from", f);
            daterange.put("to", t);
            and.put("date-range", daterange);
        }

        final int fromClass = filter.getFromClass();
        final int toClass = filter.getToClass();

        if (fromClass >= 0 && toClass >= 0 && fromClass <= toClass) {
            final JSONObject classrange = new JSONObject();
            final JSONNumber f = new JSONNumber(fromClass);
            final JSONNumber t = new JSONNumber(toClass);

            classrange.put("from", f);
            classrange.put("to", t);
            and.put("sector-range", classrange);
        }

        final int[] events = filter.getEvents();

        if (events.length > 0) {
            final StringBuilder cids = new StringBuilder();

            for (int i = 0; i < events.length; i++) {
                if (i > 0)
                    cids.append(' ');
                cids.append(events[i]);
            }
            final JSONObject columns = new JSONObject();
            columns.put("cids", new JSONString(cids.toString()));
            and.put("columns", columns);
        }
        if (and.size() > 0) {
            final JSONObject jFilter = new JSONObject();
            jFilter.put("and", and);
            root.put("filter", jFilter);
        }
        return root;
    }
}

http://dive4elements.wald.intevation.org