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: raimund@2505: import com.google.gwt.core.client.GWT; 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; raimund@2505: 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: teichmann@5835: import org.dive4elements.river.client.client.Config; teichmann@5835: import org.dive4elements.river.client.client.FLYSConstants; teichmann@5835: import org.dive4elements.river.client.client.services.FixingsOverviewService; teichmann@5835: import org.dive4elements.river.client.client.services.FixingsOverviewServiceAsync; teichmann@5835: import org.dive4elements.river.client.client.ui.AbstractUIProvider; teichmann@7281: import org.dive4elements.river.client.shared.MapUtils; teichmann@5835: import org.dive4elements.river.client.shared.model.Data; teichmann@5835: import org.dive4elements.river.client.shared.model.DataList; teichmann@5835: import org.dive4elements.river.client.shared.model.FixAnalysisArtifact; teichmann@5835: import org.dive4elements.river.client.shared.model.FixFilter; teichmann@5835: import org.dive4elements.river.client.shared.model.FixingsOverviewInfo; raimund@2505: sascha@3366: import java.util.Date; sascha@3366: import java.util.HashMap; raimund@2505: 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: */ raimund@2505: public abstract class FixationPanel raimund@2517: extends AbstractUIProvider raimund@2517: implements ResizedHandler raimund@2505: { christian@4568: private static final long serialVersionUID = -3667553404493415619L; christian@4568: tom@8856: protected static HashMap instances = tom@8856: new HashMap(); raimund@2505: raimund@2505: /** The message class that provides i18n strings. */ raimund@2505: protected FLYSConstants MESSAGES = GWT.create(FLYSConstants.class); raimund@2505: raimund@2505: protected FixingsOverviewServiceAsync overviewService = raimund@2505: GWT.create(FixingsOverviewService.class); raimund@2505: felix@3861: protected String htmlOverview; raimund@2505: protected FixingsOverviewInfo fixInfo; raimund@2517: protected TabSet tabs; raimund@2517: protected Tab events; raimund@2517: protected Tab chart; raimund@2517: protected VLayout chartContainer; raimund@2517: protected Img chartImg; sascha@2923: protected TextItem kmText; raimund@2505: tom@8856: public static final DateTimeFormat DTF = DateTimeFormat.getFormat( tom@8856: "dd.MM.yyyy"); ingo@2962: ingo@2962: raimund@2505: public FixationPanel() { raimund@2517: chartImg = new Img(); raimund@2505: htmlOverview = ""; raimund@2505: } raimund@2505: christian@4568: felix@3861: /** Get the (master) artifact UUID. */ raimund@2505: protected String getArtifactUuid() { raimund@2505: return this.artifact.getUuid(); raimund@2505: } raimund@2505: raimund@2505: protected void init() { raimund@2505: } raimund@2505: christian@4568: @Override raimund@2505: public Data[] getData() { raimund@2505: return null; raimund@2505: } raimund@2505: christian@4568: @Override raimund@2505: public Canvas create(DataList list) { raimund@2505: VLayout layout = new VLayout(); raimund@2505: raimund@2505: Canvas helper = createHelper(); raimund@2505: this.helperContainer.addMember(helper); raimund@2505: raimund@2505: Canvas submit = getNextButton(); raimund@2505: Canvas widget = createWidget(list); raimund@2505: raimund@2505: layout.addMember(widget); raimund@2505: layout.addMember(submit); raimund@2505: return layout; raimund@2505: } raimund@2505: christian@4568: @Override raimund@2505: public Canvas createOld(DataList list) { raimund@2505: return new DynamicForm(); raimund@2505: } raimund@2505: raimund@2505: protected Canvas createHelper() { raimund@2505: Config config = Config.getInstance(); raimund@2505: String locale = config.getLocale (); raimund@2505: raimund@2517: tabs = new TabSet(); raimund@2517: events = new Tab(MESSAGES.events()); raimund@2517: chart = new Tab(MESSAGES.kmchart()); raimund@2517: raimund@2517: chartContainer = new VLayout(); raimund@2517: Canvas scroll = createChartHelper(); raimund@2517: raimund@2517: VLayout layout = new VLayout(); raimund@2517: layout.addResizedHandler(this); raimund@2517: layout.addMember(chartContainer); raimund@2517: layout.addMember(scroll); raimund@2517: layout.setAlign(Alignment.CENTER); raimund@2517: chart.setPane(layout); raimund@2517: raimund@2517: final HTMLPane eventPane = new HTMLPane(); raimund@2505: raimund@2505: String river = artifact.getArtifactDescription().getRiver(); raimund@2505: createCallback(); sascha@2914: raimund@2505: String callBack = "fixationCallback(this.checked, this.name)"; felix@4148: felix@4148: if (this.artifact instanceof FixAnalysisArtifact == false) felix@4148: return chartContainer; felix@4148: raimund@2884: FixAnalysisArtifact art = (FixAnalysisArtifact) this.artifact; raimund@2884: raimund@2505: overviewService.generateOverview( raimund@2505: locale, raimund@2505: artifact.getUuid(), teichmann@7281: MapUtils.toJavaEncodedString(getOverviewFilter(art.getFilter())), raimund@2505: renderCheckboxes(), raimund@2505: callBack, raimund@2505: new AsyncCallback() { christian@4568: @Override raimund@2505: public void onFailure(Throwable caught) { raimund@2505: GWT.log("Could not receive overview."); raimund@2505: SC.warn(caught.getMessage()); raimund@2505: } christian@4568: @Override raimund@2505: public void onSuccess(FixingsOverviewInfo info) { raimund@2505: GWT.log("Successfully loaded overview."); raimund@2505: fixInfo = info; raimund@2505: htmlOverview = info.getHTML(); raimund@2884: FixAnalysisArtifact art = (FixAnalysisArtifact)artifact; sascha@2923: FixFilter filter = art.getFilter(); sascha@2923: filter.setRiver(info.getRiver()); raimund@3362: if (filter.getCurrentKm() == -Double.MAX_VALUE || raimund@3362: filter.getCurrentKm() == -1d) { sascha@2923: filter.setCurrentKm(info.getFrom()); sascha@2923: filter.setToKm(info.getTo()); sascha@2923: } sascha@2923: if (kmText != null) { raimund@3362: NumberFormat nf = NumberFormat.getDecimalFormat(); raimund@3362: try { raimund@3362: double d = Double.valueOf(filter.getCurrentKm()); raimund@3362: kmText.setValue(nf.format(d)); raimund@3362: } catch (NumberFormatException e) { raimund@3362: kmText.setValue(filter.getCurrentKm()); raimund@3362: } sascha@2923: } raimund@2517: eventPane.setContents(htmlOverview); raimund@2517: updateChartTab(fixInfo.getFrom()); raimund@2517: events.setPane(eventPane); raimund@2537: success(); raimund@2505: } raimund@2505: }); raimund@2505: raimund@2517: tabs.addTab(events); raimund@2517: tabs.addTab(chart); raimund@2505: raimund@2517: return tabs; raimund@2505: } raimund@2505: raimund@2517: raimund@2517: protected Canvas createChartHelper() { raimund@2517: DynamicForm form = new DynamicForm(); raimund@2517: Button lower = new Button("<<"); raimund@2517: lower.setWidth(30); raimund@2517: Button upper = new Button(">>"); raimund@2517: upper.setWidth(30); sascha@2923: kmText = new TextItem(); sascha@2923: kmText.setWidth(60); sascha@2923: kmText.setShowTitle(false); raimund@3362: raimund@2517: sascha@2923: form.setFields(kmText); raimund@2517: form.setWidth(60); raimund@2517: lower.addClickHandler(new ClickHandler() { christian@4568: @Override raimund@2517: public void onClick(ClickEvent ce) { sascha@2923: FixFilter filter = updateChartTabLow(); raimund@3362: NumberFormat nf = NumberFormat.getDecimalFormat(); raimund@3362: try { raimund@3362: double d = Double.valueOf(filter.getCurrentKm()); raimund@3362: kmText.setValue(nf.format(d)); raimund@3362: } catch (NumberFormatException e) { raimund@3362: kmText.setValue(filter.getCurrentKm()); raimund@3362: } raimund@2517: } raimund@2517: }); raimund@2517: raimund@2517: upper.addClickHandler(new ClickHandler() { christian@4568: @Override raimund@2517: public void onClick(ClickEvent ce) { sascha@2923: FixFilter filter = updateChartTabUp(); raimund@3362: NumberFormat nf = NumberFormat.getDecimalFormat(); raimund@3362: try { raimund@3362: double d = Double.valueOf(filter.getCurrentKm()); raimund@3362: kmText.setValue(nf.format(d)); raimund@3362: } catch (NumberFormatException e) { raimund@3362: kmText.setValue(filter.getCurrentKm()); raimund@3362: } raimund@2517: } raimund@2517: }); raimund@2517: sascha@2923: kmText.addChangedHandler(new ChangedHandler() { christian@4568: @Override raimund@2517: public void onChanged(ChangedEvent ce) { raimund@2517: //TODO: get current value. raimund@3362: if(ce.getItem().getValue() != null) { raimund@3362: NumberFormat nf = NumberFormat.getDecimalFormat(); raimund@2517: try { raimund@3362: double d = nf.parse(ce.getItem().getValue().toString()); sascha@2923: updateChartTab(d); raimund@2517: } raimund@2517: catch(NumberFormatException nfe) { raimund@2517: // Do nothing. raimund@2517: } raimund@2517: } raimund@2517: } raimund@2517: }); raimund@2517: raimund@2517: 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: raimund@2517: protected void updateChartTab(double km) { raimund@2517: Config config = Config.getInstance(); raimund@2517: String locale = config.getLocale (); raimund@2517: raimund@2884: FixAnalysisArtifact art = (FixAnalysisArtifact) this.artifact; sascha@2923: sascha@2923: if (fixInfo != null) { sascha@2923: if (km < fixInfo.getFrom()) km = fixInfo.getFrom(); sascha@2923: if (km > fixInfo.getTo()) km = fixInfo.getTo(); raimund@2884: } sascha@2923: sascha@2923: FixFilter filter = art.getFilter(); sascha@2923: sascha@2923: if (km < filter.getFromKm()) km = filter.getFromKm(); sascha@2923: if (km > filter.getToKm()) km = filter.getToKm(); sascha@2923: sascha@2923: filter.setCurrentKm(km); raimund@2901: raimund@2901: int hWidth = helperContainer.getWidth() - 12; raimund@2901: int hHeight = helperContainer.getHeight() - 62; raimund@2901: sascha@2922: if ((int)(hHeight *4f/3) < hWidth) { sascha@2922: hWidth = (int)(hHeight * 4f/3); raimund@2901: } raimund@2901: else { sascha@2922: hHeight = (int)(hWidth *3f/4); raimund@2901: } raimund@2901: raimund@2517: String imgUrl = GWT.getModuleBaseURL(); raimund@2517: imgUrl += "fixings-km-chart"; raimund@2517: imgUrl += "?locale=" + locale; ingo@2962: imgUrl += "&filter=" + getChartFilter(filter, hWidth, hHeight); raimund@2517: sascha@2922: if (chartContainer.hasMember(chartImg)) { sascha@2922: chartImg.setWidth(hWidth); sascha@2922: chartImg.setHeight(hHeight); sascha@2922: chartImg.setSrc(imgUrl); sascha@2922: } sascha@2922: else { sascha@2922: chartImg = new Img(imgUrl, hWidth, hHeight); sascha@2922: chartContainer.addMember(chartImg); sascha@2922: } raimund@2517: } raimund@2517: raimund@2517: sascha@2923: protected FixFilter updateChartTabLow() { raimund@2884: FixAnalysisArtifact art = (FixAnalysisArtifact) this.artifact; raimund@2884: sascha@2923: FixFilter filter = art.getFilter(); sascha@2923: sascha@2923: double curr = filter.getCurrentKm(); sascha@2923: if (curr > filter.getFromKm()) { raimund@2517: double newVal = (curr - 0.1) * 10; raimund@2517: long round = Math.round(newVal); raimund@2517: updateChartTab(((double)round) / 10); raimund@2517: } sascha@2923: return filter; raimund@2517: } raimund@2517: raimund@2517: sascha@2923: protected FixFilter updateChartTabUp() { raimund@2884: FixAnalysisArtifact art = (FixAnalysisArtifact) this.artifact; raimund@2884: sascha@2923: FixFilter filter = art.getFilter(); sascha@2923: sascha@2923: double curr = filter.getCurrentKm(); sascha@2923: if (curr < filter.getToKm()) { raimund@2517: double newVal = (curr + 0.1) * 10; raimund@2517: long round = Math.round(newVal); raimund@2517: updateChartTab(((double)round) / 10); raimund@2517: } sascha@2923: return filter; raimund@2517: } raimund@2517: raimund@2517: christian@4568: @Override raimund@2517: public void onResized(ResizedEvent re) { raimund@2884: FixAnalysisArtifact art = (FixAnalysisArtifact) this.artifact; raimund@2884: raimund@2884: updateChartTab(art.getFilter().getCurrentKm()); raimund@2517: } 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: raimund@2505: private static void helperCallback(boolean checked, String name) { raimund@2505: String[] parts = name.split(":"); raimund@2505: String uuid = parts[0]; raimund@2505: String cid = parts[1]; ingo@2962: raimund@2505: FixationPanel p = FixationPanel.getInstance(uuid); raimund@2505: if (p != null) { raimund@2505: p.setValues(cid, checked); raimund@2505: } raimund@2505: } raimund@2505: raimund@2505: private static FixationPanel getInstance(String uuid) { sascha@2923: return instances.get(uuid); raimund@2505: } raimund@2505: raimund@2505: public abstract Canvas createWidget(DataList data); raimund@2505: public abstract void setValues(String cid, boolean checked); raimund@2505: public abstract boolean renderCheckboxes(); raimund@2537: public abstract void success(); raimund@2517: raimund@2517: felix@5334: /** Creates JSON string from filter. */ ingo@2962: public static String getOverviewFilter(FixFilter filter) { ingo@2962: String river = filter.getRiver(); raimund@2517: ingo@2962: if (river != null && river.length() > 0) { ingo@2962: JSONObject jfix = new JSONObject(); ingo@2962: JSONObject jfilter = new JSONObject(); ingo@2962: JSONObject jrName = new JSONObject(); ingo@2962: 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: ingo@2962: public String getChartFilter(FixFilter filter, int width, int height) { ingo@2962: String river = filter.getRiver(); ingo@2962: double currentKm = filter.getCurrentKm(); ingo@2962: double fromKm = filter.getFromKm(); ingo@2962: double toKm = filter.getToKm(); raimund@2517: ingo@2962: if (river != null && river.length() > 0 && ingo@2962: currentKm >= fromKm && currentKm <= toKm) ingo@2962: { ingo@2962: JSONObject jfix = new JSONObject(); ingo@2962: JSONObject jfilter = new JSONObject(); ingo@2962: JSONObject jrName = new JSONObject(); ingo@2962: JSONString jrValue = new JSONString(river); ingo@2962: JSONObject jkm = new JSONObject(); ingo@2962: JSONNumber jkmValue = new JSONNumber(currentKm); ingo@2962: JSONObject jextent = new JSONObject(); ingo@2962: JSONNumber jwidth = new JSONNumber(width); ingo@2962: 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: tom@8856: protected static JSONObject createFilter( tom@8856: FixFilter filter, tom@8856: JSONObject root tom@8856: ) { ingo@2962: double fromKm = filter.getFromKm(); ingo@2962: double toKm = filter.getToKm(); rrenkert@8400: boolean hasDate = filter.hasDate(); raimund@2517: ingo@2962: if (fromKm >= 0 && toKm >= 0 && fromKm <= toKm) { ingo@2962: JSONObject range = new JSONObject(); ingo@2962: JSONObject fromtokm = new JSONObject(); ingo@2962: JSONNumber f = new JSONNumber(fromKm); ingo@2962: 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: ingo@2962: JSONObject and = new JSONObject(); ingo@2962: if (hasDate) { ingo@2962: long fromDate = filter.getFromDate(); ingo@2962: long toDate = filter.getToDate(); raimund@2517: ingo@2962: Date df = new Date(fromDate); ingo@2962: Date dt = new Date(toDate); raimund@2884: ingo@2962: JSONObject daterange = new JSONObject(); ingo@2962: JSONString f = new JSONString(DTF.format(df)); ingo@2962: 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: ingo@2962: int fromClass = filter.getFromClass(); ingo@2962: int toClass = filter.getToClass(); ingo@2962: ingo@2962: if (fromClass >= 0 && toClass >= 0 && fromClass <= toClass) { ingo@2962: JSONObject classrange = new JSONObject(); ingo@2962: JSONNumber f = new JSONNumber(fromClass); ingo@2962: 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: ingo@2962: int[] events = filter.getEvents(); ingo@2962: ingo@2962: if (events.length > 0) { ingo@2962: StringBuilder cids = new StringBuilder(); ingo@2962: ingo@2962: for (int i = 0; i < events.length; i++) { ingo@2962: if (i > 0) cids.append(' '); ingo@2962: cids.append(events[i]); raimund@2884: } ingo@2962: 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) { ingo@2962: JSONObject jFilter = new JSONObject(); ingo@2962: jFilter.put("and", and); ingo@2962: root.put("filter", jFilter); ingo@2962: } ingo@2962: return root; raimund@2517: } raimund@2505: } felix@3861: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :