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 import com.android.internal.R;
     30 
     31 /**
     32  * @hide
     33  */
     34 public class VolumePreference extends SeekBarDialogPreference implements
     35         PreferenceManager.OnActivityStopListener, View.OnKeyListener, SeekBarVolumizer.Callback {
     36     private int mStreamType;
     37 
     38     /** May be null if the dialog isn't visible. */
     39     private SeekBarVolumizer mSeekBarVolumizer;
     40 
     41     public VolumePreference(
     42             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
     43         super(context, attrs, defStyleAttr, defStyleRes);
     44 
     45         final TypedArray a = context.obtainStyledAttributes(attrs,
     46                 R.styleable.VolumePreference, defStyleAttr, defStyleRes);
     47         mStreamType = a.getInt(android.R.styleable.VolumePreference_streamType, 0);
     48         a.recycle();
     49     }
     50 
     51     public VolumePreference(Context context, AttributeSet attrs, int defStyleAttr) {
     52         this(context, attrs, defStyleAttr, 0);
     53     }
     54 
     55     public VolumePreference(Context context, AttributeSet attrs) {
     56         this(context, attrs, R.attr.seekBarDialogPreferenceStyle);
     57     }
     58 
     59     public VolumePreference(Context context) {
     60         this(context, null);
     61     }
     62 
     63     public void setStreamType(int streamType) {
     64         mStreamType = streamType;
     65     }
     66 
     67     @Override
     68     protected void onBindDialogView(View view) {
     69         super.onBindDialogView(view);
     70 
     71         final SeekBar seekBar = (SeekBar) view.findViewById(R.id.seekbar);
     72         mSeekBarVolumizer = new SeekBarVolumizer(getContext(), mStreamType, null, this);
     73         mSeekBarVolumizer.start();
     74         mSeekBarVolumizer.setSeekBar(seekBar);
     75 
     76         getPreferenceManager().registerOnActivityStopListener(this);
     77 
     78         // grab focus and key events so that pressing the volume buttons in the
     79         // dialog doesn't also show the normal volume adjust toast.
     80         view.setOnKeyListener(this);
     81         view.setFocusableInTouchMode(true);
     82         view.requestFocus();
     83     }
     84 
     85     public boolean onKey(View v, int keyCode, KeyEvent event) {
     86         // If key arrives immediately after the activity has been cleaned up.
     87         if (mSeekBarVolumizer == null) return true;
     88         boolean isdown = (event.getAction() == KeyEvent.ACTION_DOWN);
     89         switch (keyCode) {
     90             case KeyEvent.KEYCODE_VOLUME_DOWN:
     91                 if (isdown) {
     92                     mSeekBarVolumizer.changeVolumeBy(-1);
     93                 }
     94                 return true;
     95             case KeyEvent.KEYCODE_VOLUME_UP:
     96                 if (isdown) {
     97                     mSeekBarVolumizer.changeVolumeBy(1);
     98                 }
     99                 return true;
    100             case KeyEvent.KEYCODE_VOLUME_MUTE:
    101                 if (isdown) {
    102                     mSeekBarVolumizer.muteVolume();
    103                 }
    104                 return true;
    105             default:
    106                 return false;
    107         }
    108     }
    109 
    110     @Override
    111     protected void onDialogClosed(boolean positiveResult) {
    112         super.onDialogClosed(positiveResult);
    113 
    114         if (!positiveResult && mSeekBarVolumizer != null) {
    115             mSeekBarVolumizer.revertVolume();
    116         }
    117 
    118         cleanup();
    119     }
    120 
    121     public void onActivityStop() {
    122         if (mSeekBarVolumizer != null) {
    123             mSeekBarVolumizer.stopSample();
    124         }
    125     }
    126 
    127     /**
    128      * Do clean up.  This can be called multiple times!
    129      */
    130     private void cleanup() {
    131        getPreferenceManager().unregisterOnActivityStopListener(this);
    132 
    133        if (mSeekBarVolumizer != null) {
    134            final Dialog dialog = getDialog();
    135            if (dialog != null && dialog.isShowing()) {
    136                final View view = dialog.getWindow().getDecorView().findViewById(R.id.seekbar);
    137                if (view != null) {
    138                    view.setOnKeyListener(null);
    139                }
    140 
    141                // Stopped while dialog was showing, revert changes
    142                mSeekBarVolumizer.revertVolume();
    143            }
    144 
    145            mSeekBarVolumizer.stop();
    146            mSeekBarVolumizer = null;
    147        }
    148 
    149     }
    150 
    151     @Override
    152     public void onSampleStarting(SeekBarVolumizer volumizer) {
    153         if (mSeekBarVolumizer != null && volumizer != mSeekBarVolumizer) {
    154             mSeekBarVolumizer.stopSample();
    155         }
    156     }
    157 
    158     @Override
    159     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
    160         // noop
    161     }
    162 
    163     @Override
    164     public void onMuted(boolean muted, boolean zenMuted) {
    165         // noop
    166     }
    167 
    168     @Override
    169     protected Parcelable onSaveInstanceState() {
    170         final Parcelable superState = super.onSaveInstanceState();
    171         if (isPersistent()) {
    172             // No need to save instance state since it's persistent
    173             return superState;
    174         }
    175 
    176         final SavedState myState = new SavedState(superState);
    177         if (mSeekBarVolumizer != null) {
    178             mSeekBarVolumizer.onSaveInstanceState(myState.getVolumeStore());
    179         }
    180         return myState;
    181     }
    182 
    183     @Override
    184     protected void onRestoreInstanceState(Parcelable state) {
    185         if (state == null || !state.getClass().equals(SavedState.class)) {
    186             // Didn't save state for us in onSaveInstanceState
    187             super.onRestoreInstanceState(state);
    188             return;
    189         }
    190 
    191         SavedState myState = (SavedState) state;
    192         super.onRestoreInstanceState(myState.getSuperState());
    193         if (mSeekBarVolumizer != null) {
    194             mSeekBarVolumizer.onRestoreInstanceState(myState.getVolumeStore());
    195         }
    196     }
    197 
    198     public static class VolumeStore {
    199         public int volume = -1;
    200         public int originalVolume = -1;
    201     }
    202 
    203     private static class SavedState extends BaseSavedState {
    204         VolumeStore mVolumeStore = new VolumeStore();
    205 
    206         public SavedState(Parcel source) {
    207             super(source);
    208             mVolumeStore.volume = source.readInt();
    209             mVolumeStore.originalVolume = source.readInt();
    210         }
    211 
    212         @Override
    213         public void writeToParcel(Parcel dest, int flags) {
    214             super.writeToParcel(dest, flags);
    215             dest.writeInt(mVolumeStore.volume);
    216             dest.writeInt(mVolumeStore.originalVolume);
    217         }
    218 
    219         VolumeStore getVolumeStore() {
    220             return mVolumeStore;
    221         }
    222 
    223         public SavedState(Parcelable superState) {
    224             super(superState);
    225         }
    226 
    227         public static final Parcelable.Creator<SavedState> CREATOR =
    228                 new Parcelable.Creator<SavedState>() {
    229             public SavedState createFromParcel(Parcel in) {
    230                 return new SavedState(in);
    231             }
    232 
    233             public SavedState[] newArray(int size) {
    234                 return new SavedState[size];
    235             }
    236         };
    237     }
    238 }
    239