Mercurial > dive4elements > river
comparison 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 |
comparison
equal
deleted
inserted
replaced
9262:fee5fa18361c | 9263:abf14917be32 |
---|---|
1 /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde | |
2 * Software engineering by | |
3 * Björnsen Beratende Ingenieure GmbH | |
4 * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt | |
5 * | |
6 * This file is Free Software under the GNU AGPL (>=v3) | |
7 * and comes with ABSOLUTELY NO WARRANTY! Check out the | |
8 * documentation coming with Dive4Elements River for details. | |
9 */ | |
10 package org.dive4elements.river.client.client.ui.chart; | |
11 | |
12 import java.util.Set; | |
13 import java.util.SortedSet; | |
14 import java.util.TreeSet; | |
15 | |
16 /** | |
17 * Allows stepping through a list of distinct (known) values. | |
18 * | |
19 * @author Gernot Belger | |
20 */ | |
21 public class DistinctValuesNaviChartStepper implements INaviChartStepper { | |
22 | |
23 private final TreeSet<Double> validSteps = new TreeSet<Double>(); | |
24 | |
25 private double currentKm; | |
26 | |
27 public DistinctValuesNaviChartStepper(final Set<Double> validKms) { | |
28 this.validSteps.addAll(validKms); | |
29 | |
30 if (this.validSteps.isEmpty()) | |
31 this.validSteps.add(-1d); | |
32 | |
33 this.currentKm = this.validSteps.first(); | |
34 } | |
35 | |
36 @Override | |
37 public double getCurrentKm() { | |
38 return this.currentKm; | |
39 } | |
40 | |
41 @Override | |
42 public double stepForward() { | |
43 this.currentKm = calculateStepFormward(); | |
44 return this.currentKm; | |
45 } | |
46 | |
47 private double calculateStepFormward() { | |
48 // REMARK: can't use higher due to gwt bug | |
49 // final Double next = this.validSteps.higher(this.currentKm); | |
50 | |
51 // REMAREK: add a bit, because tailSet is inclusive | |
52 final SortedSet<Double> tailSet = this.validSteps.tailSet(this.currentKm + 1e-6); | |
53 final Double next = tailSet.isEmpty() ? null : tailSet.first(); | |
54 | |
55 if (next != null) | |
56 return next; | |
57 | |
58 return this.validSteps.last(); | |
59 } | |
60 | |
61 @Override | |
62 public double stepBackward() { | |
63 this.currentKm = calculateStepBackward(); | |
64 return this.currentKm; | |
65 } | |
66 | |
67 private double calculateStepBackward() { | |
68 // REMARK: can't use lower due to gwt bug | |
69 // final Double prev = this.validSteps.lower(this.currentKm); | |
70 | |
71 final SortedSet<Double> headSet = this.validSteps.headSet(this.currentKm); | |
72 final Double prev = headSet.isEmpty() ? null : headSet.last(); | |
73 | |
74 if (prev != null) | |
75 return prev; | |
76 | |
77 return this.validSteps.first(); | |
78 } | |
79 | |
80 @Override | |
81 public double setValidCurrentKm(final double currentKm) { | |
82 this.currentKm = calculateValidCurrentKm(currentKm); | |
83 return this.currentKm; | |
84 } | |
85 | |
86 private double calculateValidCurrentKm(final double newKm) { | |
87 | |
88 if (this.validSteps.contains(newKm)) { | |
89 /* special case, and because headSet() is not inclusive */ | |
90 return newKm; | |
91 } | |
92 | |
93 final SortedSet<Double> headSet = this.validSteps.headSet(newKm); | |
94 final SortedSet<Double> tailSet = this.validSteps.tailSet(newKm); | |
95 | |
96 // REMARK: can't use floor/ceiling because of gwt bug | |
97 // final Double floor = this.validSteps.floor(currentKm); | |
98 // final Double ceiling = this.validSteps.ceiling(currentKm); | |
99 final Double floor = headSet.isEmpty() ? null : headSet.last(); | |
100 final Double ceiling = tailSet.isEmpty() ? null : tailSet.first(); | |
101 | |
102 if (floor != null && ceiling == null) | |
103 return floor; | |
104 | |
105 if (floor == null && ceiling != null) | |
106 return ceiling; | |
107 | |
108 if (floor == null && ceiling == null) { | |
109 /* should never happen as validKms is never empty */ | |
110 return this.currentKm; | |
111 } | |
112 | |
113 if (floor == null || ceiling == null) { | |
114 /* will never happen, but makes the NullPointer access checker happy, else we get warnings in the folowing code */ | |
115 return this.currentKm; | |
116 } | |
117 | |
118 /* both not null; find nearest */ | |
119 final double floorDiff = Math.abs(newKm - floor); | |
120 final double ceilingDiff = Math.abs(newKm - ceiling); | |
121 if (floorDiff < ceilingDiff) | |
122 return floor; | |
123 | |
124 return ceiling; | |
125 } | |
126 } |