/*
* Copyright (C) 2015-present, osfans
* waxaca@163.com https://github.com/osfans
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package com.osfans.trime;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
/** @hide */
public class SeekBarPreference extends Preference implements OnSeekBarChangeListener {
private int mProgress;
private int mMax;
private boolean mTrackingTouch;
private TextView mValue;
public SeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
int[] set = {android.R.attr.max};
TypedArray a = context.obtainStyledAttributes(attrs, set);
setMax(a.getInt(0, 100));
a.recycle();
}
public SeekBarPreference(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.preferenceStyle);
}
public SeekBarPreference(Context context) {
this(context, null);
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
SeekBar seekBar = (SeekBar) view.findViewById(R.id.seekbar);
seekBar.setOnSeekBarChangeListener(this);
seekBar.setMax(mMax);
seekBar.setProgress(mProgress);
seekBar.setEnabled(isEnabled());
mValue = (TextView) view.findViewById(R.id.value);
setValue();
}
private CharSequence getValue(int progress) {
String unit = "%";
switch (getKey()) {
case "longpress_timeout":
progress = 10 * progress + 100;
unit = getContext().getString(R.string.key_vibrate_duration_unit);
break;
case "key_vibrate_duration":
unit = getContext().getString(R.string.key_vibrate_duration_unit);
break;
case "repeat_interval":
progress = 10 * progress + 10;
unit = getContext().getString(R.string.key_vibrate_duration_unit);
break;
}
return progress + unit;
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
setProgress(restoreValue ? getPersistedInt(mProgress) : (Integer) defaultValue);
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getInt(index, 0);
}
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() != KeyEvent.ACTION_DOWN) {
return false;
}
SeekBar seekBar = (SeekBar) v.findViewById(R.id.seekbar);
if (seekBar == null) {
return false;
}
return seekBar.onKeyDown(keyCode, event);
}
private void setMax(int max) {
if (max != mMax) {
mMax = max;
notifyChanged();
}
}
private void setProgress(int progress) {
setProgress(progress, true);
}
private void setValue(int progress) {
if (mValue != null) mValue.setText(getValue(progress));
}
private void setValue() {
setValue(mProgress);
}
private void setProgress(int progress, boolean notifyChanged) {
if (progress > mMax) {
progress = mMax;
}
if (progress < 0) {
progress = 0;
}
if (progress != mProgress) {
mProgress = progress;
persistInt(progress);
if (notifyChanged) {
notifyChanged();
}
setValue();
}
}
public int getProgress() {
return mProgress;
}
/**
* Persist the seekBar's progress value if callChangeListener returns true, otherwise set the
* seekBar's progress to the stored value
*/
private void syncProgress(SeekBar seekBar) {
int progress = seekBar.getProgress();
if (progress != mProgress) {
if (callChangeListener(progress)) {
setProgress(progress, false);
} else {
seekBar.setProgress(mProgress);
}
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser && !mTrackingTouch) {
syncProgress(seekBar);
}
setValue(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
mTrackingTouch = true;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mTrackingTouch = false;
if (seekBar.getProgress() != mProgress) {
syncProgress(seekBar);
}
}
@Override
protected Parcelable onSaveInstanceState() {
/*
* Suppose a client uses this preference type without persisting. We
* must save the instance state so it is able to, for example, survive
* orientation changes.
*/
final Parcelable superState = super.onSaveInstanceState();
if (isPersistent()) {
// No need to save instance state since it's persistent
return superState;
}
// Save the instance state
final SavedState myState = new SavedState(superState);
myState.progress = mProgress;
myState.max = mMax;
return myState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (!state.getClass().equals(SavedState.class)) {
// Didn't save state for us in onSaveInstanceState
super.onRestoreInstanceState(state);
return;
}
// Restore the instance state
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
mProgress = myState.progress;
mMax = myState.max;
notifyChanged();
}
/**
* SavedState, a subclass of {@link BaseSavedState}, will store the state of MyPreference, a
* subclass of Preference.
*
*
It is important to always call through to super methods.
*/
private static class SavedState extends BaseSavedState {
int progress;
int max;
public SavedState(Parcel source) {
super(source);
// Restore the click counter
progress = source.readInt();
max = source.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
// Save the click counter
dest.writeInt(progress);
dest.writeInt(max);
}
public SavedState(Parcelable superState) {
super(superState);
}
public static final Parcelable.Creator CREATOR =
new Parcelable.Creator() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}