# HG changeset patch # User gernotbelger # Date 1531214652 -7200 # Node ID 972e10522ed6e8d5492a176dbe28d1cd95bedb43 # Parent b515ed950d39bab690393c1bcc21dd41ba02c313 salix.supraregional ui diff -r b515ed950d39 -r 972e10522ed6 artifacts/doc/conf/artifacts/uinfo.xml --- a/artifacts/doc/conf/artifacts/uinfo.xml Fri Jul 06 17:56:18 2018 +0200 +++ b/artifacts/doc/conf/artifacts/uinfo.xml Tue Jul 10 11:24:12 2018 +0200 @@ -78,6 +78,18 @@ + + + + + + + + + + + + @@ -85,7 +97,9 @@ - + + + @@ -343,7 +357,7 @@ - + diff -r b515ed950d39 -r 972e10522ed6 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixZone.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixZone.java Tue Jul 10 11:24:12 2018 +0200 @@ -0,0 +1,154 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.artifacts.uinfo.salix; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; + +/** + * @author Domenico Nardi Tironi + * + */ +public class SalixZone implements Comparable { + + // IMMER ABGLEICHEN Server Client SalixZone.java + private static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR"; + private static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR"; + private final int dwsplValue; + private final double fromKm; + private final double toKm; + + private final static double DELTA = 0.0001; + + public static List parse(final String zonesRaw) { + final List resultList = new ArrayList<>(); + + final List results = new ArrayList<>(); + if (zonesRaw.contains(TABLE_ROW_SEPARATOR)) { + final String[] rows = zonesRaw.split(TABLE_ROW_SEPARATOR); + for (final String row : rows) { + if (row.contains(TABLE_CELL_SEPARATOR)) { + final String[] result = row.split(TABLE_CELL_SEPARATOR); + results.add(result); + } + } + } + for (final String[] zone : results) { + final SalixZone helper = new SalixZone(Integer.valueOf(zone[0]), Double.valueOf(zone[1]), Double.valueOf(zone[2])); + resultList.add(helper); + } + return resultList; + } + + public static SalixZone createFromTableEntry(final String dwspl, final String from, final String to) { + return new SalixZone(Integer.valueOf(dwspl), Double.valueOf(from), Double.valueOf(to)); // Error-Handling? + } + + private SalixZone(final int dwsplValue, final double fromKm, final double toKm) { + this.dwsplValue = dwsplValue; + this.fromKm = fromKm; + this.toKm = toKm; + } + + public Double getToKm() { + return this.toKm; + } + + public int getDwsplValue() { + return this.dwsplValue; + } + + public Double getFromKm() { + return this.fromKm; + } + + public static final String parseListToDataString(final List list) { + + java.util.Collections.sort(list); + final StringBuilder builder = new StringBuilder(); + for (final SalixZone zone : list) { + builder.append(zone.getDwsplValue()); + builder.append(TABLE_CELL_SEPARATOR); + builder.append(zone.getFromKm()); + builder.append(TABLE_CELL_SEPARATOR); + builder.append(zone.getToKm()); + builder.append(TABLE_ROW_SEPARATOR); + } + return builder.toString(); + } + + public static final boolean zonesAreOverlapping(final List list) { + for (final SalixZone zone : list) { + for (final SalixZone zoneOther : list) { + if (zone != zoneOther) { + final boolean overlaps = zone.overlaps(zoneOther); + if (overlaps) { + return overlaps; // cancel. only one zone has to overlap + } + } + } + } + + return false; + } + + public static final boolean hasGaps(final List list, final double lower, final double upper) { + + if (((upper - lower) > DELTA) && list.size() == 0) + return true; + + final TreeSet treeList = new TreeSet(); + treeList.addAll(list); + double lowerCompare = lower + DELTA; + for (final SalixZone zone : treeList) { + if (zone.getLowerFromTo() > lowerCompare) { + return true; + } + lowerCompare = zone.getUpperFromTo() + DELTA; + } + if ((lowerCompare + DELTA) < upper) + return true; // am Ende nicht geschlossen + + return false; + } + + private Double getLowerFromTo() { + return this.fromKm < this.toKm ? this.fromKm : this.toKm; // Math. is forbidden :-( + } + + private Double getUpperFromTo() { + return this.fromKm > this.toKm ? this.fromKm : this.toKm;// Math. is forbidden :-( + } + + private boolean overlaps(final SalixZone otherZone) { + final double otherLower = otherZone.getLowerFromTo(); + final double otherUpper = otherZone.getUpperFromTo(); + + final double upper = getUpperFromTo() - DELTA; + final double lower = getLowerFromTo() + DELTA; + final double otherSchwerpunkt = (otherLower + otherUpper) / 2; + if ((otherUpper < upper && otherUpper > lower)) { + return true; + } else if (otherLower > lower && otherLower < upper) { + return true; + } else if (otherSchwerpunkt > lower && otherSchwerpunkt < upper) { + return true; + } + return false; + } + + @Override + public int compareTo(final SalixZone o) { + final int basicCompare = this.getLowerFromTo().compareTo(o.getLowerFromTo()); + return basicCompare; + } + +} \ No newline at end of file diff -r b515ed950d39 -r 972e10522ed6 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SupraRegionalTableState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SupraRegionalTableState.java Tue Jul 10 11:24:12 2018 +0200 @@ -0,0 +1,54 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.artifacts.uinfo.salix; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.D4EArtifact; +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.states.DefaultState; +import org.w3c.dom.Element; + +/** + * @author Domenico Nardi Tironi + */ +public class SupraRegionalTableState extends DefaultState { + + private static final long serialVersionUID = 1L; + + @Override + protected String getUIProvider() { + return "uinfo.salix.supraregional.table"; + } + + @Override + protected Element[] createItems(final ElementCreator cr, final Artifact artifact, final String name, final CallContext context) { + final String datakey = "supraregional_table"; + if (name.equals(datakey)) { + + final D4EArtifact flys = (D4EArtifact) artifact; + final String s = flys.getDataAsString(datakey); + + final RangeAccess ra = new RangeAccess((D4EArtifact) artifact); + + final Element item = createItem(cr, new String[] { "salix_zones", s }); + final Element min = createItem(cr, new String[] { "salix_zones_min", new Double(ra.getFrom()).toString() }); + + final Element max = createItem(cr, new String[] { "salix_zones_max", new Double(ra.getTo()).toString() }); + + return new Element[] { min, max, item }; + + } + + return new Element[] {}; + } + +} \ No newline at end of file diff -r b515ed950d39 -r 972e10522ed6 artifacts/src/main/resources/messages.properties --- a/artifacts/src/main/resources/messages.properties Fri Jul 06 17:56:18 2018 +0200 +++ b/artifacts/src/main/resources/messages.properties Tue Jul 10 11:24:12 2018 +0200 @@ -76,6 +76,7 @@ state.minfo.m3_per_a = m\u00b3/a state.uinfo.vegetation_zones.table = Einteilung der Vegetationszonen und \u00dcberflutungsdauern (\u00dcFD) +state.uinfo.salix.supraregional = \u00dcberregional wirkende Eingriffe state.uinfo.year_totalepoch = Year/Gesamter Zeitraum state.uinfo.year_epoch = Year/Epoch diff -r b515ed950d39 -r 972e10522ed6 artifacts/src/main/resources/messages_de.properties --- a/artifacts/src/main/resources/messages_de.properties Fri Jul 06 17:56:18 2018 +0200 +++ b/artifacts/src/main/resources/messages_de.properties Tue Jul 10 11:24:12 2018 +0200 @@ -76,6 +76,7 @@ state.minfo.m3_per_a = m\u00b3/a state.uinfo.vegetation_zones.table = Einteilung der Vegetationszonen und \u00dcberflutungsdauern (\u00dcFD) +state.uinfo.salix.supraregional = \u00dcberregional wirkende Eingriffe state.uinfo.year_totalepoch = Jahr/Gesamter Zeitraum state.uinfo.year_epoch = Jahr/Epoche diff -r b515ed950d39 -r 972e10522ed6 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Fri Jul 06 17:56:18 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Tue Jul 10 11:24:12 2018 +0200 @@ -1556,4 +1556,14 @@ String sinfo_sounding_waterlevel_select_waterlevel(); String sinfo_deactivate_intelligent_datacord(); + + String uinfo_salix_dmwspl_short(); + + String uinfo_salix_invalid_double(); + + String uinfo_salix_km_limit_exceed(); + + String uinfo_salix_km_overlap(); + + String uinfo_salix_km_has_gaps(); } \ No newline at end of file diff -r b515ed950d39 -r 972e10522ed6 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Fri Jul 06 17:56:18 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Tue Jul 10 11:24:12 2018 +0200 @@ -817,6 +817,7 @@ sinfo_flood_height = H\u00f6he Infrastruktur BWaStr uinfo = U-INFO +uinfo_salix_dmwspl_short = \u0394MW [cm] uinfo_inundation_duration_export = \u00dcberflutungsdauern Export uinfo_salix_line_export = Salix-Linie Export uinfo_vegetation_zones_export = Vegetationszonen Export @@ -829,6 +830,10 @@ uinfo_vegetation_zones_validation_range = Werte m\u00fcssen zwischen 0 und 365 liegen. uinfo_vegetation_zones_validation_from_greater_to = Der Wert f\u00fcr "\u00dcfd von" muss kleiner als "\u00dcfd bis". uinfo_vegetation_zones_invalid_integer = Nur Ganzzahlen erlaubt. +uinfo_salix_invalid_double = Nur Zahlen erlaubt. +uinfo_salix_km_limit_exceed = Die Zahl ist au\u00dferhalb des g\u00fcltigen km-Bereichs. +uinfo_salix_km_overlap = Km-Bereiche \u00fcperlappen. +uinfo_salix_km_has_gaps = Der Km-Bereich ist nicht vollst. belegt. bundu = Betrieb und Unterhaltung diff -r b515ed950d39 -r 972e10522ed6 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Fri Jul 06 17:56:18 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Tue Jul 10 11:24:12 2018 +0200 @@ -817,6 +817,7 @@ sinfo_flood_height = H\u00f6he Infrastruktur BWaStr uinfo = U-INFO +uinfo_salix_dmwspl_short = \u0394MW [cm] uinfo_inundation_duration_export = \u00dcberflutungsdauern Export uinfo_salix_line_export = Salix-Linie Export uinfo_vegetation_zones_export = Vegetationszonen Export @@ -829,6 +830,10 @@ uinfo_vegetation_zones_validation_range = Werte m\u00fcssen zwischen 0 und 365 liegen. uinfo_vegetation_zones_validation_from_greater_to = Der Wert f\u00fcr "\u00dcfd von" muss kleiner als "\u00dcfd bis". uinfo_vegetation_zones_invalid_integer = Nur Ganzzahlen erlaubt. +uinfo_salix_invalid_double = Nur Zahlen erlaubt. +uinfo_salix_km_limit_exceed = Die Zahl ist au\u00dferhalb des g\u00fcltigen km-Bereichs. +uinfo_salix_km_overlap = Km-Bereiche \u00fcperlappen. +uinfo_salix_km_has_gaps = Der Km-Bereich ist nicht vollst. belegt. bundu = Betrieb und Unterhaltung diff -r b515ed950d39 -r 972e10522ed6 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java Fri Jul 06 17:56:18 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java Tue Jul 10 11:24:12 2018 +0200 @@ -331,5 +331,11 @@ * @return the selected data. */ protected abstract Data[] getData(); + + protected String getRiverName() { + final ArtifactDescription adescr = this.artifact.getArtifactDescription(); + return adescr.getRiver(); + } + } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r b515ed950d39 -r 972e10522ed6 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanel.java Fri Jul 06 17:56:18 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanel.java Tue Jul 10 11:24:12 2018 +0200 @@ -9,18 +9,9 @@ package org.dive4elements.river.client.client.ui; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import org.dive4elements.river.client.client.Config; import org.dive4elements.river.client.client.FLYSConstants; -import org.dive4elements.river.client.client.event.FilterHandler; -import org.dive4elements.river.client.client.event.RangeFilterEvent; -import org.dive4elements.river.client.client.event.StringFilterEvent; -import org.dive4elements.river.client.client.ui.range.DistanceInfoDataSource; -import org.dive4elements.river.client.client.ui.range.LocationsTable; -import org.dive4elements.river.client.client.ui.range.RangeTable; -import org.dive4elements.river.client.shared.model.ArtifactDescription; import org.dive4elements.river.client.shared.model.Data; import org.dive4elements.river.client.shared.model.DataItem; import org.dive4elements.river.client.shared.model.DataList; @@ -29,34 +20,22 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.i18n.client.NumberFormat; -import com.smartgwt.client.data.AdvancedCriteria; -import com.smartgwt.client.data.Criteria; -import com.smartgwt.client.data.Criterion; import com.smartgwt.client.data.Record; -import com.smartgwt.client.types.Alignment; -import com.smartgwt.client.types.OperatorId; import com.smartgwt.client.util.SC; import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.Label; -import com.smartgwt.client.widgets.form.DynamicForm; -import com.smartgwt.client.widgets.form.fields.SelectItem; import com.smartgwt.client.widgets.form.fields.StaticTextItem; import com.smartgwt.client.widgets.form.fields.events.BlurEvent; import com.smartgwt.client.widgets.form.fields.events.BlurHandler; -import com.smartgwt.client.widgets.form.fields.events.ChangedEvent; -import com.smartgwt.client.widgets.form.fields.events.ChangedHandler; import com.smartgwt.client.widgets.grid.ListGrid; import com.smartgwt.client.widgets.grid.events.RecordClickEvent; import com.smartgwt.client.widgets.grid.events.RecordClickHandler; 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; -import com.smartgwt.client.widgets.tab.events.TabSelectedEvent; -import com.smartgwt.client.widgets.tab.events.TabSelectedHandler; /** Panel to allow input of distance for calculation range. */ -public class DistancePanel extends AbstractUIProvider implements BlurHandler, FilterHandler { +public class DistancePanel extends AbstractUIProvider implements BlurHandler { private static final long serialVersionUID = -883142387908664588L; @@ -68,8 +47,8 @@ protected FLYSConstants MSG = GWT.create(FLYSConstants.class); - protected RangeTable distancesTable; - protected LocationsTable locationsTable; + // protected RangeTable distancesTable; + // protected LocationsTable locationsTable; protected DoubleRangePanel distancePanel; @@ -299,11 +278,6 @@ return new DefaultData(field, null, null, new DataItem[] { item }); } - @Override - public void onBlur(final BlurEvent event) { - this.distancePanel.validateForm(); - } - protected void initMinMaxValues(final DataList data) { final Data f = getData(data.getAll(), getLowerField()); final Data t = getData(data.getAll(), getUpperField()); @@ -393,19 +367,10 @@ } protected void initHelperPanel() { - this.distancesTable = new RangeTable(); - this.locationsTable = new LocationsTable(); - final Config config = Config.getInstance(); - final String url = config.getServerUrl(); - final String river = getRiverName(); + final DistancePanelInputHelper helper = new DistancePanelInputHelper(this.MSG, this.helperContainer, this.getRiverName()); - this.distancesTable.setAutoFetchData(true); - this.locationsTable.setAutoFetchData(true); - this.distancesTable.setDataSource(new DistanceInfoDataSource(url, river, "distances")); - this.locationsTable.setDataSource(new DistanceInfoDataSource(url, river, "locations")); - - this.distancesTable.addRecordClickHandler(new RecordClickHandler() { + helper.getDistancesTable().addRecordClickHandler(new RecordClickHandler() { @Override public void onRecordClick(final RecordClickEvent e) { final Record r = e.getRecord(); @@ -423,7 +388,7 @@ } }); - this.locationsTable.addRecordClickHandler(new RecordClickHandler() { + helper.getLocationsTable().addRecordClickHandler(new RecordClickHandler() { @Override public void onRecordClick(final RecordClickEvent e) { final Record r = e.getRecord(); @@ -447,151 +412,11 @@ } }); - this.tabs = new TabSet(); - this.tabs.setWidth100(); - this.tabs.setHeight100(); - - final Tab locations = new Tab(this.MSG.locations()); - final Tab distances = new Tab(this.MSG.distance()); - - locations.setPane(this.locationsTable); - distances.setPane(this.distancesTable); - - this.tabs.addTab(locations, 0); - this.tabs.addTab(distances, 1); - - this.filterResultCount = new StaticTextItem(this.MSG.resultCount()); - this.filterResultCount.setTitleAlign(Alignment.LEFT); - this.filterResultCount.setTitleStyle("color: #000"); - - this.filterDescription = new TableFilter(); - this.filterDescription.setHeight("30px"); - this.filterDescription.addFilterHandler(this); - - this.filterRange = new RangeTableFilter(); - this.filterRange.setHeight("30px"); - this.filterRange.addFilterHandler(this); - this.filterRange.setVisible(false); - - final SelectItem filterCriteria = new SelectItem(); - filterCriteria.setShowTitle(false); - filterCriteria.setWidth(100); - filterCriteria.addChangedHandler(new ChangedHandler() { - @Override - public void onChanged(final ChangedEvent e) { - if (e.getValue().toString().equals("range")) { - DistancePanel.this.filterRange.setVisible(true); - DistancePanel.this.filterDescription.setVisible(false); - DistancePanel.this.filterDescription.clear(); - } else { - DistancePanel.this.filterRange.setVisible(false); - DistancePanel.this.filterRange.clear(); - DistancePanel.this.filterDescription.setVisible(true); - } - } - }); - - final LinkedHashMap filterMap = new LinkedHashMap(); - filterMap.put("description", this.MSG.description()); - filterMap.put("range", this.MSG.range()); - filterCriteria.setValueMap(filterMap); - filterCriteria.setValue("description"); - - final DynamicForm form = new DynamicForm(); - form.setFields(filterCriteria); - - final DynamicForm form2 = new DynamicForm(); - form2.setFields(this.filterResultCount); - - final HLayout filterLayout = new HLayout(); - filterLayout.addMember(form); - filterLayout.addMember(this.filterDescription); - filterLayout.addMember(this.filterRange); - filterLayout.setHeight(30); - this.tabs.addTabSelectedHandler(new TabSelectedHandler() { - @Override - public void onTabSelected(final TabSelectedEvent evt) { - DistancePanel.this.filterDescription.clear(); - DistancePanel.this.filterRange.clear(); - DistancePanel.this.filterResultCount.setValue(""); - - final Canvas c = evt.getTabPane(); - if (c instanceof ListGrid) { - DistancePanel.this.currentFiltered = (ListGrid) c; - } - } - }); - - this.helperContainer.addMember(this.tabs); - this.helperContainer.addMember(filterLayout); - this.helperContainer.addMember(form2); } @Override - public void onFilterCriteriaChanged(final StringFilterEvent event) { - final String search = event.getFilter(); - - if (search != null && search.length() > 0) { - final Criteria c = new Criteria("description", search); - this.locationsTable.filterData(c); - this.distancesTable.filterData(c); - this.filterResultCount.setValue(this.currentFiltered.getRecords().length); - } else { - this.locationsTable.clearCriteria(); - this.distancesTable.clearCriteria(); - this.filterResultCount.setValue(""); - } - } - - @Override - public void onFilterCriteriaChanged(final RangeFilterEvent event) { - final Float from = event.getFrom() - 0.001f; - final Float to = event.getTo() + 0.001f; - - Criterion combinedFilter = null; - Criterion locationFilter = null; - - if (from.equals(Float.NaN) && to.equals(Float.NaN)) { - this.locationsTable.clearCriteria(); - this.distancesTable.clearCriteria(); - this.filterResultCount.setValue(""); - return; - } - - if (from.equals(Float.NaN)) { - combinedFilter = new Criterion("to", OperatorId.LESS_OR_EQUAL, to); - - locationFilter = new Criterion("from", OperatorId.LESS_OR_EQUAL, to); - - this.locationsTable.filterData(locationFilter); - this.distancesTable.filterData(combinedFilter); - this.filterResultCount.setValue(this.currentFiltered.getRecords().length); - return; - } - - if (to.equals(Float.NaN)) { - combinedFilter = new Criterion("from", OperatorId.GREATER_OR_EQUAL, from); - } else { - final AdvancedCriteria c1 = new AdvancedCriteria(OperatorId.AND, - new Criterion[] { new Criterion("from", OperatorId.GREATER_OR_EQUAL, from), new Criterion("from", OperatorId.LESS_OR_EQUAL, to) }); - - final AdvancedCriteria c2 = new AdvancedCriteria(OperatorId.AND, - new Criterion[] { new Criterion("to", OperatorId.GREATER_OR_EQUAL, from), new Criterion("to", OperatorId.LESS_OR_EQUAL, to) }); - - final AdvancedCriteria c3 = new AdvancedCriteria(OperatorId.AND, - new Criterion[] { new Criterion("from", OperatorId.LESS_OR_EQUAL, to), new Criterion("to", OperatorId.GREATER_OR_EQUAL, from) }); - - combinedFilter = new AdvancedCriteria(OperatorId.OR, new Criterion[] { c1, c2, c3 }); - } - this.locationsTable.filterData(combinedFilter); - this.distancesTable.filterData(combinedFilter); - this.filterResultCount.setValue(this.currentFiltered.getRecords().length); - - } - - protected String getRiverName() { - final ArtifactDescription adescr = this.artifact.getArtifactDescription(); - return adescr.getRiver(); + public void onBlur(final BlurEvent event) { + this.distancePanel.validateForm(); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r b515ed950d39 -r 972e10522ed6 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanelInputHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanelInputHelper.java Tue Jul 10 11:24:12 2018 +0200 @@ -0,0 +1,229 @@ +/* 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; + +import java.util.LinkedHashMap; + +import org.dive4elements.river.client.client.Config; +import org.dive4elements.river.client.client.FLYSConstants; +import org.dive4elements.river.client.client.event.FilterHandler; +import org.dive4elements.river.client.client.event.RangeFilterEvent; +import org.dive4elements.river.client.client.event.StringFilterEvent; +import org.dive4elements.river.client.client.ui.range.DistanceInfoDataSource; +import org.dive4elements.river.client.client.ui.range.LocationsTable; +import org.dive4elements.river.client.client.ui.range.RangeTable; + +import com.smartgwt.client.data.AdvancedCriteria; +import com.smartgwt.client.data.Criteria; +import com.smartgwt.client.data.Criterion; +import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.types.OperatorId; +import com.smartgwt.client.widgets.Canvas; +import com.smartgwt.client.widgets.form.DynamicForm; +import com.smartgwt.client.widgets.form.fields.SelectItem; +import com.smartgwt.client.widgets.form.fields.StaticTextItem; +import com.smartgwt.client.widgets.form.fields.events.ChangedEvent; +import com.smartgwt.client.widgets.form.fields.events.ChangedHandler; +import com.smartgwt.client.widgets.grid.ListGrid; +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; +import com.smartgwt.client.widgets.tab.events.TabSelectedEvent; +import com.smartgwt.client.widgets.tab.events.TabSelectedHandler; + +/** Panel to allow input of distance for calculation range. */ +public class DistancePanelInputHelper implements FilterHandler { + + private RangeTable distancesTable; + private LocationsTable locationsTable; + private TabSet tabs; + private StaticTextItem filterResultCount; + private TableFilter filterDescription; + private RangeTableFilter filterRange; + private ListGrid currentFiltered; + protected final VLayout helperContainer; + private final FLYSConstants MSG; + private final String river; + + public DistancePanelInputHelper(final FLYSConstants MSG, final VLayout helperContainer, final String river) { + this.MSG = MSG; + this.helperContainer = helperContainer; + this.river = river; + + initHelperPanel(); // copy from DistancePanel + } + + protected void initHelperPanel() { + this.distancesTable = new RangeTable(); + this.locationsTable = new LocationsTable(); + + final Config config = Config.getInstance(); + final String url = config.getServerUrl(); + // final String river = getRiverName(); + + this.distancesTable.setAutoFetchData(true); + this.locationsTable.setAutoFetchData(true); + this.distancesTable.setDataSource(new DistanceInfoDataSource(url, this.river, "distances")); + this.locationsTable.setDataSource(new DistanceInfoDataSource(url, this.river, "locations")); + + // recordClickHandlers were here + + this.tabs = new TabSet(); + this.tabs.setWidth100(); + this.tabs.setHeight100(); + + final Tab locations = new Tab(this.MSG.locations()); + final Tab distances = new Tab(this.MSG.distance()); + + locations.setPane(this.locationsTable); + distances.setPane(this.distancesTable); + + this.tabs.addTab(locations, 0); + this.tabs.addTab(distances, 1); + + this.filterResultCount = new StaticTextItem(this.MSG.resultCount()); + this.filterResultCount.setTitleAlign(Alignment.LEFT); + this.filterResultCount.setTitleStyle("color: #000"); + + this.filterDescription = new TableFilter(); + this.filterDescription.setHeight("30px"); + this.filterDescription.addFilterHandler(this); + + this.filterRange = new RangeTableFilter(); + this.filterRange.setHeight("30px"); + this.filterRange.addFilterHandler(this); + this.filterRange.setVisible(false); + + final SelectItem filterCriteria = new SelectItem(); + filterCriteria.setShowTitle(false); + filterCriteria.setWidth(100); + filterCriteria.addChangedHandler(new ChangedHandler() { + @Override + public void onChanged(final ChangedEvent e) { + if (e.getValue().toString().equals("range")) { + DistancePanelInputHelper.this.filterRange.setVisible(true); + DistancePanelInputHelper.this.filterDescription.setVisible(false); + DistancePanelInputHelper.this.filterDescription.clear(); + } else { + DistancePanelInputHelper.this.filterRange.setVisible(false); + DistancePanelInputHelper.this.filterRange.clear(); + DistancePanelInputHelper.this.filterDescription.setVisible(true); + } + } + }); + + final LinkedHashMap filterMap = new LinkedHashMap(); + filterMap.put("description", this.MSG.description()); + filterMap.put("range", this.MSG.range()); + filterCriteria.setValueMap(filterMap); + filterCriteria.setValue("description"); + + final DynamicForm form = new DynamicForm(); + form.setFields(filterCriteria); + + final DynamicForm form2 = new DynamicForm(); + form2.setFields(this.filterResultCount); + + final HLayout filterLayout = new HLayout(); + filterLayout.addMember(form); + filterLayout.addMember(this.filterDescription); + filterLayout.addMember(this.filterRange); + filterLayout.setHeight(30); + this.tabs.addTabSelectedHandler(new TabSelectedHandler() { + @Override + public void onTabSelected(final TabSelectedEvent evt) { + DistancePanelInputHelper.this.filterDescription.clear(); + DistancePanelInputHelper.this.filterRange.clear(); + DistancePanelInputHelper.this.filterResultCount.setValue(""); + + final Canvas c = evt.getTabPane(); + if (c instanceof ListGrid) { + DistancePanelInputHelper.this.currentFiltered = (ListGrid) c; + } + } + }); + + this.helperContainer.addMember(this.tabs); + this.helperContainer.addMember(filterLayout); + this.helperContainer.addMember(form2); + } + + @Override + public void onFilterCriteriaChanged(final StringFilterEvent event) { + final String search = event.getFilter(); + + if (search != null && search.length() > 0) { + final Criteria c = new Criteria("description", search); + this.locationsTable.filterData(c); + this.distancesTable.filterData(c); + this.filterResultCount.setValue(this.currentFiltered.getRecords().length); + } else { + this.locationsTable.clearCriteria(); + this.distancesTable.clearCriteria(); + this.filterResultCount.setValue(""); + } + } + + @Override + public void onFilterCriteriaChanged(final RangeFilterEvent event) { + final Float from = event.getFrom() - 0.001f; + final Float to = event.getTo() + 0.001f; + + Criterion combinedFilter = null; + Criterion locationFilter = null; + + if (from.equals(Float.NaN) && to.equals(Float.NaN)) { + this.locationsTable.clearCriteria(); + this.distancesTable.clearCriteria(); + this.filterResultCount.setValue(""); + return; + } + + if (from.equals(Float.NaN)) { + combinedFilter = new Criterion("to", OperatorId.LESS_OR_EQUAL, to); + + locationFilter = new Criterion("from", OperatorId.LESS_OR_EQUAL, to); + + this.locationsTable.filterData(locationFilter); + this.distancesTable.filterData(combinedFilter); + this.filterResultCount.setValue(this.currentFiltered.getRecords().length); + return; + } + + if (to.equals(Float.NaN)) { + combinedFilter = new Criterion("from", OperatorId.GREATER_OR_EQUAL, from); + } else { + final AdvancedCriteria c1 = new AdvancedCriteria(OperatorId.AND, + new Criterion[] { new Criterion("from", OperatorId.GREATER_OR_EQUAL, from), new Criterion("from", OperatorId.LESS_OR_EQUAL, to) }); + + final AdvancedCriteria c2 = new AdvancedCriteria(OperatorId.AND, + new Criterion[] { new Criterion("to", OperatorId.GREATER_OR_EQUAL, from), new Criterion("to", OperatorId.LESS_OR_EQUAL, to) }); + + final AdvancedCriteria c3 = new AdvancedCriteria(OperatorId.AND, + new Criterion[] { new Criterion("from", OperatorId.LESS_OR_EQUAL, to), new Criterion("to", OperatorId.GREATER_OR_EQUAL, from) }); + + combinedFilter = new AdvancedCriteria(OperatorId.OR, new Criterion[] { c1, c2, c3 }); + } + this.locationsTable.filterData(combinedFilter); + this.distancesTable.filterData(combinedFilter); + this.filterResultCount.setValue(this.currentFiltered.getRecords().length); + + } + + public ListGrid getDistancesTable() { + return this.distancesTable; + } + + public ListGrid getLocationsTable() { + return this.locationsTable; + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r b515ed950d39 -r 972e10522ed6 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/PanelHelper.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/PanelHelper.java Fri Jul 06 17:56:18 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/PanelHelper.java Tue Jul 10 11:24:12 2018 +0200 @@ -9,10 +9,18 @@ */ package org.dive4elements.river.client.client.ui; +import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.types.ListGridFieldType; import com.smartgwt.client.widgets.form.fields.IntegerItem; import com.smartgwt.client.widgets.form.fields.TextItem; +import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator; import com.smartgwt.client.widgets.form.validator.IsIntegerValidator; import com.smartgwt.client.widgets.form.validator.Validator; +import com.smartgwt.client.widgets.grid.ListGrid; +import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.widgets.grid.SortNormalizer; +import com.smartgwt.client.widgets.grid.events.RecordClickEvent; +import com.smartgwt.client.widgets.grid.events.RecordClickHandler; import com.smartgwt.client.widgets.layout.VLayout; /** @@ -63,4 +71,48 @@ return inputItem; } + + public static final ListGridField createRemoveField(final ListGrid table, final String icon) { + final ListGridField removeField = new ListGridField("_removeRecord", "Remove Record") { + { + setType(ListGridFieldType.ICON); + setIcon(icon); + setCanEdit(false); + setCanFilter(false); + setCanSort(false); + setCanGroupBy(false); + setCanFreeze(false); + setWidth(25); + setCanDragResize(false); + super.setCanToggle(false); + } + }; + table.addRecordClickHandler(new RecordClickHandler() { + @Override + public void onRecordClick(final RecordClickEvent event) { + // Just handle remove-clicks + if (!event.getField().getName().equals(removeField.getName())) { + return; + } + event.getViewer().removeData(event.getRecord()); + } + }); + + return removeField; + } + + public static final ListGridField createIntTableField(final String key, final String msg, final boolean canSort, final SortNormalizer normalizer, + final IntegerRangeValidator validators) { + final ListGridField intField = new ListGridField(key, msg); + intField.setType(ListGridFieldType.INTEGER); + intField.setValidators(validators); + intField.setWidth(90); + intField.setAlign(Alignment.RIGHT); + intField.setSortNormalizer(normalizer); + intField.setCanSort(canSort); + intField.setCanDragResize(false); + + return intField; + } + } diff -r b515ed950d39 -r 972e10522ed6 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java Fri Jul 06 17:56:18 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java Tue Jul 10 11:24:12 2018 +0200 @@ -32,6 +32,7 @@ import org.dive4elements.river.client.client.ui.uinfo.LoadSedimentHeightPanel; import org.dive4elements.river.client.client.ui.uinfo.LoadSingleEpochSelect; import org.dive4elements.river.client.client.ui.uinfo.LoadSingleYearPanel; +import org.dive4elements.river.client.client.ui.uinfo.SupraRegionalTablePanel; import org.dive4elements.river.client.client.ui.uinfo.VegetationzonesTableEditPanel; import org.dive4elements.river.client.client.ui.uinfo.VegetationzonesTablePanel; import org.dive4elements.river.client.shared.model.User; @@ -179,6 +180,8 @@ return new UserRGDProvider(); } else if (uiProvider.equals("static_sqrelation")) { return new StaticDataPanel(); + } else if (uiProvider.equals("uinfo.salix.supraregional.table")) { + return new SupraRegionalTablePanel(); } if ("sinfo_flowdepth_twin_panel".equals(uiProvider)) diff -r b515ed950d39 -r 972e10522ed6 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/SupraRegionalTablePanel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/SupraRegionalTablePanel.java Tue Jul 10 11:24:12 2018 +0200 @@ -0,0 +1,412 @@ +/* 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.uinfo; + +import java.util.ArrayList; +import java.util.List; + +import org.dive4elements.river.client.client.ui.AbstractUIProvider; +import org.dive4elements.river.client.client.ui.DistancePanelInputHelper; +import org.dive4elements.river.client.client.ui.PanelHelper; +import org.dive4elements.river.client.shared.model.Data; +import org.dive4elements.river.client.shared.model.DataItem; +import org.dive4elements.river.client.shared.model.DataList; +import org.dive4elements.river.client.shared.model.DefaultData; +import org.dive4elements.river.client.shared.model.DefaultDataItem; +import org.dive4elements.river.client.shared.model.SalixZone; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.i18n.client.NumberFormat; +import com.google.gwt.user.client.ui.Label; +import com.smartgwt.client.data.Record; +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.events.ClickEvent; +import com.smartgwt.client.widgets.events.ClickHandler; +import com.smartgwt.client.widgets.form.DynamicForm; +import com.smartgwt.client.widgets.form.fields.TextItem; +import com.smartgwt.client.widgets.grid.CellEditValueFormatter; +import com.smartgwt.client.widgets.grid.CellFormatter; +import com.smartgwt.client.widgets.grid.ListGrid; +import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.widgets.grid.ListGridRecord; +import com.smartgwt.client.widgets.grid.events.CellSavedEvent; +import com.smartgwt.client.widgets.grid.events.CellSavedHandler; +import com.smartgwt.client.widgets.grid.events.RecordClickEvent; +import com.smartgwt.client.widgets.grid.events.RecordClickHandler; +import com.smartgwt.client.widgets.layout.HLayout; +import com.smartgwt.client.widgets.layout.Layout; +import com.smartgwt.client.widgets.layout.VLayout; + +public class SupraRegionalTablePanel extends AbstractUIProvider { + private static final long serialVersionUID = 1L; + + private Double minKm, maxKm = -1.; + // private String tableData = ""; + private ListGrid table; + private final String datakey = "supraregional_table"; + final Label validationLabel = new Label(); + + private final NumberFormat format = NumberFormat.getDecimalFormat(); + + @Override + public Canvas createOld(final DataList dataList) { + final HLayout layout = new HLayout(); + layout.setWidth("400px"); + final VLayout vLayout = new VLayout(); + vLayout.setWidth(130); + final Label label = new Label(dataList.getLabel()); + label.setWidth("200px"); + label.setHeight("25px"); + + final List items = dataList.getAll(); + final Data str = getData(items, this.datakey); + final DataItem[] strItems = str.getItems(); + + final List entries = SalixZone.parse(strItems[0].getLabel()); + + for (final SalixZone entry : entries) { + final Label dateLabel = new Label( + entry.getDwsplValue() + " (" + this.format.format(entry.getFromKm()) + "-" + this.format.format(entry.getToKm()) + " km)"); + dateLabel.setHeight("20px"); + vLayout.addMember(dateLabel); + } + final Canvas back = getBackButton(dataList.getState()); + layout.addMember(label); + layout.addMember(vLayout); + layout.addMember(back); + + return layout; + } + + @Override + public Canvas create(final DataList data) { + + final Data dataItem = data.getAll().get(0); + String tableData = ""; + for (final DataItem item : dataItem.getItems()) { + final String label = item.getLabel(); + if (label.equals("salix_zones_min")) + this.minKm = Double.valueOf(item.getStringValue()); + else if (label.equals("salix_zones_max")) + this.maxKm = Double.valueOf(item.getStringValue()); + else if (label.equals("salix_zones")) + tableData = item.getStringValue(); + } + + if (this.minKm > this.maxKm) { + final double temp = this.minKm; + this.minKm = this.maxKm; + this.maxKm = temp; + } + + final VLayout layout = new VLayout(); + final Canvas submit = getNextButton(); + + final VLayout root = new VLayout(); + root.setWidth(420); + createWidget(root, data, tableData); + + layout.addMember(root); + layout.addMember(submit); + + validateRangeOverlap();// init Text + return layout; + } + + @Override + protected Data[] getData() { + final List data = new ArrayList(); + + final ListGridRecord[] lgr = this.table.getRecords(); + if (lgr == null) { + return new Data[0]; + } + final List zoneList = getSalixZones(lgr); + final DataItem item = new DefaultDataItem(this.datakey, null, SalixZone.parseListToDataString(zoneList)); + data.add(new DefaultData(this.datakey, null, null, new DataItem[] { item })); + return data.toArray(new Data[data.size()]); + } + + private List getSalixZones(final ListGridRecord[] lgr) { + final List zoneList = new ArrayList(); + for (final ListGridRecord element : lgr) { + final Record r = element; + final SalixZone zone = SalixZone.createFromTableEntry(r.getAttribute("dmwspl"), r.getAttribute("from"), r.getAttribute("to")); + zoneList.add(zone); + } + return zoneList; + } + + public Canvas createWidget(final Layout root, final DataList data, final String tableData) { + + this.table = createTable(root, data, tableData); + + final TextItem dwspl = PanelHelper.createItem("_label_dwspl", this.MSG.uinfo_salix_dmwspl_short(), "50"); + // this.dwspl.setColSpan(3); + final TextItem start = PanelHelper.createIntegerItem("_from_dwspl", getLabelFromTo(this.MSG.from()), "50"); + // this.start.setColSpan(3); + final TextItem end = PanelHelper.createIntegerItem("_to_dwspl", getLabelFromTo(this.MSG.to()), "50"); + // this.end.setColSpan(3); + + final HLayout fields = new HLayout(); + + final Button add = new Button(this.MSG.add_date()); // TODO: make key more generic or change to more specific + + final DynamicForm newEntryForm = new DynamicForm(); + newEntryForm.setWidth(320); + newEntryForm.setNumCols(12); + newEntryForm.setFields(dwspl, start, end); + + add.addClickHandler(new ClickHandler() { + @Override + public void onClick(final ClickEvent ce) { + final String v1 = start.getValueAsString(); + final String v2 = end.getValueAsString(); + final String v3 = dwspl.getValueAsString(); + final String message = validate(v1, v2, v3); + if (message != null) { + SC.warn(message); + return; + } + final ListGridRecord r = new ListGridRecord(); + r.setAttribute("dmwspl", v3); + r.setAttribute("from", SupraRegionalTablePanel.this.format.parse(v1)); + r.setAttribute("to", SupraRegionalTablePanel.this.format.parse(v2)); + SupraRegionalTablePanel.this.table.addData(r); + validateRangeOverlap(); + } + }); + + fields.addMember(newEntryForm); + + root.addMember(fields); + root.addMember(PanelHelper.getSpacer(10)); + + initHelperPanel(start, end); + + root.addMember(add); + root.addMember(PanelHelper.getSpacer(20)); + return root; + } + + private String getLabelFromTo(final String fromOrTo) { + return new StringBuilder().append(fromOrTo).append(" [").append(this.MSG.dpUnitFrom()).append("]").toString(); + } + + protected void initHelperPanel(final TextItem start, final TextItem end) { + final DistancePanelInputHelper helper = new DistancePanelInputHelper(this.MSG, this.helperContainer, this.getRiverName()); + + helper.getDistancesTable().addRecordClickHandler(new RecordClickHandler() { + @Override + public void onRecordClick(final RecordClickEvent e) { + final Record r = e.getRecord(); + + final String from = r.getAttribute("from"); + final String to = r.getAttribute("to"); + + try { + start.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(from))); + end.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(to))); + } + catch (final NumberFormatException nfe) { + SC.warn(SupraRegionalTablePanel.this.MSG.wrongFormat()); + } + } + }); + + helper.getLocationsTable().addRecordClickHandler(new RecordClickHandler() { + @Override + public void onRecordClick(final RecordClickEvent e) { + final Record r = e.getRecord(); + final int field = e.getFieldNum(); + + try { + final String value = r.getAttribute("from"); + switch (field) { + case 0: + start.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(value))); + break; + case 1: + end.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(value))); + break; + } + } + catch (final NumberFormatException nfe) { + SC.warn(SupraRegionalTablePanel.this.MSG.wrongFormat()); + } + } + }); + + } + + protected final ListGrid createTable(final Layout root, final DataList data, final String tableData) { + + final Label title = new Label(data.get(0).getDescription()); + title.setHeight("35px"); + this.validationLabel.setHeight("10px"); + + final ListGrid elements = new ListGrid(); + elements.setWidth(320); + elements.setHeight(300); + elements.setShowHeaderContextMenu(false); + elements.setCanReorderFields(false); + elements.setCanResizeFields(false); + elements.setCanEdit(true); + elements.setCanSort(false); + elements.setCanResizeFields(false); + + final ListGridField dmwsplField = new ListGridField("dmwspl", this.MSG.uinfo_salix_dmwspl_short()); + dmwsplField.setAlign(Alignment.RIGHT); + dmwsplField.setWidth(95); + dmwsplField.addCellSavedHandler(new CellSavedHandler() { + @Override + public void onCellSaved(final CellSavedEvent event) { + final Object value = event.getNewValue(); + event.getRecord().setAttribute("dmwspl", event.getOldValue()); + try { + final int intValue = Integer.valueOf(String.valueOf(value)); + event.getRecord().setAttribute("dmwspl", intValue); + } + catch (final NumberFormatException e) { + e.printStackTrace(); + } + } + }); + final ListGridField fromField = createDoubleTableField("from", this.MSG.from()); + final ListGridField toField = createDoubleTableField("to", this.MSG.to()); + final ListGridField removeField = PanelHelper.createRemoveField(elements, GWT.getHostPageBaseURL() + this.MSG.removeFeature()); + elements.addRecordClickHandler(new RecordClickHandler() { // adding another custom record-Remove-Handler which is not included in the Panelhelper + @Override + public void onRecordClick(final RecordClickEvent event) { + if (event.getField().getName().equals(removeField.getName())) { + validateRangeOverlap(); + } + } + }); + elements.setFields(dmwsplField, fromField, toField, removeField); + addDataInit(elements, tableData); + + root.addMember(title); + root.addMember(elements); + root.addMember(PanelHelper.getSpacer(3)); + root.addMember(this.validationLabel); + root.addMember(PanelHelper.getSpacer(4)); + return elements; + } + + private void addDataInit(final ListGrid table, final String tableData) { + if (tableData != null) { + final List rows = SalixZone.parse(tableData); + for (final SalixZone row : rows) { + table.addData(createEntry(row)); + } + } + } + + public final ListGridRecord createEntry(final SalixZone row) { + + final Integer dwspl = row.getDwsplValue(); + final Double from = row.getFromKm(); + final Double to = row.getToKm(); + + if (dwspl == null || from == null || to == null) { + return null; + } + + final ListGridRecord r = new ListGridRecord(); + r.setAttribute("dmwspl", dwspl); + r.setAttribute("from", from); + r.setAttribute("to", to); + + return r; + + } + + private ListGridField createDoubleTableField(final String key, final String msg) { + final ListGridField field = new ListGridField(key, msg); + field.setAlign(Alignment.RIGHT); + field.setWidth(90); + field.addCellSavedHandler(new CellSavedHandler() { + @Override + public void onCellSaved(final CellSavedEvent event) { + final Object value = event.getNewValue(); + event.getRecord().setAttribute(key, event.getOldValue()); + try { + final double d = SupraRegionalTablePanel.this.format.parse(String.valueOf(value)); + if (d > SupraRegionalTablePanel.this.maxKm) { + event.getRecord().setAttribute(key, SupraRegionalTablePanel.this.maxKm); + } else if (d < SupraRegionalTablePanel.this.minKm) { + event.getRecord().setAttribute(key, SupraRegionalTablePanel.this.minKm); + } else { + event.getRecord().setAttribute(key, d); + } + validateRangeOverlap(); + } + catch (final NumberFormatException e) { + e.printStackTrace(); + } + } + }); + + field.setEditValueFormatter(new CellEditValueFormatter() { + @Override + public Object format(final Object value, final ListGridRecord record, final int rowNum, final int colNum) { + if (!(value instanceof Float || value instanceof Double)) { + try { + return (float) SupraRegionalTablePanel.this.format.parse(String.valueOf(value)); + } + catch (final Exception e2) { + return record.getAttribute(key); + } + } else { + return SupraRegionalTablePanel.this.format.format((Double) value); + } + } + }); + field.setCellFormatter(new CellFormatter() { + @Override + public String format(final Object value, final ListGridRecord record, final int rowNum, final int colNum) { + return SupraRegionalTablePanel.this.format.format(Double.valueOf(String.valueOf(value))); + } + }); + return field; + } + + private String validate(final String fromInput, final String toInput, final String dmwspl) { + + if (fromInput == null || toInput == null || dmwspl == null || fromInput.trim().isEmpty() || toInput.trim().isEmpty() || dmwspl.trim().isEmpty()) + return this.MSG.uinfo_vegetation_zones_validation_empty(); + + try { + final Double from = this.format.parse(fromInput); + final Double to = this.format.parse(toInput); + Integer.valueOf(dmwspl); + + if (from < this.minKm || from > this.maxKm || to > this.maxKm || to < this.minKm) + return this.MSG.uinfo_salix_km_limit_exceed(); + return null; + } + catch (final NumberFormatException e) { + return this.MSG.wrongFormat(); + } + } + + private void validateRangeOverlap() { + final StringBuilder builder = new StringBuilder(); + if (SalixZone.zonesAreOverlapping(this.getSalixZones(this.table.getRecords()))) + builder.append(this.MSG.uinfo_salix_km_overlap()).append(" "); + if (SalixZone.hasGaps(this.getSalixZones(this.table.getRecords()), this.minKm, this.maxKm)) + builder.append(this.MSG.uinfo_salix_km_has_gaps());// "Der Km-Bereich wird nicht vollst. abgedeckt."; + + this.validationLabel.setText(builder.toString()); + } +} \ No newline at end of file diff -r b515ed950d39 -r 972e10522ed6 gwt-client/src/main/java/org/dive4elements/river/client/shared/model/SalixZone.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/SalixZone.java Tue Jul 10 11:24:12 2018 +0200 @@ -0,0 +1,155 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.shared.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; + +/** + * @author Domenico Nardi Tironi + * + */ +public class SalixZone implements Comparable { + + // IMMER ABGLEICHEN Server Client SalixZone.java + private static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR"; + private static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR"; + private final int dwsplValue; + private final double fromKm; + private final double toKm; + + private final static double DELTA = 0.0001; + + public static List parse(final String zonesRaw) { + final List resultList = new ArrayList(); + + final List results = new ArrayList(); + if (zonesRaw.contains(TABLE_ROW_SEPARATOR)) { + final String[] rows = zonesRaw.split(TABLE_ROW_SEPARATOR); + for (final String row : rows) { + if (row.contains(TABLE_CELL_SEPARATOR)) { + final String[] result = row.split(TABLE_CELL_SEPARATOR); + results.add(result); + } + } + } + for (final String[] zone : results) { + final SalixZone helper = new SalixZone(Integer.valueOf(zone[0]), Double.valueOf(zone[1]), Double.valueOf(zone[2])); + resultList.add(helper); + } + return resultList; + } + + public static SalixZone createFromTableEntry(final String dwspl, final String from, final String to) { + return new SalixZone(Integer.valueOf(dwspl), Double.valueOf(from), Double.valueOf(to)); // Error-Handling? + } + + private SalixZone(final int dwsplValue, final double fromKm, final double toKm) { + this.dwsplValue = dwsplValue; + this.fromKm = fromKm; + this.toKm = toKm; + } + + public Double getToKm() { + return this.toKm; + } + + public int getDwsplValue() { + return this.dwsplValue; + } + + public Double getFromKm() { + return this.fromKm; + } + + public static final String parseListToDataString(final List list) { + + java.util.Collections.sort(list); + final StringBuilder builder = new StringBuilder(); + for (final SalixZone zone : list) { + builder.append(zone.getDwsplValue()); + builder.append(TABLE_CELL_SEPARATOR); + builder.append(zone.getFromKm()); + builder.append(TABLE_CELL_SEPARATOR); + builder.append(zone.getToKm()); + builder.append(TABLE_ROW_SEPARATOR); + } + return builder.toString(); + } + + public static final boolean zonesAreOverlapping(final List list) { + for (final SalixZone zone : list) { + for (final SalixZone zoneOther : list) { + if (zone != zoneOther) { + final boolean overlaps = zone.overlaps(zoneOther); + if (overlaps) { + return overlaps; // cancel. only one zone has to overlap + } + } + } + } + + return false; + } + + public static final boolean hasGaps(final List list, final double lower, final double upper) { + + if (((upper - lower) > DELTA) && list.size() == 0) + return true; + + final TreeSet treeList = new TreeSet(); + treeList.addAll(list); + double lowerCompare = lower + DELTA; + for (final SalixZone zone : treeList) { + if (zone.getLowerFromTo() > lowerCompare) { + return true; + } + lowerCompare = zone.getUpperFromTo() + DELTA; + } + if ((lowerCompare + DELTA) < upper) + return true; // am Ende nicht geschlossen + + return false; + } + + private Double getLowerFromTo() { + return this.fromKm < this.toKm ? this.fromKm : this.toKm; // Math. is forbidden :-( + } + + private Double getUpperFromTo() { + return this.fromKm > this.toKm ? this.fromKm : this.toKm;// Math. is forbidden :-( + } + + private boolean overlaps(final SalixZone otherZone) { + final double otherLower = otherZone.getLowerFromTo(); + final double otherUpper = otherZone.getUpperFromTo(); + + final double upper = getUpperFromTo() - DELTA; + final double lower = getLowerFromTo() + DELTA; + final double otherSchwerpunkt = (otherLower + otherUpper) / 2; + if ((otherUpper < upper && otherUpper > lower)) { + return true; + } else if (otherLower > lower && otherLower < upper) { + return true; + } else if (otherSchwerpunkt > lower && otherSchwerpunkt < upper) { + return true; + } + return false; + } + + @Override + public int compareTo(final SalixZone o) { + final int basicCompare = this.getLowerFromTo().compareTo(o.getLowerFromTo()); + return basicCompare; + } + +}