From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / android / project / xscreensaver / src / org / jwz / xscreensaver / SliderPreference.java
1 /* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  *
12  * A numeric preference as a slider, inline in the preferences list.
13  * XML options include:
14  *
15  *  low, high (floats) -- smallest and largest allowed values.
16  *  If low > high, the value increases as the slider's thumb moves left.
17  *
18  *  lowLabel, highLabel (strings) -- labels shown at the left and right
19  *  ends of the slider.
20  *
21  *  integral (boolean) -- whether to use whole numbers instead of floats;
22  */
23
24 package org.jwz.xscreensaver;
25
26 import android.content.Context;
27 import android.content.res.TypedArray;
28 import android.content.res.Resources;
29 import android.preference.Preference;
30 import android.util.AttributeSet;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.widget.SeekBar;
34 import android.widget.TextView;
35 import android.util.Log;
36
37 public class SliderPreference extends Preference {
38
39   protected float low, high;
40   protected String low_label, high_label;
41   protected boolean integral;
42   protected float mValue;
43   protected int seekbar_ticks;
44
45   public SliderPreference(Context context, AttributeSet attrs) {
46     this (context, attrs, 0);
47   }
48
49   public SliderPreference (Context context, AttributeSet attrs, int defStyle) {
50     super (context, attrs, defStyle);
51
52     Resources res = context.getResources();
53
54     // Parse these from the "<SliderPreference>" tag
55     low        = Float.parseFloat (attrs.getAttributeValue (null, "low"));
56     high       = Float.parseFloat (attrs.getAttributeValue (null, "high"));
57     integral   = attrs.getAttributeBooleanValue (null, "integral", false);
58     low_label  = res.getString(
59                    attrs.getAttributeResourceValue (null, "lowLabel", 0));
60     high_label = res.getString(
61                    attrs.getAttributeResourceValue (null, "highLabel", 0));
62
63     seekbar_ticks = (integral
64                      ? (int) Math.floor (Math.abs (high - low))
65                      : 100000);
66
67     setWidgetLayoutResource (R.layout.slider_preference);
68   }
69
70
71   @Override
72   protected void onSetInitialValue (boolean restore, Object def) {
73     if (restore) {
74       mValue = getPersistedFloat (low);
75     } else {
76       mValue = (Float) def;
77       persistFloat (mValue);
78     }
79     //Log.d("xscreensaver", String.format("SLIDER INIT %s: %f",
80     //      low_label, mValue));
81   }
82
83   @Override
84   protected Object onGetDefaultValue(TypedArray a, int index) {
85     return a.getFloat (index, low);
86   }
87
88
89   public float getValue() {
90     return mValue;
91   }
92
93   public void setValue (float value) {
94
95     if (low < high) {
96       value = Math.max (low, Math.min (high, value));
97     } else {
98       value = Math.max (high, Math.min (low, value));
99     }
100
101     if (integral)
102       value = Math.round (value);
103
104     if (value != mValue) {
105       //Log.d("xscreensaver", String.format("SLIDER %s: %f", low_label, value));
106       persistFloat (value);
107       mValue = value;
108       notifyChanged();
109     }
110   }
111
112
113   @Override
114   protected View onCreateView (ViewGroup parent) {
115     View view = super.onCreateView(parent);
116
117     TextView low_view = (TextView)
118       view.findViewById (R.id.slider_preference_low);
119     low_view.setText (low_label);
120
121     TextView high_view = (TextView)
122       view.findViewById (R.id.slider_preference_high);
123     high_view.setText (high_label);
124
125     SeekBar seekbar = (SeekBar)
126       view.findViewById (R.id.slider_preference_seekbar);
127     seekbar.setMax (seekbar_ticks);
128
129     float ratio = (mValue - low) / (high - low);
130     int seek_value = (int) (ratio * (float) seekbar_ticks);
131
132     seekbar.setProgress (seek_value);
133
134     final SliderPreference slider = this;
135
136     seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
137
138         @Override
139         public void onStopTrackingTouch(SeekBar seekBar) {
140         }
141
142         @Override
143         public void onStartTrackingTouch(SeekBar seekBar) {
144         }
145
146         @Override
147         public void onProgressChanged (SeekBar seekBar, int progress,
148                                        boolean fromUser) {
149           if (fromUser) {
150             float ratio = (float) progress / (float) seekbar_ticks;
151             float value = low + (ratio * (high - low));
152             slider.setValue (value);
153             callChangeListener (progress);
154           }
155         }
156       });
157
158     return view;
159   }
160 }