Home | History | Annotate | Download | only in preference
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.preference;
     18 
     19 import android.app.Dialog;
     20 import android.content.Context;
     21 import android.content.res.TypedArray;
     22 import android.os.Parcel;
     23 import android.os.Parcelable;
     24 import android.util.AttributeSet;
     25 import android.view.KeyEvent;
     26 import android.view.View;
     27 import android.widget.SeekBar;
     28 
     29 /**
     30  * @hide
     31  */
     32 public class VolumePreference extends SeekBarDialogPreference implements
     33         PreferenceManager.OnActivityStopListener, View.OnKeyListener, SeekBarVolumizer.Callback {
     34 
     35     static final String TAG = "VolumePreference";
     36 
     37     private int mStreamType;
     38 
     39     /** May be null if the dialog isn't visible. */
     40     private SeekBarVolumizer mSeekBarVolumizer;
     41 
     42     public VolumePreference(
     43             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
     44         super(context, attrs, defStyleAttr, defStyleRes);
     45 
     46         final TypedArray a = context.obtainStyledAttributes(attrs,
     47                 com.android.internal.R.styleable.VolumePreference, defStyleAttr, defStyleRes);
     48         mStreamType = a.getInt(android.R.styleable.VolumePreference_streamType, 0);
     49         a.recycle();
     50     }
     51 
     52     public VolumePreference(Context context, AttributeSet attrs, int defStyleAttr) {
     53         this(context, attrs, defStyleAttr, 0);
     54     }
     55 
     56     public VolumePreference(Context context, AttributeSet attrs) {
     57         this(context, attrs, com.android.internal.R.attr.dialogPreferenceStyle);
     58     }
     59 
     60     public void setStreamType(int streamType) {
     61         mStreamType = streamType;
     62     }
     63 
     64     @Override
     65     protected void onBindDialogView(View view) {
     66         super.onBindDialogView(view);
     67 
     68         final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
     69         mSeekBarVolumizer = new SeekBarVolumizer(getContext(), mStreamType, null, this);
     70         mSeekBarVolumizer.setSeekBar(seekBar);
     71 
     72         getPreferenceManager().registerOnActivityStopListener(this);
     73 
     74         // grab focus and key events so that pressing the volume buttons in the
     75         // dialog doesn't also show the normal volume adjust toast.
     76         view.setOnKeyListener(this);
     77         view.setFocusableInTouchMode(true);
     78         view.requestFocus();
     79     }
     80 
     81     public boolean onKey(View v, int keyCode, KeyEvent event) {
     82         // If key arrives immediately after the activity has been cleaned up.
     83         if (mSeekBarVolumizer == null) return true;
     84         boolean isdown = (event.getAction() == KeyEvent.ACTION_DOWN);
     85         switch (keyCode) {
     86             case KeyEvent.KEYCODE_VOLUME_DOWN:
     87                 if (isdown) {
     88                     mSeekBarVolumizer.changeVolumeBy(-1);
     89                 }
     90                 return true;
     91             case KeyEvent.KEYCODE_VOLUME_UP:
     92                 if (isdown) {
     93                     mSeekBarVolumizer.changeVolumeBy(1);
     94                 }
     95                 return true;
     96             case KeyEvent.KEYCODE_VOLUME_MUTE:
     97                 if (isdown) {
     98                     mSeekBarVolumizer.muteVolume();
     99                 }
    100                 return true;
    101             default:
    102                 return false;
    103         }
    104     }
    105 
    106     @Override
    107     protected void onDialogClosed(boolean positiveResult) {
    108         super.onDialogClosed(positiveResult);
    109 
    110         if (!positiveResult && mSeekBarVolumizer != null) {
    111             mSeekBarVolumizer.revertVolume();
    112         }
    113 
    114         cleanup();
    115     }
    116 
    117     public void onActivityStop() {
    118         if (mSeekBarVolumizer != null) {
    119             mSeekBarVolumizer.postStopSample();
    120         }
    121     }
    122 
    123     /**
    124      * Do clean up.  This can be called multiple times!
    125      */
    126     private void cleanup() {
    127        getPreferenceManager().unregisterOnActivityStopListener(this);
    128 
    129        if (mSeekBarVolumizer != null) {
    130            Dialog dialog = getDialog();
    131            if (dialog != null && dialog.isShowing()) {
    132                View view = dialog.getWindow().getDecorView()
    133                        .findViewById(com.android.internal.R.id.seekbar);
    134                if (view != null) view.setOnKeyListener(null);
    135                // Stopped while dialog was showing, revert changes
    136                mSeekBarVolumizer.revertVolume();
    137            }
    138            mSeekBarVolumizer.stop();
    139            mSeekBarVolumizer = null;
    140        }
    141 
    142     }
    143 
    144     @Override
    145     public void onSampleStarting(SeekBarVolumizer volumizer) {
    146         if (mSeekBarVolumizer != null && volumizer != mSeekBarVolumizer) {
    147             mSeekBarVolumizer.stopSample();
    148         }
    149     }
    150 
    151     @Override
    152     protected Parcelable onSaveInstanceState() {
    153         final Parcelable superState = super.onSaveInstanceState();
    154         if (isPersistent()) {
    155             // No need to save instance state since it's persistent
    156             return superState;
    157         }
    158 
    159         final SavedState myState = new SavedState(superState);
    160         if (mSeekBarVolumizer != null) {
    161             mSeekBarVolumizer.onSaveInstanceState(myState.getVolumeStore());
    162         }
    163         return myState;
    164     }
    165 
    166     @Override
    167     protected void onRestoreInstanceState(Parcelable state) {
    168         if (state == null || !state.getClass().equals(SavedState.class)) {
    169             // Didn't save state for us in onSaveInstanceState
    170             super.onRestoreInstanceState(state);
    171             return;
    172         }
    173 
    174         SavedState myState = (SavedState) state;
    175         super.onRestoreInstanceState(myState.getSuperState());
    176         if (mSeekBarVolumizer != null) {
    177             mSeekBarVolumizer.onRestoreInstanceState(myState.getVolumeStore());
    178         }
    179     }
    180 
    181     public static class VolumeStore {
    182         public int volume = -1;
    183         public int originalVolume = -1;
    184     }
    185 
    186     private static class SavedState extends BaseSavedState {
    187         VolumeStore mVolumeStore = new VolumeStore();
    188 
    189         public SavedState(Parcel source) {
    190             super(source);
    191             mVolumeStore.volume = source.readInt();
    192             mVolumeStore.originalVolume = source.readInt();
    193         }
    194 
    195         @Override
    196         public void writeToParcel(Parcel dest, int flags) {
    197             super.writeToParcel(dest, flags);
    198             dest.writeInt(mVolumeStore.volume);
    199             dest.writeInt(mVolumeStore.originalVolume);
    200         }
    201 
    202         VolumeStore getVolumeStore() {
    203             return mVolumeStore;
    204         }
    205 
    206         public SavedState(Parcelable superState) {
    207             super(superState);
    208         }
    209 
    210         public static final Parcelable.Creator<SavedState> CREATOR =
    211                 new Parcelable.Creator<SavedState>() {
    212             public SavedState createFromParcel(Parcel in) {
    213                 return new SavedState(in);
    214             }
    215 
    216             public SavedState[] newArray(int size) {
    217                 return new SavedState[size];
    218             }
    219         };
    220     }
    221 }
    222