view gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/DistinctValuesNaviChartStepper.java @ 9416:05405292a7ca

Navigationtheme panel now shows themes of dWt and WQ charts grayed out, if the current station is outside the valid range of the theme.
author gernotbelger
date Thu, 16 Aug 2018 16:28:03 +0200
parents abf14917be32
children
line wrap: on
line source
/** 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;
    }
}

http://dive4elements.wald.intevation.org