prefs
This commit is contained in:
parent
1e36fc56aa
commit
663f5b1dbc
@ -6,7 +6,6 @@
|
|||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="NumberRangeSeekBar">
|
<declare-styleable name="NumberRangeSeekBar">
|
||||||
<attr name="min" format="string"/>
|
<attr name="boundaries" format="string"/>
|
||||||
<attr name="max" format="string"/>
|
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -14,14 +14,26 @@
|
|||||||
|
|
||||||
|
|
||||||
<org.solovyev.android.view.prefs.IntegerRangeSeekBarPreference
|
<org.solovyev.android.view.prefs.IntegerRangeSeekBarPreference
|
||||||
a:key="touch.duration"
|
a:key="org.solovyev.android.calculator.DragButtonCalibrationActivity_distance"
|
||||||
a:title="Duration of something"
|
a:title="Distance of drag event"
|
||||||
a:summary="How long something will last"
|
a:text=" pxs"
|
||||||
a:dialogMessage="Something duration"
|
a:defaultValue="40;150"
|
||||||
a:defaultValue="5"
|
range:boundaries="15;500"/>
|
||||||
a:text=" minutes"
|
|
||||||
range:min="10"
|
<org.solovyev.android.view.prefs.IntegerRangeSeekBarPreference
|
||||||
range:max="600"/>
|
a:key="org.solovyev.android.calculator.DragButtonCalibrationActivity_duration"
|
||||||
|
a:title="Duration of drag event"
|
||||||
|
a:text=" ms"
|
||||||
|
a:defaultValue="40;1000"
|
||||||
|
range:boundaries="5;4000"/>
|
||||||
|
|
||||||
|
<org.solovyev.android.view.prefs.IntegerRangeSeekBarPreference
|
||||||
|
a:key="org.solovyev.android.calculator.DragButtonCalibrationActivity_angle"
|
||||||
|
a:title="Angle of drag event"
|
||||||
|
a:text=" degrees"
|
||||||
|
a:defaultValue="130;180"
|
||||||
|
range:boundaries="100;180"/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
@ -11,6 +11,7 @@ import android.content.Intent;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
@ -18,12 +19,10 @@ import android.view.View;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.view.widgets.*;
|
import org.solovyev.android.view.widgets.*;
|
||||||
|
import org.solovyev.common.FloatIntervalMapper;
|
||||||
import org.solovyev.common.collections.ManyValuedHashMap;
|
import org.solovyev.common.collections.ManyValuedHashMap;
|
||||||
import org.solovyev.common.collections.ManyValuedMap;
|
import org.solovyev.common.collections.ManyValuedMap;
|
||||||
import org.solovyev.common.utils.Interval;
|
import org.solovyev.common.utils.*;
|
||||||
import org.solovyev.common.utils.IntervalImpl;
|
|
||||||
import org.solovyev.common.utils.MathUtils;
|
|
||||||
import org.solovyev.common.utils.Point2d;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -42,13 +41,6 @@ public class DragButtonCalibrationActivity extends Activity {
|
|||||||
|
|
||||||
private final Map<DragButton, CalibrationArrow> map = new HashMap<DragButton, CalibrationArrow>();
|
private final Map<DragButton, CalibrationArrow> map = new HashMap<DragButton, CalibrationArrow>();
|
||||||
|
|
||||||
public static final String PREFERENCES = "dragButtonPreferences";
|
|
||||||
|
|
||||||
public static final String PREFERENCES_FIRST_RUN = "firstRun";
|
|
||||||
|
|
||||||
public static final String PREFERENCES_MIN = "min";
|
|
||||||
public static final String PREFERENCES_MAX = "max";
|
|
||||||
|
|
||||||
private static final float DEFAULT_VALUE = -999;
|
private static final float DEFAULT_VALUE = -999;
|
||||||
private static final int MIN_HISTORY_FOR_CALIBRATION = 10;
|
private static final int MIN_HISTORY_FOR_CALIBRATION = 10;
|
||||||
public static final String INTENT_ACTION = "org.solovyev.android.calculator.DragButtonPreferencesChanged";
|
public static final String INTENT_ACTION = "org.solovyev.android.calculator.DragButtonPreferencesChanged";
|
||||||
@ -168,7 +160,7 @@ public class DragButtonCalibrationActivity extends Activity {
|
|||||||
Log.d(this.getClass().getName(), "Time statistics: ");
|
Log.d(this.getClass().getName(), "Time statistics: ");
|
||||||
logStatData(timeStatData);
|
logStatData(timeStatData);
|
||||||
|
|
||||||
final SharedPreferences settings = getSharedPreferences(PREFERENCES, 0);
|
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
final SharedPreferences.Editor editor = settings.edit();
|
final SharedPreferences.Editor editor = settings.edit();
|
||||||
|
|
||||||
setPreferences(angleStatData, editor, PreferenceType.angle);
|
setPreferences(angleStatData, editor, PreferenceType.angle);
|
||||||
@ -186,59 +178,61 @@ public class DragButtonCalibrationActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setPreferences(@NotNull Map<DragDirection, MathUtils.StatData> statData, @NotNull SharedPreferences.Editor editor, @NotNull PreferenceType preferenceType) {
|
private void setPreferences(@NotNull Map<DragDirection, MathUtils.StatData> statData, @NotNull SharedPreferences.Editor editor, @NotNull PreferenceType preferenceType) {
|
||||||
|
final Mapper<Interval<Float>> mapper = new FloatIntervalMapper();
|
||||||
for (Map.Entry<DragDirection, MathUtils.StatData> entry : statData.entrySet()) {
|
for (Map.Entry<DragDirection, MathUtils.StatData> entry : statData.entrySet()) {
|
||||||
final float min = (float) entry.getValue().getMean() - 2 * (float) entry.getValue().getStandardDeviation();
|
final float min = (float) entry.getValue().getMean() - 2 * (float) entry.getValue().getStandardDeviation();
|
||||||
final float max = (float) entry.getValue().getMean() + 2 * (float) entry.getValue().getStandardDeviation();
|
final float max = (float) entry.getValue().getMean() + 2 * (float) entry.getValue().getStandardDeviation();
|
||||||
editor.putFloat(preferenceType.name() + "_" + entry.getKey().name() + "_" + PREFERENCES_MIN, Math.max(0, min));
|
editor.putString(getPreferenceId(preferenceType, entry.getKey()), mapper.formatValue(transformInterval(preferenceType, entry.getKey(), new IntervalImpl<Float>(Math.max(0, min), max))));
|
||||||
editor.putFloat(preferenceType.name() + "_" + entry.getKey().name() + "_" + PREFERENCES_MAX, max);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo serso: currently we do not use direction
|
||||||
|
public static String getPreferenceId(@NotNull PreferenceType preferenceType, @NotNull DragDirection direction) {
|
||||||
|
return "org.solovyev.android.calculator.DragButtonCalibrationActivity" + "_" + preferenceType.name() /*+ "_" + direction.name()*/;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Preferences getPreferences(@NotNull Context context) {
|
public static Preferences getPreferences(@NotNull Context context) {
|
||||||
SharedPreferences preferences = context.getSharedPreferences(PREFERENCES, MODE_PRIVATE);
|
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
||||||
|
final Mapper<Interval<Float>> mapper = new FloatIntervalMapper();
|
||||||
|
|
||||||
final Preferences result = new Preferences();
|
final Preferences result = new Preferences();
|
||||||
|
|
||||||
for (PreferenceType preferenceType : PreferenceType.values()) {
|
for (PreferenceType preferenceType : PreferenceType.values()) {
|
||||||
for (DragDirection dragDirection : DragDirection.values()) {
|
for (DragDirection dragDirection : DragDirection.values()) {
|
||||||
|
|
||||||
final float defaultMin;
|
final Interval<Float> defaultValue;
|
||||||
final float defaultMax;
|
|
||||||
switch (preferenceType) {
|
switch (preferenceType) {
|
||||||
case angle:
|
case angle:
|
||||||
switch (dragDirection) {
|
switch (dragDirection) {
|
||||||
case up:
|
case up:
|
||||||
defaultMin = 130f;
|
defaultValue = new IntervalImpl<Float>(130f, 180f);
|
||||||
defaultMax = 180f;
|
|
||||||
break;
|
break;
|
||||||
case down:
|
case down:
|
||||||
defaultMin = 0f;
|
defaultValue = new IntervalImpl<Float>(0f, 50f);
|
||||||
defaultMax = 50f;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
defaultMin = 0;
|
defaultValue = new IntervalImpl<Float>(0f, 0f);
|
||||||
defaultMax = 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case distance:
|
case distance:
|
||||||
defaultMin = 10f;
|
defaultValue = new IntervalImpl<Float>(10f, 150f);
|
||||||
defaultMax = 150f;
|
|
||||||
break;
|
break;
|
||||||
case duration:
|
case duration:
|
||||||
defaultMin = 40f;
|
defaultValue = new IntervalImpl<Float>(40f, 1000f);
|
||||||
defaultMax = 1000f;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
defaultMin = DEFAULT_VALUE;
|
defaultValue = new IntervalImpl<Float>(DEFAULT_VALUE, DEFAULT_VALUE);
|
||||||
defaultMax = DEFAULT_VALUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final float min = preferences.getFloat(preferenceType.name() + "_" + dragDirection.name() + "_" + PREFERENCES_MIN, defaultMin);
|
final String value = preferences.getString(getPreferenceId(preferenceType, dragDirection), mapper.formatValue(defaultValue));
|
||||||
final float max = preferences.getFloat(preferenceType.name() + "_" + dragDirection.name() + "_" + PREFERENCES_MAX, defaultMax);
|
|
||||||
|
|
||||||
if (min != DEFAULT_VALUE && max != DEFAULT_VALUE) {
|
final Interval<Float> interval = mapper.parseValue(value);
|
||||||
final DragPreference directionPreference = new DragPreference(dragDirection, new IntervalImpl<Float>(min, max));
|
transformInterval(preferenceType, dragDirection, interval);
|
||||||
|
if (new IntervalImpl<Float>(DEFAULT_VALUE, DEFAULT_VALUE).equals(interval)) {
|
||||||
|
assert interval != null;
|
||||||
|
final DragPreference directionPreference = new DragPreference(dragDirection, interval);
|
||||||
|
|
||||||
Preference preference = result.getPreferencesMap().get(preferenceType);
|
Preference preference = result.getPreferencesMap().get(preferenceType);
|
||||||
if (preference == null) {
|
if (preference == null) {
|
||||||
@ -257,6 +251,17 @@ public class DragButtonCalibrationActivity extends Activity {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static Interval<Float> transformInterval(@NotNull PreferenceType preferenceType, @NotNull DragDirection dragDirection, @NotNull Interval<Float> interval) {
|
||||||
|
if ( preferenceType == PreferenceType.angle && dragDirection == DragDirection.down ) {
|
||||||
|
final Interval<Float> clone = interval.clone();
|
||||||
|
interval.setLeftBorder(180f - clone.getRightBorder());
|
||||||
|
interval.setRightBorder(180f - clone.getLeftBorder());
|
||||||
|
}
|
||||||
|
|
||||||
|
return interval;
|
||||||
|
}
|
||||||
|
|
||||||
public static class DragPreference {
|
public static class DragPreference {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ -4,17 +4,19 @@ import android.content.Context;
|
|||||||
import android.preference.DialogPreference;
|
import android.preference.DialogPreference;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.common.utils.Mapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 9/19/11
|
* Date: 9/19/11
|
||||||
* Time: 3:17 PM
|
* Time: 3:17 PM
|
||||||
*/
|
*/
|
||||||
public class AbstractDialogPreference extends DialogPreference {
|
public abstract class AbstractDialogPreference<T> extends DialogPreference {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected static final String androidns = "http://schemas.android.com/apk/res/android";
|
protected static final String androidns = "http://schemas.android.com/apk/res/android";
|
||||||
@ -26,38 +28,118 @@ public class AbstractDialogPreference extends DialogPreference {
|
|||||||
protected final Context context;
|
protected final Context context;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected String dialogMessage;
|
protected String description;
|
||||||
|
|
||||||
public AbstractDialogPreference(Context context, AttributeSet attrs) {
|
@Nullable
|
||||||
|
protected T value;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private T defaultValue;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected String valueText;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final String defaultStringValue;
|
||||||
|
|
||||||
|
|
||||||
|
public AbstractDialogPreference(Context context, AttributeSet attrs, @Nullable String defaultStringValue) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.defaultStringValue = defaultStringValue;
|
||||||
|
|
||||||
dialogMessage = attrs.getAttributeValue(androidns, "dialogMessage");
|
final String defaultValueFromAttrs = attrs.getAttributeValue(androidns, "defaultValue");
|
||||||
|
if ( defaultValueFromAttrs != null ) {
|
||||||
|
defaultValue = getMapper().parseValue(defaultValueFromAttrs);
|
||||||
|
} else if (defaultStringValue != null) {
|
||||||
|
defaultValue = getMapper().parseValue(defaultStringValue);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
description = attrs.getAttributeValue(androidns, "dialogMessage");
|
||||||
|
valueText = attrs.getAttributeValue(androidns, "text");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@NotNull
|
||||||
protected LinearLayout onCreateDialogView() {
|
protected LinearLayout onCreateDialogView() {
|
||||||
LinearLayout.LayoutParams params;
|
if (shouldPersist()) {
|
||||||
LinearLayout layout = new LinearLayout(context);
|
value = getPersistedValue();
|
||||||
layout.setOrientation(LinearLayout.VERTICAL);
|
}
|
||||||
layout.setPadding(6, 6, 6, 6);
|
|
||||||
|
final LinearLayout result = new LinearLayout(context);
|
||||||
final TextView splashText = new TextView(context);
|
result.setOrientation(LinearLayout.VERTICAL);
|
||||||
if (dialogMessage != null) {
|
result.setPadding(6, 6, 6, 6);
|
||||||
splashText.setText(dialogMessage);
|
|
||||||
|
if (description != null) {
|
||||||
|
final TextView splashText = new TextView(context);
|
||||||
|
splashText.setText(description);
|
||||||
|
result.addView(splashText);
|
||||||
}
|
}
|
||||||
layout.addView(splashText);
|
|
||||||
|
|
||||||
valueTextView = new TextView(context);
|
valueTextView = new TextView(context);
|
||||||
valueTextView.setGravity(Gravity.CENTER_HORIZONTAL);
|
valueTextView.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||||
valueTextView.setTextSize(32);
|
valueTextView.setTextSize(32);
|
||||||
params = new LinearLayout.LayoutParams(
|
|
||||||
|
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||||
LinearLayout.LayoutParams.FILL_PARENT,
|
LinearLayout.LayoutParams.FILL_PARENT,
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||||
layout.addView(valueTextView, params);
|
result.addView(valueTextView, params);
|
||||||
|
|
||||||
return layout;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSetInitialValue(boolean restore, Object defaultValue) {
|
||||||
|
super.onSetInitialValue(restore, defaultValue);
|
||||||
|
|
||||||
|
if (restore) {
|
||||||
|
if (shouldPersist()) {
|
||||||
|
value = getPersistedValue();
|
||||||
|
} else {
|
||||||
|
value = this.defaultValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = (T) defaultValue;
|
||||||
|
if (shouldPersist()) {
|
||||||
|
persist(this.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBindDialogView(View v) {
|
||||||
|
super.onBindDialogView(v);
|
||||||
|
initPreferenceView();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void initPreferenceView();
|
||||||
|
|
||||||
|
private T getPersistedValue() {
|
||||||
|
String persistedString = getPersistedString(defaultStringValue);
|
||||||
|
if ( persistedString == defaultStringValue ) {
|
||||||
|
return defaultValue;
|
||||||
|
} else {
|
||||||
|
return getMapper().parseValue(persistedString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void persistValue(@Nullable T value) {
|
||||||
|
if (callChangeListener(value)) {
|
||||||
|
if (shouldPersist()) {
|
||||||
|
persist(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void persist(@Nullable T value) {
|
||||||
|
final String toBePersistedString = getMapper().formatValue(value);
|
||||||
|
if (toBePersistedString != null) {
|
||||||
|
persistString(toBePersistedString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected abstract Mapper<T> getMapper();
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ package org.solovyev.android.view.prefs;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.common.utils.Converter;
|
import org.solovyev.common.IntegerIntervalMapper;
|
||||||
|
import org.solovyev.common.utils.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -24,13 +25,8 @@ public class IntegerRangeSeekBarPreference extends RangeSeekBarPreference<Intege
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
Converter<String, Integer> getConverter() {
|
protected Mapper<Interval<Integer>> getMapper() {
|
||||||
return new Converter<String, Integer>() {
|
return new IntegerIntervalMapper();
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Integer convert(@NotNull String value) {
|
|
||||||
return Integer.valueOf(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.view.prefs;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/11
|
||||||
|
* Time: 10:15 PM
|
||||||
|
*/
|
||||||
|
public interface PersistenceValueGetter<T> {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
T getPersistedValue(@Nullable T defaultValue);
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.view.prefs;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/11
|
||||||
|
* Time: 10:14 PM
|
||||||
|
*/
|
||||||
|
public interface PersistenceValueSetter<T> {
|
||||||
|
|
||||||
|
void persist(@Nullable T value);
|
||||||
|
}
|
@ -2,24 +2,19 @@ package org.solovyev.android.view.prefs;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.view.widgets.AbstractRangeSeekBar;
|
import org.solovyev.android.view.widgets.AbstractRangeSeekBar;
|
||||||
import org.solovyev.android.view.widgets.NumberRangeSeekBar;
|
import org.solovyev.android.view.widgets.NumberRangeSeekBar;
|
||||||
import org.solovyev.common.utils.CollectionsUtils;
|
import org.solovyev.common.utils.Interval;
|
||||||
import org.solovyev.common.utils.Converter;
|
import org.solovyev.common.utils.NumberInterval;
|
||||||
import org.solovyev.common.utils.StringMapper;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 9/19/11
|
* Date: 9/19/11
|
||||||
* Time: 12:27 PM
|
* Time: 12:27 PM
|
||||||
*/
|
*/
|
||||||
public abstract class RangeSeekBarPreference<T extends Number> extends AbstractDialogPreference implements AbstractRangeSeekBar.OnRangeSeekBarChangeListener<T> {
|
public abstract class RangeSeekBarPreference<T extends Number> extends AbstractDialogPreference<Interval<T>> implements AbstractRangeSeekBar.OnRangeSeekBarChangeListener<T> {
|
||||||
|
|
||||||
public final static String localNameSpace = "http://schemas.android.com/apk/res/org.solovyev.android.calculator";
|
public final static String localNameSpace = "http://schemas.android.com/apk/res/org.solovyev.android.calculator";
|
||||||
|
|
||||||
@ -27,52 +22,26 @@ public abstract class RangeSeekBarPreference<T extends Number> extends AbstractD
|
|||||||
private AbstractRangeSeekBar<T> rangeSeekBar;
|
private AbstractRangeSeekBar<T> rangeSeekBar;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private T min;
|
private final Interval<T> boundaries;
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private T max;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private T selectedMin;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private T selectedMax;
|
|
||||||
|
|
||||||
|
|
||||||
public RangeSeekBarPreference(@NotNull Context context, AttributeSet attrs) {
|
public RangeSeekBarPreference(@NotNull Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs, null);
|
||||||
|
|
||||||
|
boundaries = getMapper().parseValue(attrs.getAttributeValue(localNameSpace, "boundaries"));
|
||||||
|
|
||||||
final Converter<String, T> c = getConverter();
|
assert boundaries != null;
|
||||||
|
this.rangeSeekBar = new NumberRangeSeekBar<T>(boundaries, null, context);
|
||||||
String minString = attrs.getAttributeValue(localNameSpace, "min");
|
|
||||||
min = c.convert(minString == null ? "0" : minString);
|
|
||||||
String maxString = attrs.getAttributeValue(localNameSpace, "max");
|
|
||||||
max = c.convert(maxString == null ? "100" : maxString);
|
|
||||||
|
|
||||||
|
|
||||||
this.rangeSeekBar = new NumberRangeSeekBar<T>(min, max, null, context);
|
|
||||||
rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMin(@NotNull String min) {
|
|
||||||
this.min = getConverter().convert(min);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMax(@NotNull String max) {
|
|
||||||
this.max = getConverter().convert(max);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
abstract Converter<String, T> getConverter();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected LinearLayout onCreateDialogView() {
|
protected LinearLayout onCreateDialogView() {
|
||||||
final LinearLayout result = super.onCreateDialogView();
|
final LinearLayout result = super.onCreateDialogView();
|
||||||
|
|
||||||
this.rangeSeekBar = new NumberRangeSeekBar<T>(min, max, null, context);
|
this.rangeSeekBar = new NumberRangeSeekBar<T>(boundaries, null, context);
|
||||||
rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
||||||
initRangeSeekBar();
|
initPreferenceView();
|
||||||
|
|
||||||
result.addView(rangeSeekBar);
|
result.addView(rangeSeekBar);
|
||||||
|
|
||||||
@ -80,38 +49,24 @@ public abstract class RangeSeekBarPreference<T extends Number> extends AbstractD
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onBindDialogView(View v) {
|
protected void initPreferenceView() {
|
||||||
super.onBindDialogView(v);
|
if (value != null) {
|
||||||
initRangeSeekBar();
|
rangeSeekBar.setSelectedMinValue(value.getLeftBorder());
|
||||||
|
rangeSeekBar.setSelectedMaxValue(value.getRightBorder());
|
||||||
|
setValueText(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initRangeSeekBar() {
|
|
||||||
rangeSeekBar.setSelectedMinValue(selectedMin);
|
|
||||||
rangeSeekBar.setSelectedMaxValue(selectedMax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSetInitialValue(boolean restore, Object defaultValue) {
|
|
||||||
super.onSetInitialValue(restore, defaultValue);
|
|
||||||
|
|
||||||
final List<String> values;
|
|
||||||
if (restore) {
|
|
||||||
values = CollectionsUtils.split(getPersistedString("0;100"), ";", new StringMapper());
|
|
||||||
} else {
|
|
||||||
values = CollectionsUtils.split(String.valueOf(defaultValue), ";", new StringMapper());
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedMin = getConverter().convert(values.get(0));
|
|
||||||
selectedMax = getConverter().convert(values.get(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void rangeSeekBarValuesChanged(T minValue, T maxValue) {
|
public void rangeSeekBarValuesChanged(T minValue, T maxValue) {
|
||||||
final String value = CollectionsUtils.formatValue(Arrays.asList(String.valueOf(minValue), String.valueOf(maxValue)), ";", new StringMapper());
|
final Interval<T> interval = new NumberInterval<T>(minValue, maxValue);
|
||||||
if (shouldPersist()) {
|
persistValue(interval);
|
||||||
persistString(value);
|
|
||||||
|
setValueText(interval);
|
||||||
}
|
}
|
||||||
callChangeListener(value);
|
|
||||||
|
private void setValueText(@NotNull Interval<T> interval) {
|
||||||
|
final String t = String.valueOf(interval);
|
||||||
|
valueTextView.setText(valueText == null ? t : t.concat(valueText));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,11 @@ package org.solovyev.android.view.prefs;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
|
||||||
import android.widget.SeekBar;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.SeekBar;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.common.utils.Mapper;
|
||||||
|
|
||||||
|
|
||||||
/* The following code was written by Matthew Wiggins
|
/* The following code was written by Matthew Wiggins
|
||||||
@ -21,24 +21,20 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class SeekBarPreference extends AbstractDialogPreference implements SeekBar.OnSeekBarChangeListener {
|
public class SeekBarPreference extends AbstractDialogPreference<Integer> implements SeekBar.OnSeekBarChangeListener {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private SeekBar seekBar;
|
private SeekBar seekBar;
|
||||||
|
|
||||||
private int defaultValue, max, value = 0;
|
private int max = 0;
|
||||||
|
|
||||||
@Nullable
|
|
||||||
protected String valueText;
|
|
||||||
|
|
||||||
public SeekBarPreference(Context context, AttributeSet attrs) {
|
public SeekBarPreference(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs, "50");
|
||||||
|
|
||||||
defaultValue = attrs.getAttributeIntValue(androidns, "defaultValue", 0);
|
|
||||||
max = attrs.getAttributeIntValue(androidns, "max", 100);
|
max = attrs.getAttributeIntValue(androidns, "max", 100);
|
||||||
valueText = attrs.getAttributeValue(androidns, "text");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
protected LinearLayout onCreateDialogView() {
|
protected LinearLayout onCreateDialogView() {
|
||||||
final LinearLayout layout = super.onCreateDialogView();
|
final LinearLayout layout = super.onCreateDialogView();
|
||||||
@ -47,40 +43,45 @@ public class SeekBarPreference extends AbstractDialogPreference implements SeekB
|
|||||||
seekBar.setOnSeekBarChangeListener(this);
|
seekBar.setOnSeekBarChangeListener(this);
|
||||||
layout.addView(seekBar, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
|
layout.addView(seekBar, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||||
|
|
||||||
if (shouldPersist())
|
initPreferenceView();
|
||||||
value = getPersistedInt(defaultValue);
|
|
||||||
|
|
||||||
initSeekBar();
|
|
||||||
|
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSeekBar() {
|
@Override
|
||||||
|
protected void initPreferenceView() {
|
||||||
seekBar.setMax(max);
|
seekBar.setMax(max);
|
||||||
|
if (value != null) {
|
||||||
seekBar.setProgress(value);
|
seekBar.setProgress(value);
|
||||||
|
setValueText(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected Mapper<Integer> getMapper() {
|
||||||
|
return new Mapper<Integer>() {
|
||||||
|
@Override
|
||||||
|
public String formatValue(@Nullable Integer integer) throws IllegalArgumentException {
|
||||||
|
return integer == null ? null : String.valueOf(integer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onBindDialogView(View v) {
|
public Integer parseValue(@Nullable String s) throws IllegalArgumentException {
|
||||||
super.onBindDialogView(v);
|
return s == null ? null : Integer.valueOf(s);
|
||||||
initSeekBar();
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
@Override
|
|
||||||
protected void onSetInitialValue(boolean restore, Object defaultValue) {
|
|
||||||
super.onSetInitialValue(restore, defaultValue);
|
|
||||||
if (restore)
|
|
||||||
value = shouldPersist() ? getPersistedInt(this.defaultValue) : 0;
|
|
||||||
else
|
|
||||||
value = (Integer) defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) {
|
public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) {
|
||||||
|
setValueText(value);
|
||||||
|
|
||||||
|
persistValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setValueText(int value) {
|
||||||
String t = String.valueOf(value);
|
String t = String.valueOf(value);
|
||||||
valueTextView.setText(valueText == null ? t : t.concat(valueText));
|
valueTextView.setText(valueText == null ? t : t.concat(valueText));
|
||||||
if (shouldPersist())
|
|
||||||
persistInt(value);
|
|
||||||
callChangeListener(new Integer(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onStartTrackingTouch(SeekBar seek) {
|
public void onStartTrackingTouch(SeekBar seek) {
|
||||||
@ -99,7 +100,6 @@ public class SeekBarPreference extends AbstractDialogPreference implements SeekB
|
|||||||
|
|
||||||
public void setProgress(int progress) {
|
public void setProgress(int progress) {
|
||||||
value = progress;
|
value = progress;
|
||||||
if (seekBar != null)
|
|
||||||
seekBar.setProgress(progress);
|
seekBar.setProgress(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import android.content.Context;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.common.utils.Converter;
|
import org.solovyev.common.utils.Converter;
|
||||||
|
import org.solovyev.common.utils.Interval;
|
||||||
import org.solovyev.common.utils.NumberValuer;
|
import org.solovyev.common.utils.NumberValuer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,6 +17,11 @@ public class NumberRangeSeekBar<T extends Number> extends AbstractRangeSeekBar<T
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final NumberType numberType;
|
private final NumberType numberType;
|
||||||
|
|
||||||
|
|
||||||
|
public NumberRangeSeekBar(@NotNull Interval<T> boundaries, @Nullable Integer steps, Context context) throws IllegalArgumentException {
|
||||||
|
this(boundaries.getLeftBorder(), boundaries.getRightBorder(), steps, context);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new RangeSeekBar.
|
* Creates a new RangeSeekBar.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.common;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.common.utils.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/21/11
|
||||||
|
* Time: 12:02 AM
|
||||||
|
*/
|
||||||
|
public abstract class AbstractIntervalMapper<T> implements Mapper<Interval<T>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String formatValue(@Nullable Interval<T> interval) throws IllegalArgumentException {
|
||||||
|
if (interval != null) {
|
||||||
|
return CollectionsUtils.formatValue(Arrays.asList(interval.getLeftBorder(), interval.getRightBorder()), ";", getFormatter());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected abstract Formatter<T> getFormatter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Interval<T> parseValue(@Nullable String s) throws IllegalArgumentException {
|
||||||
|
final List<T> list = CollectionsUtils.split(s, ";", getParser());
|
||||||
|
|
||||||
|
assert list.size() == 2;
|
||||||
|
return new IntervalImpl<T>(list.get(0), list.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected abstract Parser<T> getParser();
|
||||||
|
}
|
37
src/main/java/org/solovyev/common/FloatIntervalMapper.java
Normal file
37
src/main/java/org/solovyev/common/FloatIntervalMapper.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.common;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.common.math.ValueOfFormatter;
|
||||||
|
import org.solovyev.common.utils.Formatter;
|
||||||
|
import org.solovyev.common.utils.Parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/21/11
|
||||||
|
* Time: 12:06 AM
|
||||||
|
*/
|
||||||
|
public class FloatIntervalMapper extends AbstractIntervalMapper<Float> {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected Formatter<Float> getFormatter() {
|
||||||
|
return new ValueOfFormatter<Float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected Parser<Float> getParser() {
|
||||||
|
return new Parser<Float>() {
|
||||||
|
@Override
|
||||||
|
public Float parseValue(@Nullable String s) throws IllegalArgumentException {
|
||||||
|
return Float.valueOf(s);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
35
src/main/java/org/solovyev/common/IntegerIntervalMapper.java
Normal file
35
src/main/java/org/solovyev/common/IntegerIntervalMapper.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.common;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.common.math.ValueOfFormatter;
|
||||||
|
import org.solovyev.common.utils.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/11
|
||||||
|
* Time: 11:56 PM
|
||||||
|
*/
|
||||||
|
public class IntegerIntervalMapper extends AbstractIntervalMapper<Integer> {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected Formatter<Integer> getFormatter() {
|
||||||
|
return new ValueOfFormatter<Integer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected Parser<Integer> getParser() {
|
||||||
|
return new Parser<Integer>() {
|
||||||
|
@Override
|
||||||
|
public Integer parseValue(@Nullable String s) throws IllegalArgumentException {
|
||||||
|
return Integer.valueOf(s);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
23
src/main/java/org/solovyev/common/math/ValueOfFormatter.java
Normal file
23
src/main/java/org/solovyev/common/math/ValueOfFormatter.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.common.math;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.common.utils.Formatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/20/11
|
||||||
|
* Time: 10:52 PM
|
||||||
|
*/
|
||||||
|
public class ValueOfFormatter<T> implements Formatter<T>{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String formatValue(@Nullable T t) throws IllegalArgumentException {
|
||||||
|
return String.valueOf(t);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user