-/*
- * Copyright 2012 Jay Weisskopf
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
*
- * Licensed under the MIT License (see LICENSE.txt)
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * A numeric preference as a slider, inline in the preferences list.
+ * XML options include:
+ *
+ * low, high (floats) -- smallest and largest allowed values.
+ * If low > high, the value increases as the slider's thumb moves left.
+ *
+ * lowLabel, highLabel (strings) -- labels shown at the left and right
+ * ends of the slider.
+ *
+ * integral (boolean) -- whether to use whole numbers instead of floats;
*/
-//package net.jayschwa.android.preference;
package org.jwz.xscreensaver;
-
import android.content.Context;
import android.content.res.TypedArray;
-import android.preference.DialogPreference;
+import android.content.res.Resources;
+import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.SeekBar;
+import android.widget.TextView;
+import android.util.Log;
-/**
- * @author Jay Weisskopf
- */
-public class SliderPreference extends DialogPreference {
-
- protected final static int SEEKBAR_RESOLUTION = 10000;
-
- protected float mValue;
- protected int mSeekBarValue;
- protected CharSequence[] mSummaries;
-
- /**
- * @param context
- * @param attrs
- */
- public SliderPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- setup(context, attrs);
- }
-
- /**
- * @param context
- * @param attrs
- * @param defStyle
- */
- public SliderPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- setup(context, attrs);
- }
-
- private void setup(Context context, AttributeSet attrs) {
- setDialogLayoutResource(R.layout.slider_preference_dialog);
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SliderPreference);
- try {
- setSummary(a.getTextArray(R.styleable.SliderPreference_android_summary));
- } catch (Exception e) {
- // Do nothing
- }
- a.recycle();
- }
-
- @Override
- protected Object onGetDefaultValue(TypedArray a, int index) {
- return a.getFloat(index, 0);
- }
-
- @Override
- protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
- setValue(restoreValue ? getPersistedFloat(mValue) : (Float) defaultValue);
- }
-
- @Override
- public CharSequence getSummary() {
- if (mSummaries != null && mSummaries.length > 0) {
- int index = (int) (mValue * mSummaries.length);
- index = Math.min(index, mSummaries.length - 1);
- return mSummaries[index];
- } else {
- return super.getSummary();
- }
- }
-
- public void setSummary(CharSequence[] summaries) {
- mSummaries = summaries;
- }
-
- @Override
- public void setSummary(CharSequence summary) {
- super.setSummary(summary);
- mSummaries = null;
- }
-
- @Override
- public void setSummary(int summaryResId) {
- try {
- setSummary(getContext().getResources().getStringArray(summaryResId));
- } catch (Exception e) {
- super.setSummary(summaryResId);
- }
- }
-
- public float getValue() {
- return mValue;
- }
-
- public void setValue(float value) {
- value = Math.max(0, Math.min(value, 1)); // clamp to [0, 1]
- if (shouldPersist()) {
- persistFloat(value);
- }
- if (value != mValue) {
- mValue = value;
- notifyChanged();
- }
- }
-
- @Override
- protected View onCreateDialogView() {
- mSeekBarValue = (int) (mValue * SEEKBAR_RESOLUTION);
- View view = super.onCreateDialogView();
- SeekBar seekbar = (SeekBar) view.findViewById(R.id.slider_preference_seekbar);
- seekbar.setMax(SEEKBAR_RESOLUTION);
- seekbar.setProgress(mSeekBarValue);
- seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- }
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (fromUser) {
- SliderPreference.this.mSeekBarValue = progress;
- }
- }
- });
- return view;
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- final float newValue = (float) mSeekBarValue / SEEKBAR_RESOLUTION;
- if (positiveResult && callChangeListener(newValue)) {
- setValue(newValue);
- }
- super.onDialogClosed(positiveResult);
- }
-
- // TODO: Save and restore preference state.
+public class SliderPreference extends Preference {
+
+ protected float low, high;
+ protected String low_label, high_label;
+ protected boolean integral;
+ protected float mValue;
+ protected int seekbar_ticks;
+
+ public SliderPreference(Context context, AttributeSet attrs) {
+ this (context, attrs, 0);
+ }
+
+ public SliderPreference (Context context, AttributeSet attrs, int defStyle) {
+ super (context, attrs, defStyle);
+
+ Resources res = context.getResources();
+
+ // Parse these from the "<SliderPreference>" tag
+ low = Float.parseFloat (attrs.getAttributeValue (null, "low"));
+ high = Float.parseFloat (attrs.getAttributeValue (null, "high"));
+ integral = attrs.getAttributeBooleanValue (null, "integral", false);
+ low_label = res.getString(
+ attrs.getAttributeResourceValue (null, "lowLabel", 0));
+ high_label = res.getString(
+ attrs.getAttributeResourceValue (null, "highLabel", 0));
+
+ seekbar_ticks = (integral
+ ? (int) Math.floor (Math.abs (high - low))
+ : 100000);
+
+ setWidgetLayoutResource (R.layout.slider_preference);
+ }
+
+
+ @Override
+ protected void onSetInitialValue (boolean restore, Object def) {
+ if (restore) {
+ mValue = getPersistedFloat (low);
+ } else {
+ mValue = (Float) def;
+ persistFloat (mValue);
+ }
+ //Log.d("xscreensaver", String.format("SLIDER INIT %s: %f",
+ // low_label, mValue));
+ }
+
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ return a.getFloat (index, low);
+ }
+
+
+ public float getValue() {
+ return mValue;
+ }
+
+ public void setValue (float value) {
+
+ if (low < high) {
+ value = Math.max (low, Math.min (high, value));
+ } else {
+ value = Math.max (high, Math.min (low, value));
+ }
+
+ if (integral)
+ value = Math.round (value);
+
+ if (value != mValue) {
+ //Log.d("xscreensaver", String.format("SLIDER %s: %f", low_label, value));
+ persistFloat (value);
+ mValue = value;
+ notifyChanged();
+ }
+ }
+
+
+ @Override
+ protected View onCreateView (ViewGroup parent) {
+ View view = super.onCreateView(parent);
+
+ TextView low_view = (TextView)
+ view.findViewById (R.id.slider_preference_low);
+ low_view.setText (low_label);
+
+ TextView high_view = (TextView)
+ view.findViewById (R.id.slider_preference_high);
+ high_view.setText (high_label);
+
+ SeekBar seekbar = (SeekBar)
+ view.findViewById (R.id.slider_preference_seekbar);
+ seekbar.setMax (seekbar_ticks);
+
+ float ratio = (mValue - low) / (high - low);
+ int seek_value = (int) (ratio * (float) seekbar_ticks);
+
+ seekbar.setProgress (seek_value);
+
+ final SliderPreference slider = this;
+
+ seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onProgressChanged (SeekBar seekBar, int progress,
+ boolean fromUser) {
+ if (fromUser) {
+ float ratio = (float) progress / (float) seekbar_ticks;
+ float value = low + (ratio * (high - low));
+ slider.setValue (value);
+ callChangeListener (progress);
+ }
+ }
+ });
+
+ return view;
+ }
}