From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / android / project / xscreensaver / src / org / jwz / xscreensaver / SliderPreference.java
index 8a772637a24ebbcf224ba11038a92680e461ab08..c1a1a1de15a59eb00b0a1c96081420a8d658b170 100644 (file)
-/*
- * 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;
+  }
 }