1 /*
2  * Copyright (C) 2011 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 com.android.settings;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.database.ContentObserver;
22 import android.hardware.input.InputManager;
23 import android.os.Handler;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.provider.Settings;
27 import android.util.AttributeSet;
28 import android.view.View;
29 import android.widget.SeekBar;
30 
31 public class PointerSpeedPreference extends SeekBarDialogPreference implements
32         SeekBar.OnSeekBarChangeListener {
33     private final InputManager mIm;
34     private SeekBar mSeekBar;
35 
36     private int mOldSpeed;
37     private boolean mRestoredOldState;
38 
39     private boolean mTouchInProgress;
40 
41     private ContentObserver mSpeedObserver = new ContentObserver(new Handler()) {
42         @Override
43         public void onChange(boolean selfChange) {
44             onSpeedChanged();
45         }
46     };
47 
PointerSpeedPreference(Context context, AttributeSet attrs)48     public PointerSpeedPreference(Context context, AttributeSet attrs) {
49         super(context, attrs);
50         mIm = (InputManager)getContext().getSystemService(Context.INPUT_SERVICE);
51     }
52 
53     @Override
onClick()54     protected void onClick() {
55         super.onClick();
56 
57         getContext().getContentResolver().registerContentObserver(
58                 Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
59                 mSpeedObserver);
60 
61         mRestoredOldState = false;
62     }
63 
64     @Override
onBindDialogView(View view)65     protected void onBindDialogView(View view) {
66         super.onBindDialogView(view);
67 
68         mSeekBar = getSeekBar(view);
69         mSeekBar.setMax(InputManager.MAX_POINTER_SPEED - InputManager.MIN_POINTER_SPEED);
70         mOldSpeed = mIm.getPointerSpeed(getContext());
71         mSeekBar.setProgress(mOldSpeed - InputManager.MIN_POINTER_SPEED);
72         mSeekBar.setOnSeekBarChangeListener(this);
73     }
74 
onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch)75     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
76         if (!mTouchInProgress) {
77             mIm.tryPointerSpeed(progress + InputManager.MIN_POINTER_SPEED);
78         }
79     }
80 
onStartTrackingTouch(SeekBar seekBar)81     public void onStartTrackingTouch(SeekBar seekBar) {
82         mTouchInProgress = true;
83     }
84 
onStopTrackingTouch(SeekBar seekBar)85     public void onStopTrackingTouch(SeekBar seekBar) {
86         mTouchInProgress = false;
87         mIm.tryPointerSpeed(seekBar.getProgress() + InputManager.MIN_POINTER_SPEED);
88     }
89 
onSpeedChanged()90     private void onSpeedChanged() {
91         int speed = mIm.getPointerSpeed(getContext());
92         mSeekBar.setProgress(speed - InputManager.MIN_POINTER_SPEED);
93     }
94 
95     @Override
onDialogClosed(boolean positiveResult)96     protected void onDialogClosed(boolean positiveResult) {
97         super.onDialogClosed(positiveResult);
98 
99         final ContentResolver resolver = getContext().getContentResolver();
100 
101         if (positiveResult) {
102             mIm.setPointerSpeed(getContext(),
103                     mSeekBar.getProgress() + InputManager.MIN_POINTER_SPEED);
104         } else {
105             restoreOldState();
106         }
107 
108         resolver.unregisterContentObserver(mSpeedObserver);
109     }
110 
restoreOldState()111     private void restoreOldState() {
112         if (mRestoredOldState) return;
113 
114         mIm.tryPointerSpeed(mOldSpeed);
115         mRestoredOldState = true;
116     }
117 
118     @Override
onSaveInstanceState()119     protected Parcelable onSaveInstanceState() {
120         final Parcelable superState = super.onSaveInstanceState();
121         if (getDialog() == null || !getDialog().isShowing()) return superState;
122 
123         // Save the dialog state
124         final SavedState myState = new SavedState(superState);
125         myState.progress = mSeekBar.getProgress();
126         myState.oldSpeed = mOldSpeed;
127 
128         // Restore the old state when the activity or dialog is being paused
129         restoreOldState();
130         return myState;
131     }
132 
133     @Override
onRestoreInstanceState(Parcelable state)134     protected void onRestoreInstanceState(Parcelable state) {
135         if (state == null || !state.getClass().equals(SavedState.class)) {
136             // Didn't save state for us in onSaveInstanceState
137             super.onRestoreInstanceState(state);
138             return;
139         }
140 
141         SavedState myState = (SavedState) state;
142         super.onRestoreInstanceState(myState.getSuperState());
143         mOldSpeed = myState.oldSpeed;
144         mIm.tryPointerSpeed(myState.progress + InputManager.MIN_POINTER_SPEED);
145     }
146 
147     private static class SavedState extends BaseSavedState {
148         int progress;
149         int oldSpeed;
150 
SavedState(Parcel source)151         public SavedState(Parcel source) {
152             super(source);
153             progress = source.readInt();
154             oldSpeed = source.readInt();
155         }
156 
157         @Override
writeToParcel(Parcel dest, int flags)158         public void writeToParcel(Parcel dest, int flags) {
159             super.writeToParcel(dest, flags);
160             dest.writeInt(progress);
161             dest.writeInt(oldSpeed);
162         }
163 
SavedState(Parcelable superState)164         public SavedState(Parcelable superState) {
165             super(superState);
166         }
167 
168         public static final Parcelable.Creator<SavedState> CREATOR =
169                 new Parcelable.Creator<SavedState>() {
170 
171             public SavedState createFromParcel(Parcel in) {
172                 return new SavedState(in);
173             }
174 
175             public SavedState[] newArray(int size) {
176                 return new SavedState[size];
177             }
178         };
179     }
180 }
181 
182