Inline SeekBarPreference

 Dialog-based SeekBarPreference renamed to SeekBarDialogPreference
 New inline SeekBarPreference added

Change-Id: I7a5d8f7aa554c4af4086a9bcc74cf07879c8523c
diff --git a/core/java/android/preference/SeekBarPreference.java b/core/java/android/preference/SeekBarPreference.java
index 037fb41..b8919c2 100644
--- a/core/java/android/preference/SeekBarPreference.java
+++ b/core/java/android/preference/SeekBarPreference.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,51 +17,226 @@
 package android.preference;
 
 import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.preference.DialogPreference;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.util.AttributeSet;
+import android.view.KeyEvent;
 import android.view.View;
-import android.widget.ImageView;
 import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
 
 /**
  * @hide
  */
-public class SeekBarPreference extends DialogPreference {
-    private static final String TAG = "SeekBarPreference";
+public class SeekBarPreference extends Preference
+        implements OnSeekBarChangeListener {
 
-    private Drawable mMyIcon;
+    private int mProgress;
+    private int mMax;
+    private boolean mTrackingTouch;
 
-    public SeekBarPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        setDialogLayoutResource(com.android.internal.R.layout.seekbar_dialog);
-        createActionButtons();
-
-        // Steal the XML dialogIcon attribute's value
-        mMyIcon = getDialogIcon();
-        setDialogIcon(null);
+    public SeekBarPreference(
+            Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.ProgressBar, defStyle, 0);
+        setMax(a.getInt(com.android.internal.R.styleable.ProgressBar_max, mMax));
+        a.recycle();
+        setLayoutResource(com.android.internal.R.layout.preference_widget_seekbar);
     }
 
-    // Allow subclasses to override the action buttons
-    public void createActionButtons() {
-        setPositiveButtonText(android.R.string.ok);
-        setNegativeButtonText(android.R.string.cancel);
+    public SeekBarPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SeekBarPreference(Context context) {
+        this(context, null);
     }
 
     @Override
-    protected void onBindDialogView(View view) {
-        super.onBindDialogView(view);
+    protected void onBindView(View view) {
+        super.onBindView(view);
+        SeekBar seekBar = (SeekBar) view.findViewById(
+                com.android.internal.R.id.seekbar);
+        seekBar.setOnSeekBarChangeListener(this);
+        seekBar.setMax(mMax);
+        seekBar.setProgress(mProgress);
+        seekBar.setEnabled(isEnabled());
+    }
 
-        final ImageView iconView = (ImageView) view.findViewById(android.R.id.icon);
-        if (mMyIcon != null) {
-            iconView.setImageDrawable(mMyIcon);
-        } else {
-            iconView.setVisibility(View.GONE);
+    @Override
+    public CharSequence getSummary() {
+        return null;
+    }
+
+    @Override
+    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+        setProgress(restoreValue ? getPersistedInt(mProgress)
+                : (Integer) defaultValue);
+    }
+
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        if (event.getAction() != KeyEvent.ACTION_UP) {
+            if (keyCode == KeyEvent.KEYCODE_PLUS
+                    || keyCode == KeyEvent.KEYCODE_EQUALS) {
+                setProgress(getProgress() + 1);
+                return true;
+            }
+            if (keyCode == KeyEvent.KEYCODE_MINUS) {
+                setProgress(getProgress() - 1);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void setMax(int max) {
+        if (max != mMax) {
+            mMax = max;
+            notifyChanged();
         }
     }
 
-    protected static SeekBar getSeekBar(View dialogView) {
-        return (SeekBar) dialogView.findViewById(com.android.internal.R.id.seekbar);
+    public void setProgress(int progress) {
+        setProgress(progress, true);
+    }
+
+    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();
+            }
+        }
+    }
+
+    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
+     */
+    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);
+        }
+    }
+
+    @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.
+     * <p>
+     * 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);
+        }
+
+        @SuppressWarnings("unused")
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
     }
 }