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: }