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.stationinfo; bjoern@4956: bjoern@4956: import java.util.ArrayList; bjoern@4956: import java.util.List; bjoern@4956: rrenkert@8303: import org.dive4elements.river.client.client.Config; teichmann@5835: import org.dive4elements.river.client.client.FLYS; rrenkert@8303: import org.dive4elements.river.client.client.services.AdvanceService; rrenkert@8303: import org.dive4elements.river.client.client.services.AdvanceServiceAsync; rrenkert@8303: import org.dive4elements.river.client.client.services.ArtifactService; rrenkert@8303: import org.dive4elements.river.client.client.services.ArtifactServiceAsync; rrenkert@8303: import org.dive4elements.river.client.client.services.CreateCollectionService; rrenkert@8303: import org.dive4elements.river.client.client.services.CreateCollectionServiceAsync; rrenkert@8303: import org.dive4elements.river.client.client.services.StepForwardService; rrenkert@8303: import org.dive4elements.river.client.client.services.StepForwardServiceAsync; rrenkert@8303: import org.dive4elements.river.client.client.ui.CollectionView; gernotbelger@9270: import org.dive4elements.river.client.client.ui.StringArrayParseHelper; rrenkert@8303: import org.dive4elements.river.client.shared.model.Artifact; rrenkert@8303: import org.dive4elements.river.client.shared.model.Collection; teichmann@5835: import org.dive4elements.river.client.shared.model.Data; teichmann@5835: import org.dive4elements.river.client.shared.model.DataItem; teichmann@5835: import org.dive4elements.river.client.shared.model.DataList; rrenkert@8303: import org.dive4elements.river.client.shared.model.DefaultData; rrenkert@8303: import org.dive4elements.river.client.shared.model.DefaultDataItem; teichmann@5835: import org.dive4elements.river.client.shared.model.GaugeInfo; teichmann@5835: import org.dive4elements.river.client.shared.model.RiverInfo; bjoern@4956: gernotbelger@9093: import com.google.gwt.core.client.GWT; gernotbelger@9093: import com.google.gwt.user.client.rpc.AsyncCallback; gernotbelger@9093: import com.smartgwt.client.util.SC; gernotbelger@9093: import com.smartgwt.client.widgets.Canvas; gernotbelger@9093: import com.smartgwt.client.widgets.grid.ListGridField; gernotbelger@9093: import com.smartgwt.client.widgets.grid.ListGridRecord; gernotbelger@9093: import com.smartgwt.client.widgets.grid.events.RecordClickEvent; gernotbelger@9093: import com.smartgwt.client.widgets.grid.events.RecordClickHandler; bjoern@4956: bjoern@4956: /** bjoern@4956: * @author Björn Ricks bjoern@4956: */ bjoern@4960: public class GaugeListGrid extends InfoListGrid implements RecordClickHandler { bjoern@4956: gernotbelger@9093: public static enum DisappearType { gernotbelger@9093: remove, collapse, stayVisible gernotbelger@9093: } gernotbelger@9093: bjoern@4961: private static final int ABFLUSSTAFEL_COLUMN = 6; bjoern@4961: rrenkert@8303: /** The ArtifactService used to communicate with the Artifact server. */ gernotbelger@9093: protected ArtifactServiceAsync artifactService = GWT.create(ArtifactService.class); rrenkert@8303: rrenkert@8303: /** The StepForwardService used to put data into an existing artifact. */ gernotbelger@9093: protected StepForwardServiceAsync forwardService = GWT.create(StepForwardService.class); rrenkert@8303: gernotbelger@9093: /** The ArtifactService used to communicate with the Artifact server. */ gernotbelger@9093: protected CreateCollectionServiceAsync createCollectionService = GWT.create(CreateCollectionService.class); gernotbelger@9093: gernotbelger@9093: /** The StepForwardService used to put data into an existing artifact. */ gernotbelger@9093: protected AdvanceServiceAsync advanceService = GWT.create(AdvanceService.class); gernotbelger@9093: gernotbelger@9093: private final List gauges = new ArrayList(); gernotbelger@9093: gernotbelger@9093: public GaugeListGrid(final FLYS flys) { bjoern@4956: super(flys); gernotbelger@9473: gernotbelger@9473: final ListGridField nfield = new ListGridField("name", this.MSG.gauge_list_grid_gauge()); gernotbelger@9473: final ListGridField sfield = new ListGridField("kmstart", this.MSG.gauge_list_grid_start(), 60); gernotbelger@9473: final ListGridField efield = new ListGridField("kmend", this.MSG.gauge_list_grid_end(), 60); gernotbelger@9473: final ListGridField stfield = new ListGridField("station", this.MSG.gauge_list_grid_station()); gernotbelger@9473: final ListGridField lfield = new ListGridField("infolink", this.MSG.gauge_list_grid_info()); gernotbelger@9093: final ListGridField cfield = new ListGridField("curvelink", this.MSG.gauge_curve_link()); bjoern@4959: cfield.addRecordClickHandler(this); bjoern@4956: rrenkert@6272: this.setShowRecordComponents(true); rrenkert@6272: this.setShowRecordComponentsByCell(true); bjoern@4959: this.setFields(nfield, sfield, efield, stfield, lfield, cfield); bjoern@4956: } bjoern@4956: gernotbelger@9093: @Override gernotbelger@9093: public void setRiverInfo(final RiverInfo riverinfo) { gernotbelger@9093: final List gauges = riverinfo.getGauges(); bjoern@4956: bjoern@4956: if (gauges != null && !gauges.isEmpty()) { bjoern@4956: gernotbelger@9093: final ArrayList emptygauges = new ArrayList(); bjoern@4956: bjoern@4956: if (!riverinfo.isKmUp()) { gernotbelger@9093: for (final GaugeInfo gauge : gauges) { bjoern@4956: addGauge(gauge, emptygauges); bjoern@4956: } gernotbelger@9093: } else { gernotbelger@9093: for (int i = gauges.size() - 1; i >= 0; i--) { gernotbelger@9093: final GaugeInfo gauge = gauges.get(i); bjoern@4956: addGauge(gauge, emptygauges); bjoern@4956: } bjoern@4956: } bjoern@4956: bjoern@4956: // put empty gauges to the end gernotbelger@9093: for (final GaugeInfo gauge : emptygauges) { bjoern@4956: addGauge(gauge); bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: gernotbelger@9093: private void addGauge(final GaugeInfo gauge, final List empty) { bjoern@4956: if (gauge.getKmStart() != null && gauge.getKmEnd() != null) { bjoern@4956: addGauge(gauge); gernotbelger@9093: } else { bjoern@4956: empty.add(gauge); bjoern@4956: } bjoern@4956: } bjoern@4956: gernotbelger@9093: private void addGauge(final GaugeInfo gauge) { gernotbelger@9093: gernotbelger@9093: this.gauges.add(gauge); gernotbelger@9093: gernotbelger@9093: // this.addData(new GaugeRecord(gauge)); gernotbelger@9093: bjoern@4956: } bjoern@4956: gernotbelger@9093: @Override bjoern@4956: public void open() { gernotbelger@9093: final ArrayList locations = new ArrayList(); bjoern@4956: gernotbelger@9093: if (this.data != null && this.data.length > 0) { gernotbelger@9093: for (final DataList dl : this.data) { gernotbelger@9093: gernotbelger@9093: final String state = dl.getState(); gernotbelger@9093: DisappearType type = DisappearType.collapse; gernotbelger@9093: if (state.contains("state.bundu.") || state.contains("state.fix.")) { gernotbelger@9093: type = DisappearType.remove; gernotbelger@9093: } gernotbelger@9093: bjoern@4956: GWT.log("GaugeListGrid - open " + state); gernotbelger@9093: if (state.contains(".location_distance")) { bjoern@4956: Double ldfrom = null; bjoern@4956: Double ldto = null; bjoern@4956: gernotbelger@9093: for (int j = dl.size() - 1; j >= 0; --j) { gernotbelger@9093: final Data d = dl.get(j); gernotbelger@9093: final String label = d.getLabel(); gernotbelger@9093: GWT.log("GaugeListGrid - setData - label " + label + " " + d.getStringValue()); bjoern@4956: if (label.equals("ld_from")) { bjoern@4956: ldfrom = getDoubleValue(d); gernotbelger@9093: } else if (label.equals("ld_to")) { bjoern@4956: ldto = getDoubleValue(d); gernotbelger@9093: } else if (label.equals("ld_locations")) { bjoern@4956: getLocationsFromData(locations, d); bjoern@4956: openOnLocations(locations); bjoern@4956: return; bjoern@4956: } bjoern@4956: } bjoern@4956: if (ldfrom != null) { gernotbelger@9093: gernotbelger@9093: openOnDistance(ldfrom, ldto, type); bjoern@4956: return; bjoern@4956: } gernotbelger@9093: } else if (state.contains(".distance_only") || state.contains(".distance") gernotbelger@9093: || state.contains(".location") && !state.contains(".location_distance")) { bjoern@4956: Double ldfrom = null; bjoern@4956: Double ldto = null; bjoern@4956: gernotbelger@9093: for (int j = dl.size() - 1; j >= 0; --j) { gernotbelger@9093: final Data d = dl.get(j); gernotbelger@9093: final String label = d.getLabel(); gernotbelger@9093: GWT.log("GaugeListGrid - setData - label " + label + " " + d.getStringValue()); bjoern@4956: if (label.equals("ld_from")) { bjoern@4956: ldfrom = getDoubleValue(d); gernotbelger@9093: } else if (label.equals("ld_to")) { bjoern@4956: ldto = getDoubleValue(d); bjoern@4956: } bjoern@4956: } bjoern@4956: bjoern@4956: if (ldfrom != null) { gernotbelger@9093: openOnDistance(ldfrom, ldto, type); bjoern@4956: return; bjoern@4956: } gernotbelger@9093: } else if (state.equals("state.winfo.location")) { bjoern@4956: getLocations("ld_locations", locations, dl); bjoern@4956: openOnLocations(locations); bjoern@4956: return; gernotbelger@9093: } else if (state.equals("state.winfo.reference.curve.input.start")) { bjoern@4956: getLocations("reference_startpoint", locations, dl); gernotbelger@9093: } else if (state.equals("state.winfo.reference.curve.input.end")) { bjoern@4956: getLocations("reference_endpoint", locations, dl); gernotbelger@9093: } else if (state.equals("state.winfo.historicalq.reference_gauge")) { gernotbelger@9093: for (int j = dl.size() - 1; j >= 0; --j) { gernotbelger@9093: final Data d = dl.get(j); gernotbelger@9093: final String label = d.getLabel(); bjoern@4956: if (label.equals("reference_gauge")) { gernotbelger@9093: final String tmp = d.getStringValue(); bjoern@4956: if (tmp != null) { gernotbelger@9093: final Long gaugereference = Long.valueOf(tmp); bjoern@4956: if (gaugereference != null) { bjoern@4956: openOnReference(gaugereference); bjoern@4956: return; bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: if (!locations.isEmpty()) { bjoern@4956: openOnLocations(locations); gernotbelger@9473: } else if (this.data != null && this.data.length == 1) { gernotbelger@9275: // During selection of calc-mode: all gauges should be collapsed gernotbelger@9275: collapseAll(); gernotbelger@9473: } else { bjoern@4956: openAll(); bjoern@4956: } bjoern@4956: } bjoern@4956: gernotbelger@9093: @Override gernotbelger@9093: public void openAll() { gernotbelger@9093: gernotbelger@9093: GWT.log("InfoListGrid - openAll"); gernotbelger@9093: gernotbelger@9093: setData(new ListGridRecord[] {}); gernotbelger@9093: for (final GaugeInfo gauge : this.gauges) { gernotbelger@9093: addExpandedRecord(gauge); gernotbelger@9093: } gernotbelger@9093: } gernotbelger@9093: gernotbelger@9275: private void collapseAll() { gernotbelger@9473: gernotbelger@9275: GWT.log("InfoListGrid - openAll"); gernotbelger@9473: gernotbelger@9275: setData(new ListGridRecord[] {}); gernotbelger@9275: for (final GaugeInfo gauge : this.gauges) { gernotbelger@9275: addCollapsedRecord(gauge); gernotbelger@9275: } gernotbelger@9275: } gernotbelger@9275: gernotbelger@9093: void getLocations(final String labelname, final List locations, final DataList dl) { gernotbelger@9093: for (int j = dl.size() - 1; j >= 0; --j) { gernotbelger@9093: final Data d = dl.get(j); gernotbelger@9093: final String label = d.getLabel(); bjoern@4956: if (label.equals(labelname)) { bjoern@4956: getLocationsFromData(locations, d); bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: gernotbelger@9093: void getLocationsFromData(final List locations, final Data data) { gernotbelger@9093: final DataItem[] items = data.getItems(); gernotbelger@9093: for (final DataItem item : items) { gernotbelger@9093: final String tmp = item.getStringValue(); bjoern@4956: GWT.log("GaugeListGrid - getLocationsFromData " + tmp); bjoern@4956: if (tmp != null) { bjoern@4956: if (tmp.contains(" ")) { bjoern@4956: // string contains several values ... gernotbelger@9270: final String[] values = StringArrayParseHelper.getArrayFromRawString(tmp); gernotbelger@9093: for (final String value2 : values) { gernotbelger@9093: final Double value = Double.valueOf(value2); bjoern@4956: if (value != null) { bjoern@4956: locations.add(value); bjoern@4956: } bjoern@4956: } gernotbelger@9093: } else { gernotbelger@9093: final Double value = Double.valueOf(tmp); bjoern@4956: if (value != null) { bjoern@4956: locations.add(value); bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: gernotbelger@9093: public void openOnReference(final Long number) { bjoern@4956: GWT.log("GaugeListGrid - openOnReference " + number); gernotbelger@9093: gernotbelger@9093: setData(new ListGridRecord[] {}); gernotbelger@9093: gernotbelger@9093: for (final GaugeInfo gauge : this.gauges) { gernotbelger@9093: gernotbelger@9093: if (gauge.getOfficialNumber().equals(number)) { gernotbelger@9093: this.addExpandedRecord(gauge);// (gauge); gernotbelger@9093: } else { gernotbelger@9093: this.addCollapsedRecord(gauge); bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: gernotbelger@9284: public void openOnDistance(final double start, final Double end, final DisappearType type) { bjoern@4956: GWT.log("GaugeListGrid - openOnDistance " + start + " " + end); bjoern@4956: gernotbelger@9093: setData(new ListGridRecord[] {}); gernotbelger@9093: gernotbelger@9473: double to = end == null ? Double.MAX_VALUE : end; gernotbelger@9284: gernotbelger@9473: final double from = Math.min(start, to); gernotbelger@9284: to = Math.max(start, to); gernotbelger@9473: gernotbelger@9093: for (final GaugeInfo gauge : this.gauges) { gernotbelger@9093: gernotbelger@9284: /* in earlier version, it was assumed that gaugeEnd may be null, but start not. */ gernotbelger@9284: final Double gaugeStart = gauge.getKmStart(); gernotbelger@9284: final Double gaugeEnd = gauge.getKmEnd() == null ? gaugeStart : gauge.getKmEnd(); gernotbelger@9473: gernotbelger@9284: boolean expand; gernotbelger@9473: if (gaugeStart == null) gernotbelger@9284: expand = false; gernotbelger@9284: else { gernotbelger@9473: gernotbelger@9284: final double gaugeFrom = Math.min(gaugeStart, gaugeEnd); gernotbelger@9284: final double gaugeTo = Math.max(gaugeStart, gaugeEnd); gernotbelger@9473: gernotbelger@9284: expand = (from >= gaugeFrom && from <= gaugeTo) || (to >= gaugeFrom && to <= gaugeTo) || (from <= gaugeFrom && to >= gaugeEnd); gernotbelger@9284: } gernotbelger@9284: gernotbelger@9473: if (expand) gernotbelger@9284: addExpandedRecord(gauge); gernotbelger@9284: else gernotbelger@9093: removeOrCollapse(gauge, type); bjoern@4956: } bjoern@4956: } bjoern@4956: gernotbelger@9093: private void removeOrCollapse(final GaugeInfo gauge, final DisappearType type) { gernotbelger@9093: switch (type) { gernotbelger@9093: case remove: gernotbelger@9093: // Remove: gauge wird der datasource nicht hinzugefügt gernotbelger@9093: break; gernotbelger@9093: case collapse: gernotbelger@9093: addCollapsedRecord(gauge); gernotbelger@9093: break; gernotbelger@9093: case stayVisible: // TODO: check gernotbelger@9093: addExpandedRecord(gauge); gernotbelger@9093: break; gernotbelger@9093: } gernotbelger@9093: gernotbelger@9093: } gernotbelger@9093: bjoern@4956: /** felix@4980: * Open Gauge entry if a location fits to the gauge. bjoern@4956: */ gernotbelger@9093: public void openOnLocations(final List locations) { bjoern@4956: GWT.log("GaugeListGrid - openOnLocations " + locations); bjoern@4956: gernotbelger@9093: setData(new ListGridRecord[] {}); gernotbelger@9093: bjoern@4956: if (locations == null || locations.isEmpty()) { bjoern@4956: return; bjoern@4956: } bjoern@4956: gernotbelger@9093: for (final GaugeInfo gauge : this.gauges) { bjoern@4956: boolean isset = false; gernotbelger@9093: for (final Double location : locations) { bjoern@4956: if (locations == null) { bjoern@4956: continue; bjoern@4956: } bjoern@4956: gernotbelger@9093: final Double start = gauge.getKmStart(); gernotbelger@9093: final Double end = gauge.getKmEnd(); bjoern@4956: if (start == null || end == null) { bjoern@4956: // should not occur but avoid NullPointerException bjoern@4956: continue; bjoern@4956: } bjoern@4956: bjoern@4956: if (location >= start && location <= end) { bjoern@4956: isset = true; bjoern@4956: break; bjoern@4956: } bjoern@4956: } bjoern@4956: if (isset) { gernotbelger@9093: addExpandedRecord(gauge); gernotbelger@9093: } else { gernotbelger@9093: addCollapsedRecord(gauge); bjoern@4956: } bjoern@4956: } bjoern@4956: } bjoern@4956: gernotbelger@9093: private void addExpandedRecord(final GaugeInfo gauge) { gernotbelger@9093: final GaugeRecord record = new GaugeRecord(gauge); gernotbelger@9093: gernotbelger@9093: this.addData(record); gernotbelger@9093: gernotbelger@9093: expandRecord(record); gernotbelger@9093: } gernotbelger@9093: gernotbelger@9093: private void addCollapsedRecord(final GaugeInfo gauge) { gernotbelger@9093: final GaugeRecord record = new GaugeRecord(gauge); gernotbelger@9093: gernotbelger@9093: this.addData(record); gernotbelger@9093: gernotbelger@9093: collapseRecord(record); gernotbelger@9093: } gernotbelger@9093: bjoern@4956: @Override gernotbelger@9093: protected Canvas getExpandPanel(final ListGridRecord record) { gernotbelger@9093: final GaugeRecord item = (GaugeRecord) record; gernotbelger@9093: return new GaugeInfoPanel(item, this.flys); bjoern@4956: } bjoern@4960: felix@6032: /** felix@6032: * When clicked on the gauge discharge link, open new Gauge Discharge felix@6032: * Curve view. felix@6032: */ bjoern@4960: @Override gernotbelger@9093: public void onRecordClick(final RecordClickEvent event) { gernotbelger@9093: final GaugeRecord gauge = (GaugeRecord) event.getRecord(); gernotbelger@9093: final Config config = Config.getInstance(); rrenkert@8303: final String locale = config.getLocale(); gernotbelger@9093: this.createCollectionService.create(locale, this.flys.getCurrentUser().identifier(), new AsyncCallback() { gernotbelger@9093: @Override gernotbelger@9093: public void onFailure(final Throwable caught) { gernotbelger@9093: GWT.log("Could not create the new collection."); gernotbelger@9093: SC.warn(FLYS.getExceptionString(GaugeListGrid.this.MSG, caught)); gernotbelger@9093: } gernotbelger@9093: gernotbelger@9093: @Override gernotbelger@9093: public void onSuccess(final Collection collection) { gernotbelger@9093: GWT.log("Successfully created a new collection."); gernotbelger@9093: createArtifact(collection, locale, gauge); gernotbelger@9093: } gernotbelger@9093: }); gernotbelger@9093: } gernotbelger@9093: gernotbelger@9093: private void createArtifact(final Collection collection, final String locale, final GaugeRecord gauge) { gernotbelger@9093: this.artifactService.create(locale, "gaugedischargecurve", null, new AsyncCallback() { gernotbelger@9093: @Override gernotbelger@9093: public void onFailure(final Throwable caught) { gernotbelger@9093: GWT.log("Could not create the new artifact."); gernotbelger@9093: SC.warn(FLYS.getExceptionString(GaugeListGrid.this.MSG, caught)); gernotbelger@9093: } gernotbelger@9093: gernotbelger@9093: @Override gernotbelger@9093: public void onSuccess(final Artifact artifact) { gernotbelger@9093: GWT.log("Successfully created a new artifact."); gernotbelger@9093: gernotbelger@9093: final DataItem riverItem = new DefaultDataItem("river", "river", gauge.getRiverName()); gernotbelger@9093: final Data river = new DefaultData("river", null, null, new DataItem[] { riverItem }); gernotbelger@9093: gernotbelger@9093: final DataItem refItem = new DefaultDataItem("reference_gauge", "reference_gauge", gauge.getOfficialNumber().toString()); gernotbelger@9093: final Data ref = new DefaultData("reference_gauge", null, null, new DataItem[] { refItem }); gernotbelger@9093: gernotbelger@9093: final DataItem locItem = new DefaultDataItem("ld_locations", "ld_locations", gauge.getStation().toString()); gernotbelger@9093: final Data loc = new DefaultData("ld_locations", null, null, new DataItem[] { locItem }); gernotbelger@9093: gernotbelger@9093: final DataItem nameItem = new DefaultDataItem("gauge_name", "gauge_name", gauge.getName()); gernotbelger@9093: final Data name = new DefaultData("gauge_name", null, null, new DataItem[] { nameItem }); gernotbelger@9093: gernotbelger@9093: final Data[] data = new Data[] { river, ref, loc, name }; gernotbelger@9093: GaugeListGrid.this.forwardService.go(locale, artifact, data, new AsyncCallback() { rrenkert@8303: @Override gernotbelger@9093: public void onFailure(final Throwable caught) { gernotbelger@9093: GWT.log("Could not feed the artifact."); gernotbelger@9093: SC.warn(caught.getMessage()); rrenkert@8303: } rrenkert@8303: rrenkert@8303: @Override gernotbelger@9093: public void onSuccess(final Artifact artifact) { gernotbelger@9093: GWT.log("Successfully feed the artifact."); gernotbelger@9093: final CollectionView view = new CollectionView(GaugeListGrid.this.flys, collection, artifact); gernotbelger@9093: GaugeListGrid.this.flys.getWorkspace().addView(collection.identifier(), view); gernotbelger@9093: view.addArtifactToCollection(artifact); rrenkert@8303: } gernotbelger@9093: }); gernotbelger@9093: } gernotbelger@9093: }); bjoern@4960: } bjoern@4961: bjoern@4961: @Override gernotbelger@9093: public String getCellCSSText(final ListGridRecord record, final int rowNum, final int colNum) { bjoern@4961: if (colNum == ABFLUSSTAFEL_COLUMN) { bjoern@4961: // display the ablfusstafel cell like a link gernotbelger@9093: return "text-decoration: underline; color: #0000EE; " + "cursor: pointer;"; gernotbelger@9093: } else { bjoern@4961: return super.getCellCSSText(record, rowNum, colNum); bjoern@4961: } bjoern@4961: } bjoern@4956: }