1/*
2 * Copyright (C) 2013 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.inputmethod.latin.settings;
18
19import android.app.AlertDialog;
20import android.content.Context;
21import android.content.DialogInterface;
22import android.content.res.TypedArray;
23import android.preference.DialogPreference;
24import android.util.AttributeSet;
25import android.view.View;
26import android.widget.SeekBar;
27import android.widget.TextView;
28
29import com.android.inputmethod.latin.R;
30
31public final class SeekBarDialogPreference extends DialogPreference
32        implements SeekBar.OnSeekBarChangeListener {
33    public interface ValueProxy {
34        public int readValue(final String key);
35        public int readDefaultValue(final String key);
36        public void writeValue(final int value, final String key);
37        public void writeDefaultValue(final String key);
38        public String getValueText(final int value);
39        public void feedbackValue(final int value);
40    }
41
42    private final int mMaxValue;
43    private final int mMinValue;
44    private final int mStepValue;
45
46    private TextView mValueView;
47    private SeekBar mSeekBar;
48
49    private ValueProxy mValueProxy;
50
51    public SeekBarDialogPreference(final Context context, final AttributeSet attrs) {
52        super(context, attrs);
53        final TypedArray a = context.obtainStyledAttributes(
54                attrs, R.styleable.SeekBarDialogPreference, 0, 0);
55        mMaxValue = a.getInt(R.styleable.SeekBarDialogPreference_maxValue, 0);
56        mMinValue = a.getInt(R.styleable.SeekBarDialogPreference_minValue, 0);
57        mStepValue = a.getInt(R.styleable.SeekBarDialogPreference_stepValue, 0);
58        a.recycle();
59        setDialogLayoutResource(R.layout.seek_bar_dialog);
60    }
61
62    public void setInterface(final ValueProxy proxy) {
63        mValueProxy = proxy;
64        final int value = mValueProxy.readValue(getKey());
65        setSummary(mValueProxy.getValueText(value));
66    }
67
68    @Override
69    protected View onCreateDialogView() {
70        final View view = super.onCreateDialogView();
71        mSeekBar = (SeekBar)view.findViewById(R.id.seek_bar_dialog_bar);
72        mSeekBar.setMax(mMaxValue - mMinValue);
73        mSeekBar.setOnSeekBarChangeListener(this);
74        mValueView = (TextView)view.findViewById(R.id.seek_bar_dialog_value);
75        return view;
76    }
77
78    private int getProgressFromValue(final int value) {
79        return value - mMinValue;
80    }
81
82    private int getValueFromProgress(final int progress) {
83        return progress + mMinValue;
84    }
85
86    private int clipValue(final int value) {
87        final int clippedValue = Math.min(mMaxValue, Math.max(mMinValue, value));
88        if (mStepValue <= 1) {
89            return clippedValue;
90        }
91        return clippedValue - (clippedValue % mStepValue);
92    }
93
94    private int getClippedValueFromProgress(final int progress) {
95        return clipValue(getValueFromProgress(progress));
96    }
97
98    @Override
99    protected void onBindDialogView(final View view) {
100        final int value = mValueProxy.readValue(getKey());
101        mValueView.setText(mValueProxy.getValueText(value));
102        mSeekBar.setProgress(getProgressFromValue(clipValue(value)));
103    }
104
105    @Override
106    protected void onPrepareDialogBuilder(final AlertDialog.Builder builder) {
107        builder.setPositiveButton(android.R.string.ok, this)
108            .setNegativeButton(android.R.string.cancel, this)
109            .setNeutralButton(R.string.button_default, this);
110    }
111
112    @Override
113    public void onClick(final DialogInterface dialog, final int which) {
114        super.onClick(dialog, which);
115        final String key = getKey();
116        if (which == DialogInterface.BUTTON_NEUTRAL) {
117            final int value = mValueProxy.readDefaultValue(key);
118            setSummary(mValueProxy.getValueText(value));
119            mValueProxy.writeDefaultValue(key);
120            return;
121        }
122        if (which == DialogInterface.BUTTON_POSITIVE) {
123            final int value = getClippedValueFromProgress(mSeekBar.getProgress());
124            setSummary(mValueProxy.getValueText(value));
125            mValueProxy.writeValue(value, key);
126            return;
127        }
128    }
129
130    @Override
131    public void onProgressChanged(final SeekBar seekBar, final int progress,
132            final boolean fromUser) {
133        final int value = getClippedValueFromProgress(progress);
134        mValueView.setText(mValueProxy.getValueText(value));
135        if (!fromUser) {
136            mSeekBar.setProgress(getProgressFromValue(value));
137        }
138    }
139
140    @Override
141    public void onStartTrackingTouch(final SeekBar seekBar) {}
142
143    @Override
144    public void onStopTrackingTouch(final SeekBar seekBar) {
145        mValueProxy.feedbackValue(getClippedValueFromProgress(seekBar.getProgress()));
146    }
147}
148