# HG changeset patch # User gernotbelger # Date 1531817967 -7200 # Node ID b570b6fcc052e3eda222f92cc71967b73a113f23 # Parent 66b003701546622cb4bfa8e9b738fa3956fa37a0 VegetationZone color added and disabled diff -r 66b003701546 -r b570b6fcc052 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/commons/UInfoResultType.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/commons/UInfoResultType.java Mon Jul 16 08:43:07 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/commons/UInfoResultType.java Tue Jul 17 10:59:27 2018 +0200 @@ -151,6 +151,19 @@ } }; + public static final UInfoResultType vegzone_color = new UInfoResultType(null, "uinfo.export.csv.meta.header.veg.color") { + private static final long serialVersionUID = 1L; + + @Override + public String exportValue(final CallContext context, final Object value) { + return exportStringValue(value); + } + + @Override + protected NumberFormat createFormatter(final CallContext context) { + throw new UnsupportedOperationException(); + } + }; public static final UInfoResultType vegdauervon = new UInfoResultType(null, "uinfo.export.csv.meta.header.veg.dauervon") { private static final long serialVersionUID = 1L; @@ -173,9 +186,8 @@ @Override public String exportValue(final CallContext context, final Object value) { - - final double doubleValue = asDouble(value); - return exportDoubleValue(context, doubleValue); + // valix hex-Check? + return String.valueOf(value); } @Override diff -r 66b003701546 -r b570b6fcc052 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZone.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZone.java Mon Jul 16 08:43:07 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZone.java Tue Jul 17 10:59:27 2018 +0200 @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.TreeSet; /** * @author Domenico Nardi Tironi @@ -18,12 +19,15 @@ */ public class VegetationZone implements Comparable { - // IMMER ABGLEICHEN MIT VEGETATIONZONE IM CLIENT SuperVegZonesTablePanel.TABLE_CELL_SEPARATOR + // IMMER ABGLEICHEN MIT VegetationZone.class Server und Client + public static final boolean HAS_COLORS_EDITABLE = false; + private static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR"; private static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR"; private final String zoneName; private final int min_day_overflow; private final int max_day_overflow; + private final String hexColor; public static List parse(final String zonesRaw) { final List resultList = new ArrayList<>(); @@ -40,21 +44,22 @@ } for (final String[] zone : results) { - final VegetationZone helper = new VegetationZone(zone[0], Integer.valueOf(zone[1]), Integer.valueOf(zone[2])); + final VegetationZone helper = new VegetationZone(zone[0], Integer.valueOf(zone[1]), Integer.valueOf(zone[2]), zone[3]); resultList.add(helper); } return resultList; } - public static VegetationZone createFromTableEntry(final String zone, final String min_day_overflow, final String max_day_overflow) { - return new VegetationZone(zone, Integer.valueOf(min_day_overflow), Integer.valueOf(max_day_overflow)); // Error-Handling? + public static VegetationZone createFromTableEntry(final String zone, final String min_day_overflow, final String max_day_overflow, final String hexColor) { + return new VegetationZone(zone, Integer.valueOf(min_day_overflow), Integer.valueOf(max_day_overflow), hexColor); // Error-Handling? } - private VegetationZone(final String zone, final Integer min_day_overflow, final Integer max_day_overflow) { + private VegetationZone(final String zone, final Integer min_day_overflow, final Integer max_day_overflow, final String hexColor) { this.zoneName = zone; this.min_day_overflow = min_day_overflow; this.max_day_overflow = max_day_overflow; + this.hexColor = hexColor; } public int getMax_day_overflow() { @@ -62,9 +67,22 @@ } public String getZoneName() { + if (this.zoneName == null || this.zoneName.equals("")) { + return "---"; + } return this.zoneName; } + public String getHexColor() { + try { + final int test = Integer.decode(this.hexColor); + return this.hexColor; + } + catch (final NumberFormatException e) { + return "#ffffff"; + } + } + public int getMin_day_overflow() { return this.min_day_overflow; } @@ -72,15 +90,15 @@ public static final List getStandardList() { final List list = new ArrayList<>(); - list.add(new VegetationZone("Zonaler Wald", 0, 5)); - list.add(new VegetationZone("Hartholzaue, trocken", 5, 40)); - list.add(new VegetationZone("Hartholzaue, feucht", 40, 80)); - list.add(new VegetationZone("Silberweidenwald", 80, 140)); - list.add(new VegetationZone("Weidengebüsch", 140, 200)); - list.add(new VegetationZone("Uferröhricht", 200, 260)); - list.add(new VegetationZone("Uferpioniere", 260, 320)); - list.add(new VegetationZone("Vegetationslos", 320, 365)); - list.add(new VegetationZone("Wasserfläche", 365, 365)); + list.add(new VegetationZone("Zonaler Wald", 0, 5, "#336600")); + list.add(new VegetationZone("Hartholzaue, trocken", 6, 40, "#00cc00")); + list.add(new VegetationZone("Hartholzaue, feucht", 41, 80, "#66ff33")); + list.add(new VegetationZone("Silberweidenwald", 81, 140, "#008080")); + list.add(new VegetationZone("Weidengebüsch", 141, 200, "#33cccc")); + list.add(new VegetationZone("Uferröhricht", 201, 260, "#ffa8ff")); + list.add(new VegetationZone("Uferpioniere", 261, 320, "#ff0000")); + list.add(new VegetationZone("Vegetationslos", 321, 364, "#b2b2b2")); + list.add(new VegetationZone("Wasserfläche", 365, 365, "#0066ff")); return list; } @@ -95,6 +113,8 @@ builder.append(zone.getMin_day_overflow()); builder.append(TABLE_CELL_SEPARATOR); builder.append(zone.getMax_day_overflow()); + builder.append(TABLE_CELL_SEPARATOR); + builder.append(zone.getHexColor()); builder.append(TABLE_ROW_SEPARATOR); } return builder.toString(); @@ -105,8 +125,73 @@ public int compareTo(final VegetationZone o) { final int basicCompare = Integer.valueOf(this.getMin_day_overflow()).compareTo(o.getMin_day_overflow()); if (basicCompare == 0) - return Integer.compare(this.getMax_day_overflow(), o.getMax_day_overflow()); // wenn min==min && max==max, alphabetisch sortieren? + return Integer.valueOf(this.getMax_day_overflow()).compareTo(o.getMax_day_overflow()); // wenn min==min && max==max, alphabetisch sortieren? + + if (basicCompare == 0) { + return 1; // for treeSet + } + return basicCompare; } + public static final boolean zonesAreOverlapping(final List list) { + for (final VegetationZone zone : list) { + for (final VegetationZone 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 int lower, final int upper) { + + if ((upper - lower) == 0) + return true; + + final TreeSet treeList = new TreeSet<>(); + treeList.addAll(list); + int lowerCompare = lower; + for (final VegetationZone zone : treeList) { + if (zone.getLowerFromTo() > (lowerCompare + 1)) { // nicht inklusiv + return true; + } + lowerCompare = zone.getUpperFromTo(); + } + if ((lowerCompare) < upper) + return true; // am Ende nicht geschlossen + + return false; + } + + private boolean overlaps(final VegetationZone otherZone) { + final int otherLower = otherZone.getLowerFromTo(); + final int otherUpper = otherZone.getUpperFromTo(); + + final int upper = getUpperFromTo(); + final int lower = getLowerFromTo(); + final int 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; + } + + public Integer getLowerFromTo() { + return this.min_day_overflow < this.max_day_overflow ? this.min_day_overflow : this.max_day_overflow; // Math. is forbidden :-( + } + + public Integer getUpperFromTo() { + return this.min_day_overflow > this.max_day_overflow ? this.min_day_overflow : this.max_day_overflow;// Math. is forbidden :-( + } + } diff -r 66b003701546 -r b570b6fcc052 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCalculation.java Mon Jul 16 08:43:07 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCalculation.java Tue Jul 17 10:59:27 2018 +0200 @@ -57,7 +57,8 @@ final ResultRow row2 = ResultRow.create().// putValue(UInfoResultType.vegname, zone.getZoneName()).// putValue(UInfoResultType.vegdauervon, zone.getMin_day_overflow()).// - putValue(UInfoResultType.vegdauerbis, zone.getMax_day_overflow()); + putValue(UInfoResultType.vegdauerbis, zone.getMax_day_overflow()).// + putValue(UInfoResultType.vegzone_color, zone.getHexColor()); rows.add(row2); } diff -r 66b003701546 -r b570b6fcc052 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCalculationResult.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCalculationResult.java Mon Jul 16 08:43:07 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCalculationResult.java Tue Jul 17 10:59:27 2018 +0200 @@ -41,7 +41,8 @@ header.add(exportContextCSV.formatCsvHeader(UInfoResultType.vegname)); header.add(exportContextCSV.formatCsvHeader(UInfoResultType.vegdauervon)); header.add(exportContextCSV.formatCsvHeader(UInfoResultType.vegdauerbis)); - + if (VegetationZone.HAS_COLORS_EDITABLE) + header.add(exportContextCSV.formatCsvHeader(UInfoResultType.vegzone_color)); exportContextCSV.writeCSVLine(header.toArray(new String[header.size()])); } @@ -74,7 +75,7 @@ exportContextPDF.addJRMetadata(source, "veg_name", UInfoResultType.vegname); exportContextPDF.addJRMetadata(source, "veg_dauervon", UInfoResultType.vegdauervon); exportContextPDF.addJRMetadata(source, "veg_dauerbis", UInfoResultType.vegdauerbis); - + // TODO add color to jasper-template and here } protected String[] formatRow(final IExportContext context, final ResultRow row) { @@ -84,7 +85,8 @@ lines.add(context.formatRowValue(row, UInfoResultType.vegname)); lines.add(context.formatRowValue(row, UInfoResultType.vegdauervon)); lines.add(context.formatRowValue(row, UInfoResultType.vegdauerbis)); - + if (VegetationZone.HAS_COLORS_EDITABLE) + lines.add(context.formatRowValue(row, UInfoResultType.vegzone_color)); return lines.toArray(new String[lines.size()]); } diff -r 66b003701546 -r b570b6fcc052 artifacts/src/main/resources/messages.properties --- a/artifacts/src/main/resources/messages.properties Mon Jul 16 08:43:07 2018 +0200 +++ b/artifacts/src/main/resources/messages.properties Tue Jul 17 10:59:27 2018 +0200 @@ -1110,6 +1110,7 @@ uinfo.export.csv.meta.header.veg.name = Vegetationszonen uinfo.export.csv.meta.header.veg.dauervon = \u00dcberflutungsdauer von [d/a] uinfo.export.csv.meta.header.veg.dauerbis = \u00dcberflutungsdauer bis [d/a] +uinfo.export.csv.meta.header.veg.color = Farbe uinfo.export.url.inundationduration.inundationduration = \u00dcberflutungsdauer ({0}) uinfo.export.url.inundationduration.vegetation = Vegetationszonen ({0}) uinfo.export.url.inundationduration.vegetation_scenario= Vegetationszonen Szenario ({0}, {1}cm) diff -r 66b003701546 -r b570b6fcc052 artifacts/src/main/resources/messages_de.properties --- a/artifacts/src/main/resources/messages_de.properties Mon Jul 16 08:43:07 2018 +0200 +++ b/artifacts/src/main/resources/messages_de.properties Tue Jul 17 10:59:27 2018 +0200 @@ -1110,6 +1110,7 @@ uinfo.export.csv.meta.header.veg.name = Vegetationszonen uinfo.export.csv.meta.header.veg.dauervon = \u00dcberflutungsdauer von [d/a] uinfo.export.csv.meta.header.veg.dauerbis = \u00dcberflutungsdauer bis [d/a] +uinfo.export.csv.meta.header.veg.color = Farbe uinfo.export.url.inundationduration.inundationduration = \u00dcberflutungsdauer ({0}) uinfo.export.url.inundationduration.vegetation = Vegetationszonen ({0}) uinfo.export.url.inundationduration.vegetation_scenario= Vegetationszonen Szenario ({0}, {1}cm) diff -r 66b003701546 -r b570b6fcc052 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 Mon Jul 16 08:43:07 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Tue Jul 17 10:59:27 2018 +0200 @@ -1525,8 +1525,6 @@ String uinfo_vegetation_zones_validation_from_greater_to(); - String uinfo_vegetation_zones_invalid_integer(); - String chart_settings_export_metadata(); String sinfo_flow_depth_development_twin_panel_max_count_msg(); @@ -1561,8 +1559,6 @@ String uinfo_salix_dmwspl_short(); - String uinfo_salix_invalid_double(); - String uinfo_salix_km_limit_exceed(); String uinfo_salix_km_overlap(); @@ -1574,4 +1570,14 @@ String uinfo_salix_input_complete(); String common_input_hint_year(); + + String error_invalid_integer(); + + String error_invalid_double(); + + String uinfo_vegetation_zone_color(); + + String uinfo_vegetation_zone_overlap(); + + String uinfo_vegetation_zone_has_gaps(); } \ No newline at end of file diff -r 66b003701546 -r b570b6fcc052 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 Mon Jul 16 08:43:07 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Tue Jul 17 10:59:27 2018 +0200 @@ -326,6 +326,8 @@ ele_window_save_error = Error while saving elevations. ele_window_geometry_error = The geometry is not supported: +error_invalid_integer = Nur Ganzzahlen erlaubt. +error_invalid_double = Nur Zahlen erlaubt. error_limit_exceeded_salix = Die Eingabe ist auf 5 Werte beschr\u00e4nkt. error_no_data_for_river = F\u00fcr das gew\u00e4hlte Gew\u00e4sser liegen keine Daten vor. unexpected_exception = There occured an unexpected exception @@ -824,6 +826,9 @@ uinfo_salix_line_export = Salix-Linie Export uinfo_vegetation_zones_export = Vegetationszonen Export +uinfo_vegetation_zone_overlap = Bereiche \u00fcberlappen. +uinfo_vegetation_zone_has_gaps = Die Wertebelegung (0-365) weist L\u00fccken auf. +uinfo_vegetation_zone_color = Farbe uinfo_vegetation_zone_label = Vegetationszone uinfo_vegetation_zones_label = Vegetationszonen uinfo_vegetation_zones_from = \u00dcfd von [d/a] @@ -831,8 +836,6 @@ uinfo_vegetation_zones_validation_empty = Eingabefeld leer. 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 \u00fcberlappen. uinfo_salix_km_has_gaps = Der Km-Bereich ist nicht vollst. belegt. diff -r 66b003701546 -r b570b6fcc052 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 Mon Jul 16 08:43:07 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Tue Jul 17 10:59:27 2018 +0200 @@ -326,6 +326,8 @@ ele_window_save_error = Fehler beim Speichern der H\u00f6hen. ele_window_geometry_error = Die Geometrie wird nicht unterst\u00fctzt: +error_invalid_integer = Nur Ganzzahlen erlaubt. +error_invalid_double = Nur Zahlen erlaubt. error_limit_exceeded_salix = Die Eingabe ist auf 5 Werte beschr\u00e4nkt. error_no_data_for_river = F\u00fcr das gew\u00e4hlte Gew\u00e4sser liegen keine Daten vor. unexpected_exception = Ein unerwarteter Fehler ist aufgetreten @@ -824,15 +826,16 @@ uinfo_salix_line_export = Salix-Linie Export uinfo_vegetation_zones_export = Vegetationszonen Export +uinfo_vegetation_zone_overlap = Bereiche \u00fcberlappen. +uinfo_vegetation_zone_has_gaps = Die Wertebelegung (0-365) weist L\u00fccken auf. +uinfo_vegetation_zone_color = Farbe uinfo_vegetation_zone_label = Vegetationszone uinfo_vegetation_zones_label = Vegetationszonen uinfo_vegetation_zones_from = \u00dcfd von [d/a] uinfo_vegetation_zones_to = \u00dcfd bis [d/a] uinfo_vegetation_zones_validation_empty = Eingabefeld leer. 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_vegetation_zones_validation_from_greater_to = Der Wert f\u00fcr "\u00dcfd von" muss kleiner als "\u00dcfd bis". uinfo_salix_km_limit_exceed = Die Zahl ist au\u00dferhalb des g\u00fcltigen km-Bereichs. uinfo_salix_km_overlap = Km-Bereiche \u00fcberlappen. uinfo_salix_km_has_gaps = Der Km-Bereich ist nicht vollst. belegt. diff -r 66b003701546 -r b570b6fcc052 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractSingleItemPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractSingleItemPanel.java Mon Jul 16 08:43:07 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractSingleItemPanel.java Tue Jul 17 10:59:27 2018 +0200 @@ -118,7 +118,6 @@ final List errors = this.validate(); if (errors.size() > 0) { showErrors(errors); // TODO: do not allow advance state - // return null; } if (this.inputItem != null && !this.inputItem.getValueAsString().isEmpty()) { final List data = new ArrayList(); @@ -136,16 +135,6 @@ return this.inputItem; } - private final List checkForEmpty() { - final List errors = new ArrayList(); - - if (this.inputItem.getValueAsString() == null || this.inputItem.getValueAsString().trim().isEmpty()) { - errors.add(this.MSG.empty_filter()); - return errors; - } - return errors; - } - protected abstract String errorForItemMsg(); protected final void appendValue(final String value) { @@ -155,7 +144,7 @@ @Override public final List validate() { final List errors = new ArrayList(); - errors.addAll(this.checkForEmpty()); + errors.addAll(ValidationHelper.checkForEmpty(this.inputItem, this.MSG)); final String sValue = this.inputItem.getValueAsString(); return this.behaviour.validate(errors, sValue); } diff -r 66b003701546 -r b570b6fcc052 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ValidationHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ValidationHelper.java Tue Jul 17 10:59:27 2018 +0200 @@ -0,0 +1,33 @@ +/** 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.client.ui; + +import java.util.ArrayList; +import java.util.List; + +import org.dive4elements.river.client.client.FLYSConstants; + +import com.smartgwt.client.widgets.form.fields.TextItem; + +/** + * @author Domenico Nardi Tironi + * + */ +public class ValidationHelper { + public static final List checkForEmpty(final TextItem inputItem, final FLYSConstants MSG) { + final List errors = new ArrayList(); + + if (inputItem.getValueAsString() == null || inputItem.getValueAsString().trim().isEmpty()) { + errors.add(MSG.empty_filter()); + return errors; + } + return errors; + } +} diff -r 66b003701546 -r b570b6fcc052 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/VegZonePanelHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/VegZonePanelHelper.java Tue Jul 17 10:59:27 2018 +0200 @@ -0,0 +1,49 @@ +/** 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.client.ui; + +import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator; +import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.widgets.grid.SortNormalizer; +import com.smartgwt.client.widgets.grid.events.CellSavedEvent; +import com.smartgwt.client.widgets.grid.events.CellSavedHandler; + +/** + * @author Domenico Nardi Tironi + * + */ +public class VegZonePanelHelper { + + public VegZonePanelHelper() { + + } + + public static ListGridField createIntTableField(final String key, final String msg, final boolean canSort, final SortNormalizer normalizer, + final IntegerRangeValidator validators) { + final ListGridField intField = PanelHelper.createIntTableField(key, msg, canSort, normalizer, validators); + intField.addCellSavedHandler(new CellSavedHandler() { // wirkungslos, wenn int-validator bereits vorhanden ist.. + @Override + public void onCellSaved(final CellSavedEvent event) { + final Object value = event.getNewValue(); + event.getRecord().setAttribute(key, event.getOldValue()); + try { + final int intValue = Integer.valueOf(String.valueOf(value)); + event.getRecord().setAttribute(key, intValue); + } + catch (final NumberFormatException e) { + e.printStackTrace(); + } + } + }); + return intField; + + } + +} diff -r 66b003701546 -r b570b6fcc052 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/AbstractVegZonesTablePanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/AbstractVegZonesTablePanel.java Mon Jul 16 08:43:07 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/AbstractVegZonesTablePanel.java Tue Jul 17 10:59:27 2018 +0200 @@ -14,6 +14,7 @@ import org.dive4elements.river.client.client.ui.AbstractUIProvider; import org.dive4elements.river.client.client.ui.PanelHelper; +import org.dive4elements.river.client.client.ui.VegZonePanelHelper; import org.dive4elements.river.client.shared.model.Data; import org.dive4elements.river.client.shared.model.DataItem; import org.dive4elements.river.client.shared.model.DataList; @@ -22,16 +23,20 @@ import org.dive4elements.river.client.shared.model.VegetationZone; import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.Label; import com.smartgwt.client.data.Record; import com.smartgwt.client.types.Alignment; import com.smartgwt.client.types.ListGridFieldType; +import com.smartgwt.client.types.SortDirection; import com.smartgwt.client.widgets.Canvas; -import com.smartgwt.client.widgets.Label; +import com.smartgwt.client.widgets.form.fields.ColorItem; import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator; 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.SortNormalizer; +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; @@ -46,8 +51,31 @@ private static final long serialVersionUID = 1L; private static final String datakey = "vegzones"; + final protected List records = new ArrayList(); + private final Label validationLabel = new Label(); + private final ListGrid elements = new ListGrid() { - private final ListGrid elements = new ListGrid(); + @Override + protected String getCellCSSText(final ListGridRecord record, final int rowNum, final int colNum) { + if (record != null) { + if (getFieldName(colNum).equals("color")) { + final String color = record.getAttribute("color"); + return "background-color:" + color + ";"; + } + } + return super.getCellCSSText(record, rowNum, colNum); // is null... + } + + @Override + protected Canvas getCellHoverComponent(final Record record, final java.lang.Integer rowNum, final java.lang.Integer colNum) { + if (record != null) { + if (getFieldName(colNum).equals("color")) { + return null;// "background-color:" + color + ";"; + } + } + return super.getCellHoverComponent(record, rowNum, colNum); // is null... + } + }; protected final ListGrid createTable(final Layout root, final DataList data, final String width, final boolean editable) { @@ -59,33 +87,131 @@ this.elements.setShowHeaderContextMenu(false); this.elements.setCanReorderFields(false); this.elements.setCanSort(true); - this.elements.setSortField(1); + this.elements.setSortField("to"); this.elements.setCanResizeFields(false); this.elements.setCanEdit(editable); + final ListGridField internalNumber = new ListGridField("number", "number"); // valid only if no data is to be added + internalNumber.setCanSort(false); + internalNumber.setHidden(true); + final ListGridField vegzoneField = new ListGridField("vegzone", this.MSG.uinfo_vegetation_zones_label()); vegzoneField.setType(ListGridFieldType.TEXT); vegzoneField.setWidth("*"); // 245 vegzoneField.setCanSort(false); vegzoneField.setCanDragResize(true); + vegzoneField.setCanEdit(true); // neue Anforderung - doch nicht? ??? - final ListGridField fromField = createIntTableField("from", this.MSG.uinfo_vegetation_zones_from(), true); - final ListGridField toField = createIntTableField("to", this.MSG.uinfo_vegetation_zones_to(), false);// nicht sortierbar nach "ÜFDauer bis" + final ListGridField fromField = VegZonePanelHelper.createIntTableField("from", this.MSG.uinfo_vegetation_zones_from(), true, getNormalizer(), + getValidator()); + fromField.addCellSavedHandler(new CellSavedHandler() { + @Override + public void onCellSaved(final CellSavedEvent event) { + validateRangeOverlap(); + } + }); + // war mal ne anforderung, dass sich die Werte anderer Zellen ändern, sodass keine lücken entstehen... mach das jetzt + // aber über die Validierung. es sei denn, es soll doch wieder erwünscht sein, dass sihc die werte andere Zellen ändern + // fromField.addCellSavedHandler(new CellSavedHandler() { + // + // @Override + // public void onCellSaved(final CellSavedEvent event) { + // + // final ListGridRecord r = event.getRecord(); + // + // final int from = Integer.valueOf(r.getAttribute("from")); + // final int to = Integer.valueOf(r.getAttribute("to")); + // final String message = validate(r.getAttribute("from"), r.getAttribute("to"), r.getAttribute("zone"), + // r.getAttribute("color")); + // + // final int key = Integer.valueOf(r.getAttribute("number")); + // final int lowerKey = key - 1; + // final int higherKey = key + 1; + // + // final ListGridRecord lower = lowerKey > -1 ? AbstractVegZonesTablePanel.this.records.get(lowerKey) : null; + // final ListGridRecord higher = higherKey < AbstractVegZonesTablePanel.this.records.size() + // ? AbstractVegZonesTablePanel.this.records.get(higherKey) + // : null; + // + // // primary + // if (lower != null) { + // lower.setAttribute("to", r.getAttribute("from")); + // + // // additional: + // final int lowerFrom = Integer.valueOf(lower.getAttribute("from")); + // if (lowerFrom > from) { + // lower.setAttribute("from", from); + // } + // } + // + // if (from > to) { + // r.setAttribute("to", from); + // if (higher != null) { + // // higher.setAttribute("from", from); //ist vermutlich too much + // final int higherTo = Integer.valueOf(higher.getAttribute("to")); + // if (from > higherTo) { + // // higher.setAttribute("to", from); //ist vermutlich too much + // } + // } + // } + // } + // }); + + final ListGridField toField = VegZonePanelHelper.createIntTableField("to", this.MSG.uinfo_vegetation_zones_to(), false, getNormalizer(), + getValidator()); + toField.addCellSavedHandler(new CellSavedHandler() { + @Override + public void onCellSaved(final CellSavedEvent event) { + validateRangeOverlap(); + } + }); + // nicht + // sortierbar nach + // "ÜFDauer bis" + toField.setCanEdit(true);// neue Anforderung - doch nicht? + + final ListGridField colorField = new ListGridField("color", this.MSG.uinfo_vegetation_zone_color()); + colorField.setHidden(VegetationZone.HAS_COLORS_EDITABLE ? false : true); + final ColorItem item = new ColorItem(); + colorField.setEditorProperties(item); + + colorField.setWidth(80); // 25 too small + colorField.setAlign(Alignment.LEFT); + colorField.setCanSort(false); + colorField.setCanDragResize(false); + + // sortierbar nach + // "ÜFDauer bis" + toField.setCanEdit(true);// neue Anforderung if (editable) { - final ListGridField removeField = createRemoveField(); - this.elements.setFields(vegzoneField, fromField, toField, removeField); + final ListGridField removeField = PanelHelper.createRemoveField(this.elements, GWT.getHostPageBaseURL() + this.MSG.removeFeature()); + this.elements.addRecordClickHandler(new RecordClickHandler() { // adding another custom record-Remove-Handler which is not included in the + // Panelhelper TODO: MERGE WITH SupraRegionalPanel!! + @Override + public void onRecordClick(final RecordClickEvent event) { + if (event.getField().getName().equals(removeField.getName())) { + validateRangeOverlap(); + } + } + }); + this.elements.setFields(vegzoneField, fromField, toField, colorField, removeField); } else { - this.elements.setFields(vegzoneField, fromField, toField); + this.elements.setFields(internalNumber, vegzoneField, fromField, toField, colorField); } + this.elements.sort("from", SortDirection.ASCENDING); + this.validationLabel.setHeight("10px"); + this.validationLabel.getElement().getStyle().setColor("red"); addDataInit(data); root.setWidth(width); root.addMember(title); root.addMember(this.elements); - root.addMember(PanelHelper.getSpacer(10)); + root.addMember(PanelHelper.getSpacer(3)); + root.addMember(this.validationLabel); + root.addMember(PanelHelper.getSpacer(3)); return this.elements; } @@ -110,50 +236,6 @@ return normalizer; } - private ListGridField createIntTableField(final String key, final String msg, final boolean canSort) { - final ListGridField intField = new ListGridField(key, msg); - intField.setType(ListGridFieldType.INTEGER); - intField.setValidators(getValidator()); - intField.setWidth(90); - intField.setAlign(Alignment.RIGHT); - intField.setSortNormalizer(getNormalizer()); - intField.setCanSort(canSort); - intField.setCanDragResize(false); - - return intField; - } - - private ListGridField createRemoveField() { - - final ListGridField removeField = new ListGridField("_removeRecord", "Remove Record") { - { - setType(ListGridFieldType.ICON); - setIcon(GWT.getHostPageBaseURL() + AbstractVegZonesTablePanel.this.MSG.removeFeature()); - setCanEdit(false); - setCanFilter(false); - setCanSort(false); - setCanGroupBy(false); - setCanFreeze(false); - setWidth(25); - setCanDragResize(false); - super.setCanToggle(false); - } - }; - - this.elements.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 abstract void createWidget(final Layout root, final DataList data); private final void addDataInit(final DataList data) { @@ -189,6 +271,8 @@ layout.addMember(root); layout.addMember(submit); + validateRangeOverlap();// init Text + return layout; } @@ -200,7 +284,7 @@ vLayout.setWidth(130); final Label label = new Label(dataList.getLabel()); label.setWidth("200px"); - label.setHeight(25); + label.setHeight("25px"); final List items = dataList.getAll(); final Data str = getData(items, datakey); @@ -210,7 +294,7 @@ for (final VegetationZone entry : entries) { final Label dateLabel = new Label(entry.getZoneName() + " (" + entry.getMin_day_overflow() + "-" + entry.getMax_day_overflow() + ")"); - dateLabel.setHeight(20); + dateLabel.setHeight("20px"); vLayout.addMember(dateLabel); } final Canvas back = getBackButton(dataList.getState()); @@ -229,16 +313,21 @@ if (lgr.length == 0) { return new Data[0]; // TODO: Klären, ob Vegetationszonen-Auswahl Pflicht ist, ob es ein Fallback geben soll usw. } + + final DataItem item = new DefaultDataItem(datakey, null, VegetationZone.parseListToDataString(getZones(lgr))); // DATA-key + data.add(new DefaultData(datakey, null, null, new DataItem[] { item })); + return data.toArray(new Data[data.size()]); + } + + protected final List getZones(final ListGridRecord[] lgr) { final List zoneList = new ArrayList(); for (final ListGridRecord element : lgr) { final Record r = element; - final VegetationZone zone = VegetationZone.createFromTableEntry(r.getAttribute("vegzone"), r.getAttribute("from"), r.getAttribute("to")); + final VegetationZone zone = VegetationZone.createFromTableEntry(r.getAttribute("vegzone"), r.getAttribute("from"), r.getAttribute("to"), + r.getAttribute("color")); zoneList.add(zone); } - - final DataItem item = new DefaultDataItem(datakey, null, VegetationZone.parseListToDataString(zoneList)); // DATA-key - data.add(new DefaultData(datakey, null, null, new DataItem[] { item })); - return data.toArray(new Data[data.size()]); + return zoneList; } public final ListGridRecord createEntry(final VegetationZone row) { @@ -246,7 +335,7 @@ final String vegzone = row.getZoneName(); final Integer from = row.getMin_day_overflow(); final Integer to = row.getMax_day_overflow(); - + final String colorStr = row.getHexColor(); if (vegzone == null || from == null || to == null) { return null; } @@ -255,7 +344,51 @@ r.setAttribute("vegzone", vegzone); r.setAttribute("from", from); r.setAttribute("to", to); + r.setAttribute("color", colorStr); + r.setAttribute("number", this.records.size()); + this.records.add(r); return r; } + + protected String validate(final String fromInput, final String toInput, final String zoneName, final String hexColor) { + + if (fromInput == null || toInput == null || zoneName == null || hexColor == null || fromInput.trim().isEmpty() || toInput.trim().isEmpty() + || zoneName.trim().isEmpty() || hexColor.trim().isEmpty()) + return this.MSG.uinfo_vegetation_zones_validation_empty(); + + try { + final Integer from = Integer.valueOf(fromInput); + final Integer to = Integer.valueOf(toInput); + + if (from < 0 || from > 365) + return this.MSG.uinfo_vegetation_zones_validation_range(); + + if (to < 0 || to > 365) + return this.MSG.uinfo_vegetation_zones_validation_range(); + + if (from > to) + return this.MSG.uinfo_vegetation_zones_validation_from_greater_to(); + + return null; + } + catch (final NumberFormatException e) { + return this.MSG.error_invalid_integer(); + } + } + + @Override + public List validate() { + final List errors = new ArrayList(); + + if (VegetationZone.zonesAreOverlapping(this.getZones(this.elements.getRecords()))) + errors.add(this.MSG.uinfo_vegetation_zone_overlap()); + if (VegetationZone.hasGaps(this.getZones(this.elements.getRecords()), 0, 365)) + errors.add(this.MSG.uinfo_vegetation_zone_has_gaps()); + return errors; + } + + protected final void validateRangeOverlap() { + this.validationLabel.setText(validate().toString().replace("[", "").replace("]", "").replace(",", "")); + } } \ No newline at end of file diff -r 66b003701546 -r b570b6fcc052 gwt-client/src/main/java/org/dive4elements/river/client/shared/model/VegetationZone.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/VegetationZone.java Mon Jul 16 08:43:07 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/VegetationZone.java Tue Jul 17 10:59:27 2018 +0200 @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.TreeSet; /** * @author Domenico Nardi Tironi @@ -20,11 +21,14 @@ public class VegetationZone implements Comparable { // IMMER ABGLEICHEN MIT VegetationZone.class IM SERVER + public static final boolean HAS_COLORS_EDITABLE = false; + private static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR"; private static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR"; private final String zoneName; private final int min_day_overflow; private final int max_day_overflow; + private final String hexColor; public static List parse(final String zonesRaw) { final List resultList = new ArrayList(); @@ -41,21 +45,22 @@ } for (final String[] zone : results) { - final VegetationZone helper = new VegetationZone(zone[0], Integer.valueOf(zone[1]), Integer.valueOf(zone[2])); + final VegetationZone helper = new VegetationZone(zone[0], Integer.valueOf(zone[1]), Integer.valueOf(zone[2]), zone[3]); resultList.add(helper); } return resultList; } - public static VegetationZone createFromTableEntry(final String zone, final String min_day_overflow, final String max_day_overflow) { - return new VegetationZone(zone, Integer.valueOf(min_day_overflow), Integer.valueOf(max_day_overflow)); // Error-Handling? + public static VegetationZone createFromTableEntry(final String zone, final String min_day_overflow, final String max_day_overflow, final String hexColor) { + return new VegetationZone(zone, Integer.valueOf(min_day_overflow), Integer.valueOf(max_day_overflow), hexColor); // Error-Handling? } - private VegetationZone(final String zone, final Integer min_day_overflow, final Integer max_day_overflow) { + private VegetationZone(final String zone, final Integer min_day_overflow, final Integer max_day_overflow, final String hexColor) { this.zoneName = zone; this.min_day_overflow = min_day_overflow; this.max_day_overflow = max_day_overflow; + this.hexColor = hexColor; } public int getMax_day_overflow() { @@ -63,9 +68,22 @@ } public String getZoneName() { + if (this.zoneName == null || this.zoneName.equals("")) { + return "---"; + } return this.zoneName; } + public String getHexColor() { + try { + final int test = Integer.decode(this.hexColor); + return this.hexColor; + } + catch (final NumberFormatException e) { + return "#ffffff"; + } + } + public int getMin_day_overflow() { return this.min_day_overflow; } @@ -73,15 +91,15 @@ public static final List getStandardList() { final List list = new ArrayList(); - list.add(new VegetationZone("Zonaler Wald", 0, 5)); - list.add(new VegetationZone("Hartholzaue, trocken", 5, 40)); - list.add(new VegetationZone("Hartholzaue, feucht", 40, 80)); - list.add(new VegetationZone("Silberweidenwald", 80, 140)); - list.add(new VegetationZone("Weidengebüsch", 140, 200)); - list.add(new VegetationZone("Uferröhricht", 200, 260)); - list.add(new VegetationZone("Uferpioniere", 260, 320)); - list.add(new VegetationZone("Vegetationslos", 320, 365)); - list.add(new VegetationZone("Wasserfläche", 365, 365)); + list.add(new VegetationZone("Zonaler Wald", 0, 5, "#336600")); + list.add(new VegetationZone("Hartholzaue, trocken", 6, 40, "#00cc00")); + list.add(new VegetationZone("Hartholzaue, feucht", 41, 80, "#66ff33")); + list.add(new VegetationZone("Silberweidenwald", 81, 140, "#008080")); + list.add(new VegetationZone("Weidengebüsch", 141, 200, "#33cccc")); + list.add(new VegetationZone("Uferröhricht", 201, 260, "#ffa8ff")); + list.add(new VegetationZone("Uferpioniere", 261, 320, "#ff0000")); + list.add(new VegetationZone("Vegetationslos", 321, 364, "#b2b2b2")); + list.add(new VegetationZone("Wasserfläche", 365, 365, "#0066ff")); return list; } @@ -96,6 +114,8 @@ builder.append(zone.getMin_day_overflow()); builder.append(TABLE_CELL_SEPARATOR); builder.append(zone.getMax_day_overflow()); + builder.append(TABLE_CELL_SEPARATOR); + builder.append(zone.getHexColor()); builder.append(TABLE_ROW_SEPARATOR); } return builder.toString(); @@ -107,7 +127,72 @@ final int basicCompare = Integer.valueOf(this.getMin_day_overflow()).compareTo(o.getMin_day_overflow()); if (basicCompare == 0) return Integer.valueOf(this.getMax_day_overflow()).compareTo(o.getMax_day_overflow()); // wenn min==min && max==max, alphabetisch sortieren? + + if (basicCompare == 0) { + return 1; // for treeSet + } + return basicCompare; } -} + public static final boolean zonesAreOverlapping(final List list) { + for (final VegetationZone zone : list) { + for (final VegetationZone 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 int lower, final int upper) { + + if ((upper - lower) == 0) + return true; + + final TreeSet treeList = new TreeSet(); + treeList.addAll(list); + int lowerCompare = lower; + for (final VegetationZone zone : treeList) { + if (zone.getLowerFromTo() > (lowerCompare + 1)) { // nicht inklusiv + return true; + } + lowerCompare = zone.getUpperFromTo(); + } + if ((lowerCompare) < upper) + return true; // am Ende nicht geschlossen + + return false; + } + + private boolean overlaps(final VegetationZone otherZone) { + final int otherLower = otherZone.getLowerFromTo(); + final int otherUpper = otherZone.getUpperFromTo(); + + final int upper = getUpperFromTo(); + final int lower = getLowerFromTo(); + final int 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; + } + + public Integer getLowerFromTo() { + return this.min_day_overflow < this.max_day_overflow ? this.min_day_overflow : this.max_day_overflow; // Math. is forbidden :-( + } + + public Integer getUpperFromTo() { + return this.min_day_overflow > this.max_day_overflow ? this.min_day_overflow : this.max_day_overflow;// Math. is forbidden :-( + } + +} \ No newline at end of file