NewPipe/app/src/main/java/org/schabi/newpipe/util/SliderStrategy.java

80 lines
3.2 KiB
Java

package org.schabi.newpipe.util;
public interface SliderStrategy {
/**
* Converts from zeroed double with a minimum offset to the nearest rounded slider
* equivalent integer.
*
* @param value the value to convert
* @return the converted value
*/
int progressOf(double value);
/**
* Converts from slider integer value to an equivalent double value with a given
* minimum offset.
*
* @param progress the value to convert
* @return the converted value
*/
double valueOf(int progress);
// TODO: also implement linear strategy when needed
final class Quadratic implements SliderStrategy {
private final double leftGap;
private final double rightGap;
private final double center;
private final int centerProgress;
/**
* Quadratic slider strategy that scales the value of a slider given how far the slider
* progress is from the center of the slider. The further away from the center,
* the faster the interpreted value changes, and vice versa.
*
* @param minimum the minimum value of the interpreted value of the slider.
* @param maximum the maximum value of the interpreted value of the slider.
* @param center center of the interpreted value between the minimum and maximum, which
* will be used as the center value on the slider progress. Doesn't need
* to be the average of the minimum and maximum values, but must be in
* between the two.
* @param maxProgress the maximum possible progress of the slider, this is the
* value that is shown for the UI and controls the granularity of
* the slider. Should be as large as possible to avoid floating
* point round-off error. Using odd number is recommended.
*/
public Quadratic(final double minimum, final double maximum, final double center,
final int maxProgress) {
if (center < minimum || center > maximum) {
throw new IllegalArgumentException("Center must be in between minimum and maximum");
}
this.leftGap = minimum - center;
this.rightGap = maximum - center;
this.center = center;
this.centerProgress = maxProgress / 2;
}
@Override
public int progressOf(final double value) {
final double difference = value - center;
final double root = difference >= 0 ? Math.sqrt(difference / rightGap)
: -Math.sqrt(Math.abs(difference / leftGap));
final double offset = Math.round(root * centerProgress);
return (int) (centerProgress + offset);
}
@Override
public double valueOf(final int progress) {
final int offset = progress - centerProgress;
final double square = Math.pow(((double) offset) / ((double) centerProgress), 2);
final double difference = square * (offset >= 0 ? rightGap : leftGap);
return difference + center;
}
}
}