Mercurial > dive4elements > river
diff gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/DistinctValuesNaviChartStepper.java @ 9263:abf14917be32
Moved stepping behaviour of NaviOutputChart into an exchangeable strategy.
Allows for distinct values stepping of sinfo flood duration.
author | gernotbelger |
---|---|
date | Tue, 17 Jul 2018 19:48:18 +0200 |
parents | |
children |
line wrap: on
line diff
--- /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