Mercurial > dive4elements > river
changeset 9263:abf14917be32
Moved stepping behaviour of NaviOutputChart into an exchangeable strategy.
Allows for distinct values stepping of sinfo flood duration.
line wrap: on
line diff
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/CollectionView.java Tue Jul 17 19:48:09 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/CollectionView.java Tue Jul 17 19:48:18 2018 +0200 @@ -28,8 +28,6 @@ import org.dive4elements.river.client.client.event.ParameterChangeHandler; import org.dive4elements.river.client.client.services.AddArtifactService; import org.dive4elements.river.client.client.services.AddArtifactServiceAsync; -import org.dive4elements.river.client.client.services.ArtifactService; -import org.dive4elements.river.client.client.services.ArtifactServiceAsync; import org.dive4elements.river.client.client.services.CollectionAttributeService; import org.dive4elements.river.client.client.services.CollectionAttributeServiceAsync; import org.dive4elements.river.client.client.services.CreateCollectionService; @@ -62,64 +60,58 @@ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public class CollectionView extends Window implements CollectionChangeHandler, HasCollectionChangeHandlers, OutputModesChangeHandler, HasOutputModesChangeHandlers, ParameterChangeHandler, CloseClickHandler { - /** The ArtifactService used to communicate with the Artifact server. */ - protected CreateCollectionServiceAsync createCollectionService = GWT.create(CreateCollectionService.class); + + /** The message class that provides i18n strings. */ + private static final FLYSConstants messages = GWT.create(FLYSConstants.class); /** The ArtifactService used to communicate with the Artifact server. */ - protected ArtifactServiceAsync createArtifactService = GWT.create(ArtifactService.class); + private final CreateCollectionServiceAsync createCollectionService = GWT.create(CreateCollectionService.class); /** The AddArtifactService used to add an artifact to a collection. */ - protected AddArtifactServiceAsync addArtifactService = GWT.create(AddArtifactService.class); + private final AddArtifactServiceAsync addArtifactService = GWT.create(AddArtifactService.class); /** The DescribeCollectionService used to update the existing collection. */ - protected DescribeCollectionServiceAsync describeCollectionService = GWT.create(DescribeCollectionService.class); + private final DescribeCollectionServiceAsync describeCollectionService = GWT.create(DescribeCollectionService.class); - protected CollectionAttributeServiceAsync updater = GWT.create(CollectionAttributeService.class); + private final CollectionAttributeServiceAsync updater = GWT.create(CollectionAttributeService.class); /** The LoadArtifactService used to load recommendations */ - protected LoadArtifactServiceAsync loadArtifactService = GWT.create(LoadArtifactService.class); - - /** The message class that provides i18n strings. */ - protected FLYSConstants messages = GWT.create(FLYSConstants.class); + private final LoadArtifactServiceAsync loadArtifactService = GWT.create(LoadArtifactService.class); /** The FLYS instance used to call services. */ - protected FLYS flys; + private final FLYS flys; /** The ParameterList. */ - protected ParameterList parameterList; + private ParameterList parameterList; /** The list of CollectionChangeHandlers. */ - protected List<CollectionChangeHandler> handlers; + private final List<CollectionChangeHandler> handlers; /** The list of OutputModesChangeHandlers. */ - protected List<OutputModesChangeHandler> outHandlers; + private final List<OutputModesChangeHandler> outHandlers; /** The collection to be displayed. */ - protected Collection collection; + private Collection collection; /** The artifact that handles the parameterization. */ - protected Artifact artifact; + private Artifact artifact; - protected TabSet tabs; + private final TabSet tabs; /** The output tab. */ - protected Map<String, OutputTab> outputTabs; + private final Map<String, OutputTab> outputTabs; /** The layout. */ - protected Layout layout; + private final Layout layout; /** Layout to show spinning wheel of joy. */ - protected VLayout lockScreen; + private VLayout lockScreen; - protected int artifactsQueue; - protected int recommendationQueue; - protected Stack<Recommendation> newRecommendations; + private final int artifactsQueue; + private final Stack<Recommendation> newRecommendations; /** Values for fix analysis charts */ - protected double currentKm; - protected double minKm; - protected double maxKm; - protected double steps; + private double currentKm; /** * This constructor creates a new CollectionView that is used to display the @@ -132,15 +124,11 @@ this.handlers = new ArrayList<CollectionChangeHandler>(); this.outHandlers = new ArrayList<OutputModesChangeHandler>(); this.layout = new VLayout(); - this.parameterList = new ParameterList(flys, this, this.messages.new_project()); + this.parameterList = new ParameterList(flys, this, CollectionView.messages.new_project()); this.artifactsQueue = 0; - this.recommendationQueue = 0; this.newRecommendations = new Stack<Recommendation>(); this.currentKm = -1d; - this.minKm = -1d; - this.maxKm = -1d; - this.steps = -1d; addCollectionChangeHandler(this); addCollectionChangeHandler(this.parameterList); @@ -169,9 +157,6 @@ this.layout = new VLayout(); this.currentKm = -1d; - this.minKm = -1d; - this.maxKm = -1d; - this.steps = -1d; if (artifact != null) { this.parameterList = new ParameterList(flys, this, @@ -179,9 +164,9 @@ // but... the international name is resolved client-side.... Instead also transport the description of the artifact and // use it! // FIXME: the same holds for a very few other international strings (e.g. names of facets used in Tabs) - this.messages.getString(artifact.getName()), artifact); + CollectionView.messages.getString(artifact.getName()), artifact); } else { - this.parameterList = new ParameterList(flys, this, this.messages.new_project()); + this.parameterList = new ParameterList(flys, this, CollectionView.messages.new_project()); } this.artifactsQueue = 0; @@ -208,7 +193,7 @@ /** * This method handles the initial layout stuff. */ - protected void init() { + private void init() { setWidth(1010); setHeight(700); @@ -229,7 +214,7 @@ this.tabs.addTab(this.parameterList); } - protected FLYS getFlys() { + private FLYS getFlys() { return this.flys; } @@ -263,13 +248,13 @@ * This method calls the <code>onValueChange()</code> method of all * registered ValueChangeHanders. */ - protected void fireCollectionChangeEvent(final Collection old, final Collection newCol) { + private void fireCollectionChangeEvent(final Collection old, final Collection newCol) { for (final CollectionChangeHandler handler : this.handlers) { handler.onCollectionChange(new CollectionChangeEvent(old, newCol)); } } - protected void fireOutputModesChangeEvent(final OutputMode[] outputs) { + private void fireOutputModesChangeEvent(final OutputMode[] outputs) { if (this.collection == null) { return; } @@ -290,16 +275,6 @@ } /** - * This method returns true, if the Collection is new and no plugins has - * been chosen. - * - * @return true, if the Collection is new. - */ - public boolean isNew() { - return this.collection.hasItems(); - } - - /** * Returns the artifact that is used for the parameterization. * * @return the artifact that is used for the parameterization. @@ -321,10 +296,6 @@ public void setArtifact(final Artifact artifact) { this.artifact = artifact; - onArtifactChanged(artifact); - } - - public void onArtifactChanged(final Artifact artifact) { artifactChanged(); if (artifact.isInBackground()) { @@ -346,7 +317,7 @@ setArtifact(event.getNewValue()); } - protected void artifactChanged() { + private void artifactChanged() { final Collection c = getCollection(); if (c != null) { @@ -359,15 +330,14 @@ /** * Loads all information of a collection. * If 'recommendations' present, load these. - * + * * @param c * the Collection */ private void loadCollection(final Collection c) { final ArtifactDescription desc = getArtifact().getArtifactDescription(); final Recommendation[] recom = desc.getRecommendations(); - final Config config = Config.getInstance(); - final String locale = config.getLocale(); + final String locale = Config.getInstance().getLocale(); this.describeCollectionService.describe(c.identifier(), locale, new AsyncCallback<Collection>() { @Override @@ -403,7 +373,7 @@ return this.collection; } - protected void setCollection(final Collection collection) { + private void setCollection(final Collection collection) { setCollection(collection, false); } @@ -415,7 +385,7 @@ * @param suppress * Whether to fire a collectionchangeevent. */ - protected void setCollection(final Collection collection, final boolean suppress) { + public void setCollection(final Collection collection, final boolean suppress) { if (collection != null && this.collection == null) { this.flys.getWorkspace().addView(collection.identifier(), this); } @@ -423,11 +393,11 @@ final Collection tmp = this.collection; this.collection = collection; - setTitle(collection.getDisplayName()); + if (collection != null) + setTitle(collection.getDisplayName()); - if (!suppress) { + if (!suppress) fireCollectionChangeEvent(tmp, this.collection); - } } @Override @@ -488,7 +458,7 @@ * @param name * The name and title of the output. */ - protected void addOutputTab(final String name, final OutputMode out) { + private void addOutputTab(final String name, final OutputMode out) { if (out instanceof ExportMode) { final ExportMode export = (ExportMode) out; @@ -509,18 +479,17 @@ GWT.log("Add new output tab for '" + name + "'"); - final String title = this.messages.getString(name); + final String title = CollectionView.messages.getString(name); final OutputTab tab = out.createOutputTab(title, getCollection(), this); - if (tab != null) { + if (tab != null) this.outputTabs.put(name, tab); - } } /** * Removes all output mode tabs from tab bar. */ - protected void clearOutputTabs() { + private void clearOutputTabs() { GWT.log("Clear OutputTabs."); final int num = this.tabs.getNumTabs(); @@ -535,7 +504,7 @@ /** * Update the view (refresh the list of old and current data). */ - protected void updateView() { + private void updateView() { GWT.log("CollectionView.updateView()"); updateOutputTabs(); } @@ -543,7 +512,7 @@ /** * This method is used to update the tabs to show specific output modes. */ - protected void updateOutputTabs() { + private void updateOutputTabs() { GWT.log("Update output tabs."); if (this.outputTabs != null) { final Set<String> keys = this.outputTabs.keySet(); @@ -569,14 +538,12 @@ } public void addArtifactToCollection(final Artifact artifact) { - final Config config = Config.getInstance(); - final String locale = config.getLocale(); - final Collection collection = getCollection(); + final String locale = Config.getInstance().getLocale(); - GWT.log("CollectionView.addArtifactToCollection " + collection); + GWT.log("CollectionView.addArtifactToCollection " + this.collection); - if (collection != null) { - this.addArtifactService.add(collection, artifact, locale, new AsyncCallback<Collection>() { + if (this.collection != null) { + this.addArtifactService.add(this.collection, artifact, locale, new AsyncCallback<Collection>() { @Override public void onFailure(final Throwable caught) { GWT.log("An error occured while adding artifact."); @@ -596,7 +563,7 @@ @Override public void onFailure(final Throwable caught) { GWT.log("Could not create the new collection."); - SC.warn(FLYS.getExceptionString(CollectionView.this.messages, caught)); + SC.warn(FLYS.getExceptionString(CollectionView.messages, caught)); } @Override @@ -620,18 +587,16 @@ } } - protected void addRecommendationsToCollection() { - final Config config = Config.getInstance(); - final String locale = config.getLocale(); - final Collection collection = getCollection(); + private void addRecommendationsToCollection() { + final String locale = Config.getInstance().getLocale(); - collection.addRecommendations(this.newRecommendations); + this.collection.addRecommendations(this.newRecommendations); - this.updater.update(collection, locale, new AsyncCallback<Collection>() { + this.updater.update(this.collection, locale, new AsyncCallback<Collection>() { @Override public void onFailure(final Throwable caught) { CollectionView.this.newRecommendations.removeAllElements(); - setCollection(collection); + setCollection(CollectionView.this.collection); GWT.log("An error occured while saving recommendations."); SC.warn(FLYS.getExceptionString(CollectionView.this.messages, caught)); @@ -646,10 +611,8 @@ }); } - protected void loadRecommendedArtifacts(final Recommendation[] recommendations) { - final Config config = Config.getInstance(); - final String locale = config.getLocale(); - final Collection collection = getCollection(); + private void loadRecommendedArtifacts(final Recommendation[] recommendations) { + final String locale = Config.getInstance().getLocale(); final Artifact masterArtifact = getArtifact(); @@ -659,7 +622,7 @@ } for (final Recommendation recommendation : recommendations) { - if (collection.loadedRecommendation(recommendation)) { + if (this.collection.loadedRecommendation(recommendation)) { continue; } this.newRecommendations.push(recommendation); @@ -672,11 +635,11 @@ } - this.loadArtifactService.loadMany(collection, recommendations, null, locale, new AsyncCallback<Artifact[]>() { + this.loadArtifactService.loadMany(this.collection, recommendations, null, locale, new AsyncCallback<Artifact[]>() { @Override public void onFailure(final Throwable caught) { GWT.log("Error loading recommendations: " + caught.getMessage()); - SC.warn(FLYS.getExceptionString(CollectionView.this.messages, caught)); + SC.warn(FLYS.getExceptionString(CollectionView.messages, caught)); } @Override @@ -698,29 +661,4 @@ public double getCurrentKm() { return this.currentKm; } - - public void setMinKm(final double km) { - this.minKm = km; - } - - public double getMinKm() { - return this.minKm; - } - - public void setMaxKm(final double km) { - this.maxKm = km; - } - - public double getMaxKm() { - return this.maxKm; - } - - public void setSteps(final double step) { - this.steps = step; - } - - public double getSteps() { - return this.steps; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/DistinctValuesNaviChartStepper.java Tue Jul 17 19:48:18 2018 +0200 @@ -0,0 +1,126 @@ +/** 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.chart; + +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * Allows stepping through a list of distinct (known) values. + * + * @author Gernot Belger + */ +public class DistinctValuesNaviChartStepper implements INaviChartStepper { + + private final TreeSet<Double> validSteps = new TreeSet<Double>(); + + private double currentKm; + + public DistinctValuesNaviChartStepper(final Set<Double> validKms) { + this.validSteps.addAll(validKms); + + if (this.validSteps.isEmpty()) + this.validSteps.add(-1d); + + this.currentKm = this.validSteps.first(); + } + + @Override + public double getCurrentKm() { + return this.currentKm; + } + + @Override + public double stepForward() { + this.currentKm = calculateStepFormward(); + return this.currentKm; + } + + private double calculateStepFormward() { + // REMARK: can't use higher due to gwt bug + // final Double next = this.validSteps.higher(this.currentKm); + + // REMAREK: add a bit, because tailSet is inclusive + final SortedSet<Double> tailSet = this.validSteps.tailSet(this.currentKm + 1e-6); + final Double next = tailSet.isEmpty() ? null : tailSet.first(); + + if (next != null) + return next; + + return this.validSteps.last(); + } + + @Override + public double stepBackward() { + this.currentKm = calculateStepBackward(); + return this.currentKm; + } + + private double calculateStepBackward() { + // REMARK: can't use lower due to gwt bug + // final Double prev = this.validSteps.lower(this.currentKm); + + final SortedSet<Double> headSet = this.validSteps.headSet(this.currentKm); + final Double prev = headSet.isEmpty() ? null : headSet.last(); + + if (prev != null) + return prev; + + return this.validSteps.first(); + } + + @Override + public double setValidCurrentKm(final double currentKm) { + this.currentKm = calculateValidCurrentKm(currentKm); + return this.currentKm; + } + + private double calculateValidCurrentKm(final double newKm) { + + if (this.validSteps.contains(newKm)) { + /* special case, and because headSet() is not inclusive */ + return newKm; + } + + final SortedSet<Double> headSet = this.validSteps.headSet(newKm); + final SortedSet<Double> tailSet = this.validSteps.tailSet(newKm); + + // REMARK: can't use floor/ceiling because of gwt bug + // final Double floor = this.validSteps.floor(currentKm); + // final Double ceiling = this.validSteps.ceiling(currentKm); + final Double floor = headSet.isEmpty() ? null : headSet.last(); + final Double ceiling = tailSet.isEmpty() ? null : tailSet.first(); + + if (floor != null && ceiling == null) + return floor; + + if (floor == null && ceiling != null) + return ceiling; + + if (floor == null && ceiling == null) { + /* should never happen as validKms is never empty */ + return this.currentKm; + } + + if (floor == null || ceiling == null) { + /* will never happen, but makes the NullPointer access checker happy, else we get warnings in the folowing code */ + return this.currentKm; + } + + /* both not null; find nearest */ + final double floorDiff = Math.abs(newKm - floor); + final double ceilingDiff = Math.abs(newKm - ceiling); + if (floorDiff < ceilingDiff) + return floor; + + return ceiling; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/INaviChartStepper.java Tue Jul 17 19:48:18 2018 +0200 @@ -0,0 +1,25 @@ +/** 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.chart; + +/** + * Abstraction for stepping through the navi chart. + * + * @author Gernot Belger + */ +public interface INaviChartStepper { + double getCurrentKm(); + + double stepForward(); + + double stepBackward(); + + double setValidCurrentKm(double userInput); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/MinMaxStepNaviChartStepper.java Tue Jul 17 19:48:18 2018 +0200 @@ -0,0 +1,80 @@ +/** 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.chart; + +/** + * 'Old' stepping behaviour of the navi chart, as used by WINFO and Fixierungsanalyse. + * + * @author Gernot Belger + */ +public class MinMaxStepNaviChartStepper implements INaviChartStepper { + + private double currentKm; + private final double minKm; + private final double maxKm; + private final double step; + + public MinMaxStepNaviChartStepper(final double minKm, final double maxKm, final double step) { + this.minKm = minKm; + this.maxKm = maxKm; + this.step = step; + + this.currentKm = minKm; + } + + @Override + public double getCurrentKm() { + return this.currentKm; + } + + @Override + public double stepForward() { + + if (this.currentKm >= this.maxKm) + this.currentKm = this.maxKm; + else { + // Why this math? + double newVal = this.currentKm * 100; + newVal += this.step / 10; + this.currentKm = (double) Math.round(newVal) / 100; + } + + return this.currentKm; + } + + @Override + public double stepBackward() { + + if (this.currentKm <= this.minKm) + this.currentKm = this.minKm; + else { + // Why this math? + double newVal = this.currentKm * 100; + newVal -= this.step / 10; + + this.currentKm = ((double) Math.round(newVal) / 100); + } + + return this.currentKm; + } + + @Override + public double setValidCurrentKm(final double userInput) { + + if (userInput > this.maxKm) + this.currentKm = this.maxKm; + else if (userInput < this.minKm) + this.currentKm = this.minKm; + else + this.currentKm = userInput; + + return this.currentKm; + } +} \ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NaviChartOutputTab.java Tue Jul 17 19:48:09 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NaviChartOutputTab.java Tue Jul 17 19:48:18 2018 +0200 @@ -11,18 +11,22 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.Set; import org.dive4elements.river.client.client.Config; import org.dive4elements.river.client.client.ui.CollectionView; import org.dive4elements.river.client.shared.model.AbstractFixBunduArtifact; import org.dive4elements.river.client.shared.model.Artifact; import org.dive4elements.river.client.shared.model.Collection; +import org.dive4elements.river.client.shared.model.CollectionItem; import org.dive4elements.river.client.shared.model.FixFilter; import org.dive4elements.river.client.shared.model.OutputMode; +import org.dive4elements.river.client.shared.model.SINFOArtifact; import com.google.gwt.core.client.GWT; import com.google.gwt.i18n.client.NumberFormat; 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; @@ -42,10 +46,17 @@ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public class NaviChartOutputTab extends ChartOutputTab implements TabSelectedHandler { - protected TextItem currentkm; + private TextItem currentkm; + + private final NumberFormat kmFormat = NumberFormat.getDecimalFormat(); + + private INaviChartStepper stepper; public NaviChartOutputTab(final String title, final Collection collection, final OutputMode mode, final CollectionView collectionView) { super(title, collection, mode, collectionView); + + this.stepper = new NilNaviChartStepper(); + this.right.removeChild(this.chart); this.right.addChild(createNaviChart()); collectionView.registerTabHandler(this); @@ -72,121 +83,37 @@ form.setFields(this.currentkm); form.setWidth(60); - double fromKm; - double toKm; - - if (art instanceof AbstractFixBunduArtifact) { - final AbstractFixBunduArtifact fix = (AbstractFixBunduArtifact) art; - final FixFilter fixFilter = fix.getFilter(); - final String s = fix.getArtifactDescription().getDataValueAsString("ld_step"); - try { - final double ds = Double.parseDouble(s); - this.collectionView.setSteps(ds); - } - catch (final NumberFormatException nfe) { - this.collectionView.setSteps(100d); - } - fromKm = fixFilter.getLowerKm(); - toKm = fixFilter.getUpperKm(); - } else { - // Probably WINFOArtifact kind of artifact. - final String ld_step = art.getArtifactDescription().getDataValueAsString("ld_step"); - try { - this.collectionView.setSteps(Double.valueOf(ld_step)); - } - catch (final Exception e) { - GWT.log("No ld_steps data or not parsable."); - return root; - } - - final double[] kmRange = art.getArtifactDescription().getKMRange(); - if (kmRange == null || kmRange.length == 2) { - fromKm = kmRange[0]; - toKm = kmRange[1]; - } else { - GWT.log("No KM range in description found."); - return root; - } - } - - this.collectionView.setMinKm(fromKm); - this.collectionView.setMaxKm(toKm); - - final NumberFormat nf = NumberFormat.getDecimalFormat(); + this.stepper = createStepper(art); // Always jump to the from km when initialized. - try { - final double d = Double.valueOf(fromKm); - this.currentkm.setValue(nf.format(d)); - } - catch (final NumberFormatException e) { - this.currentkm.setValue(fromKm); - } - this.collectionView.setCurrentKm(fromKm); + final double currentKm = this.stepper.getCurrentKm(); + this.collectionView.setCurrentKm(currentKm); + this.currentkm.setValue(this.kmFormat.format(currentKm)); lower.addClickHandler(new ClickHandler() { @Override public void onClick(final ClickEvent ce) { - NaviChartOutputTab.this.tbarPanel.deselectControls(); updateChartDown(); - try { - final double d = Double.valueOf(NaviChartOutputTab.this.collectionView.getCurrentKm()); - NaviChartOutputTab.this.currentkm.setValue(nf.format(d)); - NaviChartOutputTab.this.tbarPanel.onZoom(null); - } - catch (final NumberFormatException e) { - NaviChartOutputTab.this.currentkm.setValue(NaviChartOutputTab.this.collectionView.getCurrentKm()); - } } }); upper.addClickHandler(new ClickHandler() { @Override public void onClick(final ClickEvent ce) { - NaviChartOutputTab.this.tbarPanel.deselectControls(); updateChartUp(); - try { - final double d = Double.valueOf(NaviChartOutputTab.this.collectionView.getCurrentKm()); - NaviChartOutputTab.this.currentkm.setValue(nf.format(d)); - NaviChartOutputTab.this.tbarPanel.onZoom(null); - } - catch (final NumberFormatException e) { - NaviChartOutputTab.this.currentkm.setValue(NaviChartOutputTab.this.collectionView.getCurrentKm()); - } } }); this.currentkm.addKeyPressHandler(new KeyPressHandler() { @Override public void onKeyPress(final KeyPressEvent kpe) { - if (!kpe.getKeyName().equals("Enter")) { + + if (!kpe.getKeyName().equals("Enter")) return; - } + if (kpe.getItem().getValue() != null) { - NaviChartOutputTab.this.tbarPanel.deselectControls(); - try { - final String s = kpe.getItem().getValue().toString(); - double d; - try { - d = nf.parse(s); - NaviChartOutputTab.this.currentkm.setValue(nf.format(d)); - } - catch (final NumberFormatException e) { - d = -1d; - } - if (d <= NaviChartOutputTab.this.collectionView.getMaxKm() && d >= NaviChartOutputTab.this.collectionView.getMinKm()) { - NaviChartOutputTab.this.collectionView.setCurrentKm(d); - NaviChartOutputTab.this.tbarPanel.updateLinks(); - NaviChartOutputTab.this.tbarPanel.onZoom(null); - if (NaviChartOutputTab.this.right != null) { - updateChartPanel(); - updateChartInfo(); - } - } - } - catch (final NumberFormatException nfe) { - // Do nothing. - } + final String kmText = kpe.getItem().getValue().toString(); + updateChartKm(kmText); } } }); @@ -199,21 +126,84 @@ return root; } + private INaviChartStepper createStepper(final Artifact art) { + + if (art instanceof AbstractFixBunduArtifact) { + final AbstractFixBunduArtifact fix = (AbstractFixBunduArtifact) art; + final FixFilter fixFilter = fix.getFilter(); + + final double fromKm = fixFilter.getLowerKm(); + final double toKm = fixFilter.getUpperKm(); + + final String s = fix.getArtifactDescription().getDataValueAsString("ld_step"); + try { + final double ds = Double.parseDouble(s); + return new MinMaxStepNaviChartStepper(fromKm, toKm, ds); + } + catch (final NumberFormatException nfe) { + return new MinMaxStepNaviChartStepper(fromKm, toKm, 100d); + } + } else if (art instanceof SINFOArtifact) { + /* special case for SINFO-Flood-Duration */ + final SINFOArtifact sinfo = (SINFOArtifact) art; + + final CollectionItem item = this.collection.getItem(sinfo.getUuid()); + + final Set<Double> validKms = sinfo.getValidDurationChartKms(item); + return new DistinctValuesNaviChartStepper(validKms); + } else { + // Probably WINFOArtifact kind of artifact. + + double fromKm; + double toKm; + + final double[] kmRange = art.getArtifactDescription().getKMRange(); + if (kmRange != null && kmRange.length == 2) { + fromKm = kmRange[0]; + toKm = kmRange[1]; + } else { + GWT.log("No KM range in description found."); + return new NilNaviChartStepper(); + } + + final String ld_step = art.getArtifactDescription().getDataValueAsString("ld_step"); + try { + final Double step = Double.valueOf(ld_step); + return new MinMaxStepNaviChartStepper(fromKm, toKm, step); + } + catch (final Exception e) { + GWT.log("No ld_steps data or not parsable.", e); + return new MinMaxStepNaviChartStepper(fromKm, toKm, 100d); + } + } + } + + protected void updateChartKm(final String kmText) { + + NaviChartOutputTab.this.tbarPanel.deselectControls(); + + try { + final double d = this.kmFormat.parse(kmText); + + final double validCurrentKm = this.stepper.setValidCurrentKm(d); + updateCurrentKm(validCurrentKm); + } + catch (final NumberFormatException e) { + SC.warn("Invalid value: " + kmText); + // do nothing, but an error message would be nice + } + } + /** * Callback when km-up-button is clicked. * Increases collectionViews KM and refreshes view. */ protected void updateChartUp() { - final double currentKm = this.collectionView.getCurrentKm(); - if (currentKm < this.collectionView.getMaxKm()) { - // Why this math? - double newVal = currentKm * 100; - newVal += (this.collectionView.getSteps() / 10); - this.collectionView.setCurrentKm((double) Math.round(newVal) / 100); - this.tbarPanel.updateLinks(); - updateChartPanel(); - updateChartInfo(); - } + + this.tbarPanel.deselectControls(); + + final double nextKm = this.stepper.stepForward(); + updateCurrentKm(nextKm); } /** @@ -221,16 +211,24 @@ * Decreases collectionViews KM and refreshes view. */ protected void updateChartDown() { - final double currentKm = this.collectionView.getCurrentKm(); - if (currentKm > this.collectionView.getMinKm()) { - // Why this math? - double newVal = currentKm * 100; - newVal -= (this.collectionView.getSteps() / 10); - this.collectionView.setCurrentKm((double) Math.round(newVal) / 100); - this.tbarPanel.updateLinks(); - updateChartPanel(); - updateChartInfo(); - } + + this.tbarPanel.deselectControls(); + + final double prevKm = this.stepper.stepBackward(); + updateCurrentKm(prevKm); + } + + private void updateCurrentKm(final double currentKm) { + + this.collectionView.setCurrentKm(currentKm); + + this.tbarPanel.updateLinks(); + + updateChartPanel(); + updateChartInfo(); + + this.currentkm.setValue(this.kmFormat.format(currentKm)); + this.tbarPanel.onZoom(null); } @@ -289,14 +287,17 @@ } } - if (this.collectionView.getArtifact() instanceof AbstractFixBunduArtifact) { - if (this.collectionView.getCurrentKm() == -1) { + if (this.collectionView.getCurrentKm() == -1) { + // REMARK: this happens, because we get called from the constructor of our super class + + if (this.collectionView.getArtifact() instanceof AbstractFixBunduArtifact) { final AbstractFixBunduArtifact fix = (AbstractFixBunduArtifact) this.collectionView.getArtifact(); this.collectionView.setCurrentKm(fix.getFilter().getLowerKm()); } - } else if (this.collectionView.getCurrentKm() == -1) { - this.collectionView.setCurrentKm(this.collectionView.getArtifact().getArtifactDescription().getKMRange()[0]); + else + this.collectionView.setCurrentKm(this.collectionView.getArtifact().getArtifactDescription().getKMRange()[0]); } + if (this.collectionView.getCurrentKm() != -1) { imgUrl += "¤tKm=" + this.collectionView.getCurrentKm(); } @@ -307,9 +308,11 @@ @Override public void onTabSelected(final TabSelectedEvent tse) { if (this.equals(tse.getTab())) { - updateChartPanel(); - updateChartInfo(); - this.currentkm.setValue(this.collectionView.getCurrentKm()); + + final double currentKm = this.collectionView.getCurrentKm(); + + final double validCurrentKm = this.stepper.setValidCurrentKm(currentKm); + updateCurrentKm(validCurrentKm); } } @@ -335,5 +338,4 @@ } return url; } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NilNaviChartStepper.java Tue Jul 17 19:48:18 2018 +0200 @@ -0,0 +1,38 @@ +/** 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.chart; + +/** + * Nil implementation that always return 0 as current station. + * + * @author Gernot Belger + */ +public class NilNaviChartStepper implements INaviChartStepper { + + @Override + public double getCurrentKm() { + return 0; + } + + @Override + public double stepForward() { + return 0; + } + + @Override + public double stepBackward() { + return 0; + } + + @Override + public double setValidCurrentKm(final double userInput) { + return 0; + } +} \ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ChartMode.java Tue Jul 17 19:48:09 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ChartMode.java Tue Jul 17 19:48:18 2018 +0200 @@ -49,7 +49,8 @@ this.getName().equals("extreme_wq_curve") || this.getName().equals("fix_deltawt_curve") || this.getName().equals("fix_derivate_curve") || - this.getName().equals("fix_vollmer_wq_curve")){ + this.getName().equals("fix_vollmer_wq_curve") || + this.getName().equals("sinfo_floodduration_curve")){ return new NaviChartOutputTab(t, c, this, p); } return new ChartOutputTab(t, c, this, p);
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/SINFOArtifact.java Tue Jul 17 19:48:09 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/SINFOArtifact.java Tue Jul 17 19:48:18 2018 +0200 @@ -8,8 +8,10 @@ package org.dive4elements.river.client.shared.model; +import java.util.Collections; +import java.util.HashSet; import java.util.List; - +import java.util.Set; /** * The SINFO implementation of an Artifact. @@ -18,29 +20,43 @@ */ public class SINFOArtifact extends DefaultArtifact { - /** The name of this artifact: 'sinfo'.*/ + /** The name of this artifact: 'sinfo'. */ private static final String NAME = "sinfo"; /** Necessary for serialization */ public SINFOArtifact() { } -// public SINFOArtifact(String uuid, String hash) { -// super(uuid, hash); -// } - - public SINFOArtifact( - String uuid, - String hash, - boolean inBackground, - List<CalculationMessage> messages - ) { + public SINFOArtifact(final String uuid, final String hash, final boolean inBackground, final List<CalculationMessage> messages) { super(uuid, hash, inBackground, messages); } - + @Override public String getName() { return NAME; } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : + + public Set<Double> getValidDurationChartKms(final CollectionItem item) { + + final String validKmsText = item.getData().get("validStations"); + if (validKmsText == null || validKmsText.trim().isEmpty()) + return Collections.emptySet(); + + final String[] split = validKmsText.split(","); + + final Set<Double> validKms = new HashSet<Double>(split.length); + + for (final String stationText : split) { + + try { + final double station = Double.parseDouble(stationText); + validKms.add(station); + } + catch (final NumberFormatException e) { + e.printStackTrace(); + } + } + + return validKms; + } +} \ No newline at end of file