range preference
This commit is contained in:
parent
d999d8b9df
commit
0ea44527f2
@ -4,22 +4,22 @@ import android.content.Context;
|
|||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.view.widgets.NumberPicker;
|
import org.solovyev.android.view.widgets.AbstractRangeSeekBar;
|
||||||
import org.solovyev.android.view.widgets.RangeSeekBar;
|
import org.solovyev.android.view.widgets.NumberRangeSeekBar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 9/19/11
|
* Date: 9/19/11
|
||||||
* Time: 12:27 PM
|
* Time: 12:27 PM
|
||||||
*/
|
*/
|
||||||
public abstract class RangeSeekPreference<T extends Number> extends AbstractDialogPreference implements RangeSeekBar.OnRangeSeekBarChangeListener<T> {
|
public abstract class RangeSeekPreference<T extends Number> extends AbstractDialogPreference implements AbstractRangeSeekBar.OnRangeSeekBarChangeListener<T> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final RangeSeekBar<T> rangeSeekBar;
|
private final AbstractRangeSeekBar<T> rangeSeekBar;
|
||||||
|
|
||||||
public RangeSeekPreference(@NotNull Context context, AttributeSet attrs) {
|
public RangeSeekPreference(@NotNull Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
this.rangeSeekBar = new RangeSeekBar<T>(getMinValue(), getMaxValue(), context);
|
this.rangeSeekBar = new NumberRangeSeekBar<T>(getMinValue(), getMaxValue(), context);
|
||||||
rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,11 @@ import android.graphics.Paint.Style;
|
|||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
|
import org.solovyev.common.utils.Converter;
|
||||||
import java.math.BigDecimal;
|
import org.solovyev.common.utils.Interval;
|
||||||
|
import org.solovyev.common.utils.IntervalImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Widget that lets users select a minimum and maximum value on a given numerical range.
|
* Widget that lets users select a minimum and maximum value on a given numerical range.
|
||||||
@ -23,7 +25,7 @@ import java.math.BigDecimal;
|
|||||||
* @param <T> The Number type of the range values. One of Long, Double, Integer, Float, Short, Byte or BigDecimal.
|
* @param <T> The Number type of the range values. One of Long, Double, Integer, Float, Short, Byte or BigDecimal.
|
||||||
* @author Stephan Tittel (stephan.tittel@kom.tu-darmstadt.de)
|
* @author Stephan Tittel (stephan.tittel@kom.tu-darmstadt.de)
|
||||||
*/
|
*/
|
||||||
public class RangeSeekBar<T extends Number> extends ImageView {
|
public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Paint paint = new Paint();
|
private final Paint paint = new Paint();
|
||||||
@ -45,17 +47,26 @@ public class RangeSeekBar<T extends Number> extends ImageView {
|
|||||||
private final float padding = thumbHalfWidth;
|
private final float padding = thumbHalfWidth;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final T minValue, maxValue;
|
private final Converter<T, Double> toDoubleConverter;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final NumberType numberType;
|
private final Converter<Double, T> toTConverter;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final T minValue, maxValue;
|
||||||
|
|
||||||
private final double dMinValue, dMaxValue;
|
private final double dMinValue, dMaxValue;
|
||||||
|
|
||||||
private double normalizedMinValue = 0d;
|
private double normalizedMinValue = 0d;
|
||||||
|
|
||||||
private double normalizedMaxValue = 1d;
|
private double normalizedMaxValue = 1d;
|
||||||
|
|
||||||
private Thumb pressedThumb = null;
|
private Thumb pressedThumb = null;
|
||||||
|
|
||||||
private boolean notifyWhileDragging = false;
|
private boolean notifyWhileDragging = false;
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private OnRangeSeekBarChangeListener<T> listener;
|
private OnRangeSeekBarChangeListener<T> listener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,18 +77,25 @@ public class RangeSeekBar<T extends Number> extends ImageView {
|
|||||||
* @param context
|
* @param context
|
||||||
* @throws IllegalArgumentException Will be thrown if min/max value types are not one of Long, Double, Integer, Float, Short, Byte or BigDecimal.
|
* @throws IllegalArgumentException Will be thrown if min/max value types are not one of Long, Double, Integer, Float, Short, Byte or BigDecimal.
|
||||||
*/
|
*/
|
||||||
public RangeSeekBar(@NotNull T minValue, @NotNull T maxValue, Context context) throws IllegalArgumentException {
|
public AbstractRangeSeekBar(@NotNull T minValue, @NotNull T maxValue, Context context) throws IllegalArgumentException {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
this.minValue = minValue;
|
this.minValue = minValue;
|
||||||
this.maxValue = maxValue;
|
this.maxValue = maxValue;
|
||||||
|
|
||||||
dMinValue = minValue.doubleValue();
|
this.toDoubleConverter = getToDoubleConverter();
|
||||||
dMaxValue = maxValue.doubleValue();
|
this.toTConverter = getToTConverter();
|
||||||
|
|
||||||
numberType = NumberType.fromNumber(minValue);
|
dMinValue = toDoubleConverter.convert(minValue);
|
||||||
|
dMaxValue = toDoubleConverter.convert(maxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected abstract Converter<Double,T> getToTConverter();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected abstract Converter<T,Double> getToDoubleConverter();
|
||||||
|
|
||||||
public boolean isNotifyWhileDragging() {
|
public boolean isNotifyWhileDragging() {
|
||||||
return notifyWhileDragging;
|
return notifyWhileDragging;
|
||||||
}
|
}
|
||||||
@ -314,7 +332,7 @@ public class RangeSeekBar<T extends Number> extends ImageView {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private T normalizedToValue(double normalized) {
|
private T normalizedToValue(double normalized) {
|
||||||
return (T) numberType.toNumber(dMinValue + normalized * (dMaxValue - dMinValue));
|
return toTConverter.convert(dMinValue + normalized * (dMaxValue - dMinValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -325,7 +343,7 @@ public class RangeSeekBar<T extends Number> extends ImageView {
|
|||||||
*/
|
*/
|
||||||
private double normalizeValue(T value) {
|
private double normalizeValue(T value) {
|
||||||
assert 0 != dMaxValue - dMinValue;
|
assert 0 != dMaxValue - dMinValue;
|
||||||
return (value.doubleValue() - dMinValue) / (dMaxValue - dMinValue);
|
return (toDoubleConverter.convert(value) - dMinValue) / (dMaxValue - dMinValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -373,61 +391,4 @@ public class RangeSeekBar<T extends Number> extends ImageView {
|
|||||||
private static enum Thumb {
|
private static enum Thumb {
|
||||||
MIN, MAX
|
MIN, MAX
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility enumaration used to convert between Numbers and doubles.
|
|
||||||
*
|
|
||||||
* @author Stephan Tittel (stephan.tittel@kom.tu-darmstadt.de)
|
|
||||||
*/
|
|
||||||
private static enum NumberType {
|
|
||||||
|
|
||||||
LONG(Long.class),
|
|
||||||
DOUBLE(Double.class),
|
|
||||||
INTEGER(Integer.class),
|
|
||||||
FLOAT(Float.class),
|
|
||||||
SHORT(Short.class),
|
|
||||||
BYTE(Byte.class),
|
|
||||||
BIG_DECIMAL(BigDecimal.class);
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final Class underlyingClass;
|
|
||||||
|
|
||||||
private NumberType(@NotNull Class underlyingClass) {
|
|
||||||
this.underlyingClass = underlyingClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static <E extends Number> NumberType fromNumber(E value) throws IllegalArgumentException {
|
|
||||||
|
|
||||||
for (NumberType numberType : NumberType.values()) {
|
|
||||||
if ( numberType.underlyingClass.isInstance(value) ) {
|
|
||||||
return numberType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Number class '" + value.getClass().getName() + "' is not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Number toNumber(double value) {
|
|
||||||
|
|
||||||
switch (this) {
|
|
||||||
case LONG:
|
|
||||||
return (long) value;
|
|
||||||
case DOUBLE:
|
|
||||||
return value;
|
|
||||||
case INTEGER:
|
|
||||||
return (int)value;
|
|
||||||
case FLOAT:
|
|
||||||
return (float)value;
|
|
||||||
case SHORT:
|
|
||||||
return (short)value;
|
|
||||||
case BYTE:
|
|
||||||
return (byte)value;
|
|
||||||
case BIG_DECIMAL:
|
|
||||||
return new BigDecimal(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InstantiationError("can't convert " + this + " to a Number object");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
package org.solovyev.android.view.widgets;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.common.utils.Converter;
|
||||||
|
import org.solovyev.common.utils.Mapper;
|
||||||
|
import org.solovyev.common.utils.NumberValuer;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/19/11
|
||||||
|
* Time: 4:26 PM
|
||||||
|
*/
|
||||||
|
public class NumberRangeSeekBar<T extends Number> extends AbstractRangeSeekBar<T> {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final NumberType numberType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new RangeSeekBar.
|
||||||
|
*
|
||||||
|
* @param minValue The minimum value of the selectable range.
|
||||||
|
* @param maxValue The maximum value of the selectable range.
|
||||||
|
* @param context parent context
|
||||||
|
* @throws IllegalArgumentException Will be thrown if min/max value types are not one of Long, Double, Integer, Float, Short, Byte or BigDecimal.
|
||||||
|
*/
|
||||||
|
public NumberRangeSeekBar(@NotNull T minValue, @NotNull T maxValue, Context context) throws IllegalArgumentException {
|
||||||
|
super(minValue, maxValue, context);
|
||||||
|
|
||||||
|
numberType = NumberType.fromNumber(minValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected Converter<Double, T> getToTConverter() {
|
||||||
|
return new Converter<Double, T>() {
|
||||||
|
@Override
|
||||||
|
public T convert(@NotNull Double aDouble) {
|
||||||
|
return (T) numberType.toNumber(aDouble);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected Converter<T, Double> getToDoubleConverter() {
|
||||||
|
return new NumberValuer<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility enumeration used to convert between Numbers and doubles.
|
||||||
|
*
|
||||||
|
* @author Stephan Tittel (stephan.tittel@kom.tu-darmstadt.de)
|
||||||
|
*/
|
||||||
|
private static enum NumberType {
|
||||||
|
|
||||||
|
LONG(Long.class),
|
||||||
|
DOUBLE(Double.class),
|
||||||
|
INTEGER(Integer.class),
|
||||||
|
FLOAT(Float.class),
|
||||||
|
SHORT(Short.class),
|
||||||
|
BYTE(Byte.class),
|
||||||
|
BIG_DECIMAL(BigDecimal.class);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Class underlyingClass;
|
||||||
|
|
||||||
|
private NumberType(@NotNull Class underlyingClass) {
|
||||||
|
this.underlyingClass = underlyingClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static <E extends Number> NumberType fromNumber(E value) throws IllegalArgumentException {
|
||||||
|
|
||||||
|
for (NumberType numberType : NumberType.values()) {
|
||||||
|
if (numberType.underlyingClass.isInstance(value)) {
|
||||||
|
return numberType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("Number class '" + value.getClass().getName() + "' is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends Number> T toNumber(double value) {
|
||||||
|
|
||||||
|
switch (this) {
|
||||||
|
case LONG:
|
||||||
|
return (T)new Long((long) value);
|
||||||
|
case DOUBLE:
|
||||||
|
return (T)new Double(value);
|
||||||
|
case INTEGER:
|
||||||
|
return (T)new Integer((int) value);
|
||||||
|
case FLOAT:
|
||||||
|
return (T)new Float((float) value);
|
||||||
|
case SHORT:
|
||||||
|
return (T)new Short((short) value);
|
||||||
|
case BYTE:
|
||||||
|
return (T)new Byte((byte) value);
|
||||||
|
case BIG_DECIMAL:
|
||||||
|
return (T)new BigDecimal(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InstantiationError("can't convert " + this + " to a Number object");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user