fixes
This commit is contained in:
parent
ce416f56e0
commit
7921c09f45
@ -7,5 +7,7 @@
|
|||||||
|
|
||||||
<declare-styleable name="NumberRangeSeekBar">
|
<declare-styleable name="NumberRangeSeekBar">
|
||||||
<attr name="boundaries" format="string"/>
|
<attr name="boundaries" format="string"/>
|
||||||
|
<attr name="steps" format="integer"/>
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
a:title="Distance of drag event"
|
a:title="Distance of drag event"
|
||||||
a:text=" pxs"
|
a:text=" pxs"
|
||||||
a:defaultValue="15;350"
|
a:defaultValue="15;350"
|
||||||
|
range:steps="10"
|
||||||
range:boundaries="10;500"/>
|
range:boundaries="10;500"/>
|
||||||
|
|
||||||
<org.solovyev.android.view.prefs.FloatRangeSeekBarPreference
|
<org.solovyev.android.view.prefs.FloatRangeSeekBarPreference
|
||||||
@ -25,6 +26,7 @@
|
|||||||
a:title="Duration of drag event"
|
a:title="Duration of drag event"
|
||||||
a:text=" ms"
|
a:text=" ms"
|
||||||
a:defaultValue="40;2500"
|
a:defaultValue="40;2500"
|
||||||
|
range:steps="10"
|
||||||
range:boundaries="5;4000"/>
|
range:boundaries="5;4000"/>
|
||||||
|
|
||||||
<org.solovyev.android.view.prefs.FloatRangeSeekBarPreference
|
<org.solovyev.android.view.prefs.FloatRangeSeekBarPreference
|
||||||
@ -32,6 +34,7 @@
|
|||||||
a:title="Angle of drag event"
|
a:title="Angle of drag event"
|
||||||
a:text=" degrees"
|
a:text=" degrees"
|
||||||
a:defaultValue="0;45"
|
a:defaultValue="0;45"
|
||||||
|
range:steps="5"
|
||||||
range:boundaries="0;45"/>
|
range:boundaries="0;45"/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
@ -8,6 +8,7 @@ package org.solovyev.android.calculator;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.text.ClipboardManager;
|
import android.text.ClipboardManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
@ -102,6 +103,8 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
};
|
};
|
||||||
|
|
||||||
registerReceiver(preferencesChangesReceiver, new IntentFilter(DragButtonCalibrationActivity.INTENT_ACTION));
|
registerReceiver(preferencesChangesReceiver, new IntentFilter(DragButtonCalibrationActivity.INTENT_ACTION));
|
||||||
|
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -137,8 +137,9 @@ public abstract class AbstractDialogPreference<T> extends DialogPreference {
|
|||||||
private void persist(@Nullable T value) {
|
private void persist(@Nullable T value) {
|
||||||
final String toBePersistedString = getMapper().formatValue(value);
|
final String toBePersistedString = getMapper().formatValue(value);
|
||||||
if (toBePersistedString != null) {
|
if (toBePersistedString != null) {
|
||||||
|
if ( callChangeListener(value) ) {
|
||||||
persistString(toBePersistedString);
|
persistString(toBePersistedString);
|
||||||
callChangeListener(value);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,18 +24,26 @@ public abstract class RangeSeekBarPreference<T extends Number> extends AbstractD
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final Interval<T> boundaries;
|
private final Interval<T> boundaries;
|
||||||
|
|
||||||
|
private Integer steps;
|
||||||
|
|
||||||
public RangeSeekBarPreference(@NotNull Context context, AttributeSet attrs) {
|
public RangeSeekBarPreference(@NotNull Context context, AttributeSet attrs) {
|
||||||
super(context, attrs, null);
|
super(context, attrs, null);
|
||||||
|
|
||||||
|
//noinspection ConstantConditions
|
||||||
boundaries = getMapper().parseValue(attrs.getAttributeValue(localNameSpace, "boundaries"));
|
boundaries = getMapper().parseValue(attrs.getAttributeValue(localNameSpace, "boundaries"));
|
||||||
|
|
||||||
assert boundaries != null;
|
steps = attrs.getAttributeIntValue(localNameSpace, "steps", -1);
|
||||||
|
if ( steps.equals(-1) ) {
|
||||||
|
steps = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert steps == null || steps >= 2;
|
||||||
|
|
||||||
createPreferenceView();
|
createPreferenceView();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createPreferenceView() {
|
private void createPreferenceView() {
|
||||||
this.rangeSeekBar = new NumberRangeSeekBar<T>(boundaries, null, context);
|
this.rangeSeekBar = new NumberRangeSeekBar<T>(boundaries, steps, context);
|
||||||
this.rangeSeekBar.setNotifyWhileDragging(true);
|
this.rangeSeekBar.setNotifyWhileDragging(true);
|
||||||
this.rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
this.rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ import android.widget.ImageView;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.common.math.DiscreteNormalizer;
|
|
||||||
import org.solovyev.common.math.LinearNormalizer;
|
import org.solovyev.common.math.LinearNormalizer;
|
||||||
import org.solovyev.common.math.Normalizer;
|
import org.solovyev.common.math.Normalizer;
|
||||||
import org.solovyev.common.utils.Converter;
|
import org.solovyev.common.utils.Converter;
|
||||||
@ -44,7 +43,10 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
private final T minValue, maxValue;
|
private final T minValue, maxValue;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Normalizer normalizer;
|
private final Normalizer fromValueNormalizer;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Normalizer fromScreenNormalizer;
|
||||||
|
|
||||||
private double normalizedMinValue = 0d;
|
private double normalizedMinValue = 0d;
|
||||||
|
|
||||||
@ -63,7 +65,8 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
*
|
*
|
||||||
* @param minValue The minimum value of the selectable range.
|
* @param minValue The minimum value of the selectable range.
|
||||||
* @param maxValue The maximum value of the selectable range.
|
* @param maxValue The maximum value of the selectable range.
|
||||||
* @param context
|
* @param steps number of steps to be used in range seek bar
|
||||||
|
* @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.
|
* @throws IllegalArgumentException Will be thrown if min/max value types are not one of Long, Double, Integer, Float, Short, Byte or BigDecimal.
|
||||||
*/
|
*/
|
||||||
public AbstractRangeSeekBar(@NotNull T minValue, @NotNull T maxValue, @Nullable Integer steps, Context context) throws IllegalArgumentException {
|
public AbstractRangeSeekBar(@NotNull T minValue, @NotNull T maxValue, @Nullable Integer steps, Context context) throws IllegalArgumentException {
|
||||||
@ -75,13 +78,28 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
this.toDoubleConverter = getToDoubleConverter();
|
this.toDoubleConverter = getToDoubleConverter();
|
||||||
this.toTConverter = getToTConverter();
|
this.toTConverter = getToTConverter();
|
||||||
|
|
||||||
if (steps == null) {
|
fromValueNormalizer = new LinearNormalizer(toDoubleConverter.convert(minValue), toDoubleConverter.convert(maxValue));
|
||||||
normalizer = new LinearNormalizer(toDoubleConverter.convert(minValue), toDoubleConverter.convert(maxValue));
|
|
||||||
} else {
|
|
||||||
normalizer = new DiscreteNormalizer(toDoubleConverter.convert(minValue), toDoubleConverter.convert(maxValue), steps);
|
|
||||||
}
|
|
||||||
|
|
||||||
tc = new ThumbContainer();
|
tc = new ThumbContainer();
|
||||||
|
|
||||||
|
fromScreenNormalizer = new Normalizer() {
|
||||||
|
@Override
|
||||||
|
public double normalize(double value) {
|
||||||
|
int width = getWidth();
|
||||||
|
if (width <= 2 * tc.padding) {
|
||||||
|
// prevent division by zero, simply return 0.
|
||||||
|
return 0d;
|
||||||
|
} else {
|
||||||
|
double result = (value - tc.padding) / (width - 2 * tc.padding);
|
||||||
|
return Math.min(1d, Math.max(0d, result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double denormalize(double value) {
|
||||||
|
return (float) (tc.padding + value * (getWidth() - 2 * tc.padding));
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -180,11 +198,15 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
break;
|
break;
|
||||||
case MotionEvent.ACTION_MOVE:
|
case MotionEvent.ACTION_MOVE:
|
||||||
if (pressedThumb != null) {
|
if (pressedThumb != null) {
|
||||||
|
|
||||||
|
double value = convertToNormalizedValue(event.getX());
|
||||||
|
|
||||||
if (Thumb.MIN.equals(pressedThumb)) {
|
if (Thumb.MIN.equals(pressedThumb)) {
|
||||||
setNormalizedMinValue(convertToNormalizedValue(event.getX()));
|
setNormalizedMinValue(value);
|
||||||
} else if (Thumb.MAX.equals(pressedThumb)) {
|
} else if (Thumb.MAX.equals(pressedThumb)) {
|
||||||
setNormalizedMaxValue(convertToNormalizedValue(event.getX()));
|
setNormalizedMaxValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notifyWhileDragging && listener != null) {
|
if (notifyWhileDragging && listener != null) {
|
||||||
listener.rangeSeekBarValuesChanged(getSelectedMinValue(), getSelectedMaxValue(), false);
|
listener.rangeSeekBarValuesChanged(getSelectedMinValue(), getSelectedMaxValue(), false);
|
||||||
}
|
}
|
||||||
@ -317,7 +339,7 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private T denormalizeValue(double normalized) {
|
private T denormalizeValue(double normalized) {
|
||||||
return toTConverter.convert(normalizer.denormalize(normalized));
|
return toTConverter.convert(fromValueNormalizer.denormalize(normalized));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -327,7 +349,7 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
* @return The normalized double.
|
* @return The normalized double.
|
||||||
*/
|
*/
|
||||||
private double normalizeValue(T value) {
|
private double normalizeValue(T value) {
|
||||||
return normalizer.normalize(toDoubleConverter.convert(value));
|
return fromValueNormalizer.normalize(toDoubleConverter.convert(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -337,7 +359,7 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
* @return The converted value in screen space.
|
* @return The converted value in screen space.
|
||||||
*/
|
*/
|
||||||
private float convertToScreenValue(double normalizedValue) {
|
private float convertToScreenValue(double normalizedValue) {
|
||||||
return (float) (tc.padding + normalizedValue * (getWidth() - 2 * tc.padding));
|
return (float)this.fromScreenNormalizer.denormalize(normalizedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -347,14 +369,7 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
* @return The normalized value.
|
* @return The normalized value.
|
||||||
*/
|
*/
|
||||||
private double convertToNormalizedValue(float screenValue) {
|
private double convertToNormalizedValue(float screenValue) {
|
||||||
int width = getWidth();
|
return this.fromScreenNormalizer.normalize(screenValue);
|
||||||
if (width <= 2 * tc.padding) {
|
|
||||||
// prevent division by zero, simply return 0.
|
|
||||||
return 0d;
|
|
||||||
} else {
|
|
||||||
double result = (screenValue - tc.padding) / (width - 2 * tc.padding);
|
|
||||||
return Math.min(1d, Math.max(0d, result));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.solovyev.common.math;
|
package org.solovyev.common.math;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -10,35 +11,43 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
public class DiscreteNormalizer implements Normalizer {
|
public class DiscreteNormalizer implements Normalizer {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final LinearNormalizer linearNormalizer;
|
private final Normalizer normalizer;
|
||||||
|
|
||||||
private final double min;
|
private final double min;
|
||||||
|
|
||||||
private final double step;
|
private final double step;
|
||||||
|
|
||||||
public DiscreteNormalizer(double min, double max, int steps) {
|
public DiscreteNormalizer(double min, double max, int steps) {
|
||||||
|
this(min, max, steps, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscreteNormalizer(double min, double max, int steps, @Nullable Normalizer normalizer) {
|
||||||
assert min <= max;
|
assert min <= max;
|
||||||
assert steps > 1;
|
assert steps > 1;
|
||||||
|
|
||||||
this.linearNormalizer = new LinearNormalizer(min, max);
|
if (normalizer != null) {
|
||||||
|
this.normalizer = normalizer;
|
||||||
|
} else {
|
||||||
|
this.normalizer = new LinearNormalizer(min, max);
|
||||||
|
}
|
||||||
|
|
||||||
this.step = linearNormalizer.normalize((max - min) / (steps - 1));
|
this.step = this.normalizer.normalize((max - min) / (steps - 1));
|
||||||
this.min = linearNormalizer.normalize(min);
|
this.min = this.normalizer.normalize(min);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DiscreteNormalizer(double min, double max, double step) {
|
public DiscreteNormalizer(double min, double max, double step) {
|
||||||
assert min <= max;
|
assert min <= max;
|
||||||
assert step > 0;
|
assert step > 0;
|
||||||
|
|
||||||
this.linearNormalizer = new LinearNormalizer(min, max);
|
this.normalizer = new LinearNormalizer(min, max);
|
||||||
|
|
||||||
this.step = linearNormalizer.normalize(step);
|
this.step = normalizer.normalize(step);
|
||||||
this.min = linearNormalizer.normalize(min);
|
this.min = normalizer.normalize(min);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double normalize(double value) {
|
public double normalize(double value) {
|
||||||
double normalizedValue = linearNormalizer.normalize(value);
|
double normalizedValue = normalizer.normalize(value);
|
||||||
|
|
||||||
double result = min;
|
double result = min;
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -54,6 +63,6 @@ public class DiscreteNormalizer implements Normalizer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double denormalize(double value) {
|
public double denormalize(double value) {
|
||||||
return linearNormalizer.denormalize(value);
|
return normalizer.denormalize(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user