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
17package com.android.settings;
18
19import android.content.ContentResolver;
20import android.content.Context;
21import android.database.ContentObserver;
22import android.hardware.input.InputManager;
23import android.os.Handler;
24import android.os.Parcel;
25import android.os.Parcelable;
26import android.provider.Settings;
27import android.util.AttributeSet;
28import android.view.View;
29import android.widget.SeekBar;
30
31public 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
48    public PointerSpeedPreference(Context context, AttributeSet attrs) {
49        super(context, attrs);
50        mIm = (InputManager)getContext().getSystemService(Context.INPUT_SERVICE);
51    }
52
53    @Override
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
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
75    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
76        if (!mTouchInProgress) {
77            mIm.tryPointerSpeed(progress + InputManager.MIN_POINTER_SPEED);
78        }
79    }
80
81    public void onStartTrackingTouch(SeekBar seekBar) {
82        mTouchInProgress = true;
83    }
84
85    public void onStopTrackingTouch(SeekBar seekBar) {
86        mTouchInProgress = false;
87        mIm.tryPointerSpeed(seekBar.getProgress() + InputManager.MIN_POINTER_SPEED);
88    }
89
90    private void onSpeedChanged() {
91        int speed = mIm.getPointerSpeed(getContext());
92        mSeekBar.setProgress(speed - InputManager.MIN_POINTER_SPEED);
93    }
94
95    @Override
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
111    private void restoreOldState() {
112        if (mRestoredOldState) return;
113
114        mIm.tryPointerSpeed(mOldSpeed);
115        mRestoredOldState = true;
116    }
117
118    @Override
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
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
151        public SavedState(Parcel source) {
152            super(source);
153            progress = source.readInt();
154            oldSpeed = source.readInt();
155        }
156
157        @Override
158        public void writeToParcel(Parcel dest, int flags) {
159            super.writeToParcel(dest, flags);
160            dest.writeInt(progress);
161            dest.writeInt(oldSpeed);
162        }
163
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