teichmann@5861: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
teichmann@5861: * Software engineering by Intevation GmbH
teichmann@5861: *
teichmann@5993: * This file is Free Software under the GNU AGPL (>=v3)
teichmann@5861: * and comes with ABSOLUTELY NO WARRANTY! Check out the
teichmann@5993: * documentation coming with Dive4Elements River for details.
teichmann@5861: */
teichmann@5861:
teichmann@5835: package org.dive4elements.river.client.client.ui.fixation;
raimund@2505:
gernotbelger@9072: import java.util.Date;
gernotbelger@9072: import java.util.HashMap;
gernotbelger@9072:
gernotbelger@9072: import org.dive4elements.river.client.client.Config;
gernotbelger@9072: import org.dive4elements.river.client.client.FLYSConstants;
gernotbelger@9072: import org.dive4elements.river.client.client.services.FixingsOverviewService;
gernotbelger@9072: import org.dive4elements.river.client.client.services.FixingsOverviewServiceAsync;
gernotbelger@9072: import org.dive4elements.river.client.client.ui.AbstractUIProvider;
gernotbelger@9072: import org.dive4elements.river.client.shared.model.AbstractFixBunduArtifact;
gernotbelger@9072: import org.dive4elements.river.client.shared.model.DataList;
gernotbelger@9072: import org.dive4elements.river.client.shared.model.FixFilter;
gernotbelger@9072: import org.dive4elements.river.client.shared.model.FixingsOverviewInfo;
gernotbelger@9072:
raimund@2505: import com.google.gwt.core.client.GWT;
tom@8864: import com.google.gwt.http.client.URL;
sascha@3366: import com.google.gwt.i18n.client.DateTimeFormat;
sascha@3366: import com.google.gwt.i18n.client.NumberFormat;
sascha@3366: import com.google.gwt.json.client.JSONNumber;
sascha@3366: import com.google.gwt.json.client.JSONObject;
sascha@3366: import com.google.gwt.json.client.JSONString;
raimund@2505: import com.google.gwt.user.client.rpc.AsyncCallback;
sascha@3366: import com.smartgwt.client.types.Alignment;
raimund@2505: import com.smartgwt.client.util.SC;
sascha@3366: import com.smartgwt.client.widgets.Button;
raimund@2505: import com.smartgwt.client.widgets.Canvas;
sascha@3366: import com.smartgwt.client.widgets.HTMLPane;
sascha@3366: import com.smartgwt.client.widgets.Img;
sascha@3366: import com.smartgwt.client.widgets.events.ClickEvent;
sascha@3366: import com.smartgwt.client.widgets.events.ClickHandler;
sascha@3366: import com.smartgwt.client.widgets.events.ResizedEvent;
sascha@3366: import com.smartgwt.client.widgets.events.ResizedHandler;
raimund@2505: import com.smartgwt.client.widgets.form.DynamicForm;
raimund@2517: import com.smartgwt.client.widgets.form.fields.TextItem;
raimund@2517: import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
sascha@3366: import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
sascha@3366: import com.smartgwt.client.widgets.layout.HLayout;
sascha@3366: import com.smartgwt.client.widgets.layout.VLayout;
raimund@2517: import com.smartgwt.client.widgets.tab.Tab;
raimund@2517: import com.smartgwt.client.widgets.tab.TabSet;
raimund@2505:
raimund@2505: /**
raimund@2505: * This UIProvider creates helper panel for fixation analysis without input
raimund@2505: * elements.
raimund@2505: *
raimund@2505: * @author Raimund Renkert
raimund@2505: */
gernotbelger@9072: public abstract class FixationPanel extends AbstractUIProvider implements ResizedHandler {
christian@4568: private static final long serialVersionUID = -3667553404493415619L;
christian@4568:
gernotbelger@9072: protected static HashMap instances = new HashMap();
raimund@2505:
raimund@2505: /** The message class that provides i18n strings. */
gernotbelger@9256: private final FLYSConstants MESSAGES = GWT.create(FLYSConstants.class);
raimund@2505:
gernotbelger@9256: private final FixingsOverviewServiceAsync overviewService = GWT.create(FixingsOverviewService.class);
raimund@2505:
gernotbelger@9256: private String htmlOverview;
gernotbelger@9256: private FixingsOverviewInfo fixInfo;
gernotbelger@9256: private TabSet tabs;
gernotbelger@9256: private Tab events;
gernotbelger@9256: private Tab chart;
gernotbelger@9256: private VLayout chartContainer;
gernotbelger@9256: private Img chartImg;
gernotbelger@9256: private TextItem kmText;
gernotbelger@9256:
gernotbelger@9256: private static final DateTimeFormat DTF = DateTimeFormat.getFormat("dd.MM.yyyy");
ingo@2962:
raimund@2505: public FixationPanel() {
gernotbelger@9072: this.chartImg = new Img();
gernotbelger@9072: this.htmlOverview = "";
raimund@2505: }
raimund@2505:
felix@3861: /** Get the (master) artifact UUID. */
gernotbelger@9256: private String getArtifactUuid() {
raimund@2505: return this.artifact.getUuid();
raimund@2505: }
raimund@2505:
christian@4568: @Override
gernotbelger@9256: public final Canvas create(final DataList list) {
gernotbelger@9072: final VLayout layout = new VLayout();
raimund@2505:
gernotbelger@9072: final Canvas helper = createHelper();
raimund@2505: this.helperContainer.addMember(helper);
raimund@2505:
gernotbelger@9072: final Canvas submit = getNextButton();
gernotbelger@9072: final Canvas widget = createWidget(list);
raimund@2505:
raimund@2505: layout.addMember(widget);
raimund@2505: layout.addMember(submit);
raimund@2505: return layout;
raimund@2505: }
raimund@2505:
gernotbelger@9256: private Canvas createHelper() {
gernotbelger@9072: final Config config = Config.getInstance();
gernotbelger@9072: final String locale = config.getLocale();
raimund@2505:
gernotbelger@9072: this.tabs = new TabSet();
gernotbelger@9072: this.events = new Tab(this.MESSAGES.events());
gernotbelger@9072: this.chart = new Tab(this.MESSAGES.kmchart());
raimund@2517:
gernotbelger@9072: this.chartContainer = new VLayout();
gernotbelger@9072: final Canvas scroll = createChartHelper();
raimund@2517:
gernotbelger@9072: final VLayout layout = new VLayout();
raimund@2517: layout.addResizedHandler(this);
gernotbelger@9072: layout.addMember(this.chartContainer);
raimund@2517: layout.addMember(scroll);
raimund@2517: layout.setAlign(Alignment.CENTER);
gernotbelger@9072: this.chart.setPane(layout);
raimund@2517:
raimund@2517: final HTMLPane eventPane = new HTMLPane();
raimund@2505:
gernotbelger@9256: // final String river = this.artifact.getArtifactDescription().getRiver();
raimund@2505: createCallback();
sascha@2914:
gernotbelger@9072: final String callBack = "fixationCallback(this.checked, this.name)";
raimund@2884:
gernotbelger@9072: if (this.artifact instanceof AbstractFixBunduArtifact == false)
gernotbelger@9072: return this.chartContainer;
gernotbelger@9072:
gernotbelger@9072: final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;
gernotbelger@9072:
gernotbelger@9255: this.overviewService.generateOverview(locale, this.artifact.getUuid(), getOverviewFilter(art.getFilter()),
gernotbelger@9072: renderCheckboxes(), callBack, new AsyncCallback() {
gernotbelger@9072: @Override
gernotbelger@9072: public void onFailure(final Throwable caught) {
gernotbelger@9072: GWT.log("Could not receive overview.");
gernotbelger@9072: SC.warn(caught.getMessage());
sascha@2923: }
gernotbelger@9072:
gernotbelger@9072: @Override
gernotbelger@9072: public void onSuccess(final FixingsOverviewInfo info) {
gernotbelger@9072: GWT.log("Successfully loaded overview.");
gernotbelger@9072: FixationPanel.this.fixInfo = info;
gernotbelger@9072: FixationPanel.this.htmlOverview = info.getHTML();
gernotbelger@9072: final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) FixationPanel.this.artifact;
gernotbelger@9072: final FixFilter filter = art.getFilter();
gernotbelger@9072: filter.setRiver(info.getRiver());
gernotbelger@9072: if (filter.getCurrentKm() == -Double.MAX_VALUE || filter.getCurrentKm() == -1d) {
gernotbelger@9099: filter.setCurrentKm(filter.getLowerKm());
gernotbelger@9099: filter.setToKm(filter.getUpperKm());
raimund@3362: }
gernotbelger@9072: if (FixationPanel.this.kmText != null) {
gernotbelger@9072: final NumberFormat nf = NumberFormat.getDecimalFormat();
gernotbelger@9072: try {
gernotbelger@9072: final double d = Double.valueOf(filter.getCurrentKm());
gernotbelger@9072: FixationPanel.this.kmText.setValue(nf.format(d));
gernotbelger@9072: }
gernotbelger@9072: catch (final NumberFormatException e) {
gernotbelger@9072: FixationPanel.this.kmText.setValue(filter.getCurrentKm());
gernotbelger@9072: }
gernotbelger@9072: }
gernotbelger@9072: eventPane.setContents(FixationPanel.this.htmlOverview);
gernotbelger@9099: updateChartTab(FixationPanel.this.fixInfo.getLowerKm());
gernotbelger@9072: FixationPanel.this.events.setPane(eventPane);
gernotbelger@9256: success(FixationPanel.this.fixInfo);
sascha@2923: }
gernotbelger@9072: });
raimund@2505:
gernotbelger@9072: this.tabs.addTab(this.events);
gernotbelger@9072: this.tabs.addTab(this.chart);
raimund@2505:
gernotbelger@9072: return this.tabs;
raimund@2505: }
raimund@2505:
gernotbelger@9256: private Canvas createChartHelper() {
gernotbelger@9072: final DynamicForm form = new DynamicForm();
gernotbelger@9072: final Button lower = new Button("<<");
raimund@2517: lower.setWidth(30);
gernotbelger@9072: final Button upper = new Button(">>");
raimund@2517: upper.setWidth(30);
gernotbelger@9072: this.kmText = new TextItem();
gernotbelger@9072: this.kmText.setWidth(60);
gernotbelger@9072: this.kmText.setShowTitle(false);
raimund@3362:
gernotbelger@9072: form.setFields(this.kmText);
raimund@2517: form.setWidth(60);
raimund@2517: lower.addClickHandler(new ClickHandler() {
christian@4568: @Override
gernotbelger@9072: public void onClick(final ClickEvent ce) {
gernotbelger@9072: final FixFilter filter = updateChartTabLow();
gernotbelger@9072: final NumberFormat nf = NumberFormat.getDecimalFormat();
raimund@3362: try {
gernotbelger@9072: final double d = Double.valueOf(filter.getCurrentKm());
gernotbelger@9072: FixationPanel.this.kmText.setValue(nf.format(d));
gernotbelger@9072: }
gernotbelger@9072: catch (final NumberFormatException e) {
gernotbelger@9072: FixationPanel.this.kmText.setValue(filter.getCurrentKm());
raimund@3362: }
raimund@2517: }
raimund@2517: });
raimund@2517:
raimund@2517: upper.addClickHandler(new ClickHandler() {
christian@4568: @Override
gernotbelger@9072: public void onClick(final ClickEvent ce) {
gernotbelger@9072: final FixFilter filter = updateChartTabUp();
gernotbelger@9072: final NumberFormat nf = NumberFormat.getDecimalFormat();
raimund@3362: try {
gernotbelger@9072: final double d = Double.valueOf(filter.getCurrentKm());
gernotbelger@9072: FixationPanel.this.kmText.setValue(nf.format(d));
gernotbelger@9072: }
gernotbelger@9072: catch (final NumberFormatException e) {
gernotbelger@9072: FixationPanel.this.kmText.setValue(filter.getCurrentKm());
raimund@3362: }
raimund@2517: }
raimund@2517: });
raimund@2517:
gernotbelger@9072: this.kmText.addChangedHandler(new ChangedHandler() {
christian@4568: @Override
gernotbelger@9072: public void onChanged(final ChangedEvent ce) {
gernotbelger@9072: // TODO: get current value.
gernotbelger@9072: if (ce.getItem().getValue() != null) {
gernotbelger@9072: final NumberFormat nf = NumberFormat.getDecimalFormat();
raimund@2517: try {
gernotbelger@9072: final double d = nf.parse(ce.getItem().getValue().toString());
sascha@2923: updateChartTab(d);
raimund@2517: }
gernotbelger@9072: catch (final NumberFormatException nfe) {
raimund@2517: // Do nothing.
raimund@2517: }
raimund@2517: }
raimund@2517: }
raimund@2517: });
raimund@2517:
gernotbelger@9072: final HLayout layout = new HLayout();
raimund@2517: layout.setAlign(Alignment.CENTER);
raimund@2517:
raimund@2517: layout.addMember(lower);
raimund@2517: layout.addMember(form);
raimund@2517: layout.addMember(upper);
raimund@2517: return layout;
raimund@2517: }
raimund@2517:
gernotbelger@9256: private void updateChartTab(double km) {
gernotbelger@9072: final Config config = Config.getInstance();
gernotbelger@9072: final String locale = config.getLocale();
raimund@2517:
gernotbelger@9072: final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;
sascha@2923:
gernotbelger@9099: // was soll das all
gernotbelger@9072: if (this.fixInfo != null) {
gernotbelger@9099: if (km < this.fixInfo.getLowerKm())
gernotbelger@9099: km = this.fixInfo.getLowerKm();
gernotbelger@9099: // if (km > this.fixInfo.getTo())
gernotbelger@9099: // km = this.fixInfo.getTo();
raimund@2884: }
sascha@2923:
gernotbelger@9072: final FixFilter filter = art.getFilter();
sascha@2923:
gernotbelger@9099: if (km < filter.getLowerKm())
gernotbelger@9099: km = filter.getLowerKm();
gernotbelger@9099: if (km > filter.getUpperKm())
gernotbelger@9099: km = filter.getUpperKm();
sascha@2923:
sascha@2923: filter.setCurrentKm(km);
raimund@2901:
gernotbelger@9072: int hWidth = this.helperContainer.getWidth() - 12;
gernotbelger@9072: int hHeight = this.helperContainer.getHeight() - 62;
raimund@2901:
gernotbelger@9072: if ((int) (hHeight * 4f / 3) < hWidth) {
gernotbelger@9072: hWidth = (int) (hHeight * 4f / 3);
gernotbelger@9072: } else {
gernotbelger@9072: hHeight = (int) (hWidth * 3f / 4);
raimund@2901: }
raimund@2901:
gernotbelger@9255: final String imgUrl = URL.encode(GWT.getModuleBaseURL()
gernotbelger@9255: + "fixings-km-chart"
gernotbelger@9255: + "?locale=" + locale
gernotbelger@9255: + "&filter=" + getChartFilter(filter, hWidth, hHeight));
raimund@2517:
gernotbelger@9072: if (this.chartContainer.hasMember(this.chartImg)) {
gernotbelger@9072: this.chartImg.setWidth(hWidth);
gernotbelger@9072: this.chartImg.setHeight(hHeight);
gernotbelger@9072: this.chartImg.setSrc(imgUrl);
gernotbelger@9072: } else {
gernotbelger@9072: this.chartImg = new Img(imgUrl, hWidth, hHeight);
gernotbelger@9072: this.chartContainer.addMember(this.chartImg);
sascha@2922: }
raimund@2517: }
raimund@2517:
gernotbelger@9256: private FixFilter updateChartTabLow() {
gernotbelger@9072: final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;
raimund@2884:
gernotbelger@9072: final FixFilter filter = art.getFilter();
sascha@2923:
gernotbelger@9072: final double curr = filter.getCurrentKm();
gernotbelger@9099: if (curr > filter.getLowerKm()) {
gernotbelger@9072: final double newVal = (curr - 0.1) * 10;
gernotbelger@9072: final long round = Math.round(newVal);
gernotbelger@9072: updateChartTab(((double) round) / 10);
raimund@2517: }
sascha@2923: return filter;
raimund@2517: }
raimund@2517:
gernotbelger@9256: private FixFilter updateChartTabUp() {
gernotbelger@9072: final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;
raimund@2884:
gernotbelger@9072: final FixFilter filter = art.getFilter();
sascha@2923:
gernotbelger@9072: final double curr = filter.getCurrentKm();
gernotbelger@9099: if (curr < filter.getUpperKm()) {
gernotbelger@9072: final double newVal = (curr + 0.1) * 10;
gernotbelger@9072: final long round = Math.round(newVal);
gernotbelger@9072: updateChartTab(((double) round) / 10);
raimund@2517: }
sascha@2923: return filter;
raimund@2517: }
raimund@2517:
christian@4568: @Override
gernotbelger@9256: public final void onResized(final ResizedEvent re) {
gernotbelger@9072: final AbstractFixBunduArtifact art = (AbstractFixBunduArtifact) this.artifact;
raimund@2884:
raimund@2884: updateChartTab(art.getFilter().getCurrentKm());
raimund@2517: }
raimund@2517:
raimund@2505: private native void createCallback() /*-{
teichmann@5835: $wnd.fixationCallback = @org.dive4elements.river.client.client.ui.fixation.FixationPanel::helperCallback(ZLjava/lang/String;);
raimund@2505: }-*/;
raimund@2505:
gernotbelger@9072: private static void helperCallback(final boolean checked, final String name) {
gernotbelger@9072: final String[] parts = name.split(":");
gernotbelger@9072: final String uuid = parts[0];
gernotbelger@9072: final String cid = parts[1];
ingo@2962:
gernotbelger@9072: final FixationPanel p = FixationPanel.getInstance(uuid);
raimund@2505: if (p != null) {
raimund@2505: p.setValues(cid, checked);
raimund@2505: }
raimund@2505: }
raimund@2505:
gernotbelger@9072: private static FixationPanel getInstance(final String uuid) {
sascha@2923: return instances.get(uuid);
raimund@2505: }
raimund@2505:
gernotbelger@9256: protected abstract Canvas createWidget(DataList data);
gernotbelger@9072:
gernotbelger@9256: protected abstract void setValues(String cid, boolean checked);
gernotbelger@9072:
gernotbelger@9256: protected abstract boolean renderCheckboxes();
gernotbelger@9072:
gernotbelger@9256: protected abstract void success(FixingsOverviewInfo fixInfo);
raimund@2517:
felix@5334: /** Creates JSON string from filter. */
gernotbelger@9256: private static String getOverviewFilter(final FixFilter filter) {
gernotbelger@9072: final String river = filter.getRiver();
raimund@2517:
ingo@2962: if (river != null && river.length() > 0) {
gernotbelger@9072: final JSONObject jfix = new JSONObject();
gernotbelger@9072: final JSONObject jfilter = new JSONObject();
gernotbelger@9072: final JSONObject jrName = new JSONObject();
gernotbelger@9072: final JSONString jrValue = new JSONString(river);
ingo@2962: jrName.put("name", jrValue);
ingo@2962: jfilter.put("river", jrName);
ingo@2962: jfix.put("fixings", createFilter(filter, jfilter));
ingo@2962: return jfix.toString();
raimund@2517: }
ingo@2962: return "";
ingo@2962: }
raimund@2517:
gernotbelger@9256: private String getChartFilter(final FixFilter filter, final int width, final int height) {
gernotbelger@9072: final String river = filter.getRiver();
gernotbelger@9072: final double currentKm = filter.getCurrentKm();
gernotbelger@9099: final double fromKm = filter.getLowerKm();
gernotbelger@9099: final double toKm = filter.getUpperKm();
raimund@2517:
gernotbelger@9072: if (river != null && river.length() > 0 && currentKm >= fromKm && currentKm <= toKm) {
gernotbelger@9072: final JSONObject jfix = new JSONObject();
gernotbelger@9072: final JSONObject jfilter = new JSONObject();
gernotbelger@9072: final JSONObject jrName = new JSONObject();
gernotbelger@9072: final JSONString jrValue = new JSONString(river);
gernotbelger@9072: final JSONObject jkm = new JSONObject();
gernotbelger@9072: final JSONNumber jkmValue = new JSONNumber(currentKm);
gernotbelger@9072: final JSONObject jextent = new JSONObject();
gernotbelger@9072: final JSONNumber jwidth = new JSONNumber(width);
gernotbelger@9072: final JSONNumber jheight = new JSONNumber(height);
ingo@2962:
ingo@2962: jkm.put("value", jkmValue);
ingo@2962: jrName.put("name", jrValue);
ingo@2962: jfilter.put("river", jrName);
ingo@2962: jfilter.put("km", jkm);
ingo@2962: jextent.put("width", jwidth);
ingo@2962: jextent.put("height", jheight);
ingo@2962: jfilter.put("extent", jextent);
ingo@2962: jfix.put("fixings", createFilter(filter, jfilter));
ingo@2962: return jfix.toString();
raimund@2517: }
ingo@2962: return "";
ingo@2962: }
raimund@2517:
gernotbelger@9256: private static JSONObject createFilter(final FixFilter filter, final JSONObject root) {
gernotbelger@9099: final double fromKm = filter.getLowerKm();
gernotbelger@9099: final double toKm = filter.getUpperKm();
gernotbelger@9072: final boolean hasDate = filter.hasDate();
raimund@2517:
ingo@2962: if (fromKm >= 0 && toKm >= 0 && fromKm <= toKm) {
gernotbelger@9072: final JSONObject range = new JSONObject();
gernotbelger@9072: final JSONObject fromtokm = new JSONObject();
gernotbelger@9072: final JSONNumber f = new JSONNumber(fromKm);
gernotbelger@9072: final JSONNumber t = new JSONNumber(toKm);
ingo@2962: fromtokm.put("from", f);
ingo@2962: fromtokm.put("to", t);
ingo@2962: root.put("range", fromtokm);
raimund@2517: }
raimund@2517:
gernotbelger@9072: final JSONObject and = new JSONObject();
ingo@2962: if (hasDate) {
gernotbelger@9072: final long fromDate = filter.getFromDate();
gernotbelger@9072: final long toDate = filter.getToDate();
raimund@2517:
gernotbelger@9072: final Date df = new Date(fromDate);
gernotbelger@9072: final Date dt = new Date(toDate);
raimund@2884:
gernotbelger@9072: final JSONObject daterange = new JSONObject();
gernotbelger@9072: final JSONString f = new JSONString(DTF.format(df));
gernotbelger@9072: final JSONString t = new JSONString(DTF.format(dt));
ingo@2962:
ingo@2962: daterange.put("from", f);
ingo@2962: daterange.put("to", t);
ingo@2962: and.put("date-range", daterange);
raimund@2517: }
raimund@2517:
gernotbelger@9072: final int fromClass = filter.getFromClass();
gernotbelger@9072: final int toClass = filter.getToClass();
ingo@2962:
ingo@2962: if (fromClass >= 0 && toClass >= 0 && fromClass <= toClass) {
gernotbelger@9072: final JSONObject classrange = new JSONObject();
gernotbelger@9072: final JSONNumber f = new JSONNumber(fromClass);
gernotbelger@9072: final JSONNumber t = new JSONNumber(toClass);
ingo@2962:
ingo@2962: classrange.put("from", f);
ingo@2962: classrange.put("to", t);
ingo@2962: and.put("sector-range", classrange);
ingo@2962: }
ingo@2962:
gernotbelger@9072: final int[] events = filter.getEvents();
ingo@2962:
ingo@2962: if (events.length > 0) {
gernotbelger@9072: final StringBuilder cids = new StringBuilder();
ingo@2962:
ingo@2962: for (int i = 0; i < events.length; i++) {
gernotbelger@9072: if (i > 0)
gernotbelger@9072: cids.append(' ');
ingo@2962: cids.append(events[i]);
raimund@2884: }
gernotbelger@9072: final JSONObject columns = new JSONObject();
ingo@2962: columns.put("cids", new JSONString(cids.toString()));
ingo@2962: and.put("columns", columns);
raimund@2517: }
ingo@2962: if (and.size() > 0) {
gernotbelger@9072: final JSONObject jFilter = new JSONObject();
ingo@2962: jFilter.put("and", and);
ingo@2962: root.put("filter", jFilter);
ingo@2962: }
ingo@2962: return root;
raimund@2517: }
gernotbelger@9256: }