1/*
2 * Copyright (C) 2014 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.content.Context;
20import android.content.Intent;
21import android.content.SharedPreferences;
22import android.content.res.Resources;
23import android.os.Bundle;
24import android.os.Process;
25import android.preference.Preference;
26import android.preference.Preference.OnPreferenceClickListener;
27import android.preference.PreferenceGroup;
28import android.preference.TwoStatePreference;
29
30import com.android.inputmethod.latin.DictionaryDumpBroadcastReceiver;
31import com.android.inputmethod.latin.DictionaryFacilitatorImpl;
32import com.android.inputmethod.latin.R;
33import com.android.inputmethod.latin.utils.ApplicationUtils;
34import com.android.inputmethod.latin.utils.ResourceUtils;
35
36import java.util.Locale;
37
38/**
39 * "Debug mode" settings sub screen.
40 *
41 * This settings sub screen handles a several preference options for debugging.
42 */
43public final class DebugSettingsFragment extends SubScreenFragment
44        implements OnPreferenceClickListener {
45    private static final String PREF_KEY_DUMP_DICTS = "pref_key_dump_dictionaries";
46    private static final String PREF_KEY_DUMP_DICT_PREFIX = "pref_key_dump_dictionaries";
47
48    private boolean mServiceNeedsRestart = false;
49    private TwoStatePreference mDebugMode;
50
51    @Override
52    public void onCreate(Bundle icicle) {
53        super.onCreate(icicle);
54        addPreferencesFromResource(R.xml.prefs_screen_debug);
55
56        if (!Settings.SHOULD_SHOW_LXX_SUGGESTION_UI) {
57            removePreference(DebugSettings.PREF_SHOULD_SHOW_LXX_SUGGESTION_UI);
58        }
59
60        final PreferenceGroup dictDumpPreferenceGroup =
61                (PreferenceGroup)findPreference(PREF_KEY_DUMP_DICTS);
62        for (final String dictName : DictionaryFacilitatorImpl.DICT_TYPE_TO_CLASS.keySet()) {
63            final Preference pref = new DictDumpPreference(getActivity(), dictName);
64            pref.setOnPreferenceClickListener(this);
65            dictDumpPreferenceGroup.addPreference(pref);
66        }
67        final Resources res = getResources();
68        setupKeyPreviewAnimationDuration(DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION,
69                res.getInteger(R.integer.config_key_preview_show_up_duration));
70        setupKeyPreviewAnimationDuration(DebugSettings.PREF_KEY_PREVIEW_DISMISS_DURATION,
71                res.getInteger(R.integer.config_key_preview_dismiss_duration));
72        final float defaultKeyPreviewShowUpStartScale = ResourceUtils.getFloatFromFraction(
73                res, R.fraction.config_key_preview_show_up_start_scale);
74        final float defaultKeyPreviewDismissEndScale = ResourceUtils.getFloatFromFraction(
75                res, R.fraction.config_key_preview_dismiss_end_scale);
76        setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_X_SCALE,
77                defaultKeyPreviewShowUpStartScale);
78        setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_Y_SCALE,
79                defaultKeyPreviewShowUpStartScale);
80        setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_X_SCALE,
81                defaultKeyPreviewDismissEndScale);
82        setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE,
83                defaultKeyPreviewDismissEndScale);
84        setupKeyboardHeight(
85                DebugSettings.PREF_KEYBOARD_HEIGHT_SCALE, SettingsValues.DEFAULT_SIZE_SCALE);
86
87        mServiceNeedsRestart = false;
88        mDebugMode = (TwoStatePreference) findPreference(DebugSettings.PREF_DEBUG_MODE);
89        updateDebugMode();
90    }
91
92    private static class DictDumpPreference extends Preference {
93        public final String mDictName;
94
95        public DictDumpPreference(final Context context, final String dictName) {
96            super(context);
97            setKey(PREF_KEY_DUMP_DICT_PREFIX + dictName);
98            setTitle("Dump " + dictName + " dictionary");
99            mDictName = dictName;
100        }
101    }
102
103    @Override
104    public boolean onPreferenceClick(final Preference pref) {
105        final Context context = getActivity();
106        if (pref instanceof DictDumpPreference) {
107            final DictDumpPreference dictDumpPref = (DictDumpPreference)pref;
108            final String dictName = dictDumpPref.mDictName;
109            final Intent intent = new Intent(
110                    DictionaryDumpBroadcastReceiver.DICTIONARY_DUMP_INTENT_ACTION);
111            intent.putExtra(DictionaryDumpBroadcastReceiver.DICTIONARY_NAME_KEY, dictName);
112            context.sendBroadcast(intent);
113            return true;
114        }
115        return true;
116    }
117
118    @Override
119    public void onStop() {
120        super.onStop();
121        if (mServiceNeedsRestart) {
122            Process.killProcess(Process.myPid());
123        }
124    }
125
126    @Override
127    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
128        if (key.equals(DebugSettings.PREF_DEBUG_MODE) && mDebugMode != null) {
129            mDebugMode.setChecked(prefs.getBoolean(DebugSettings.PREF_DEBUG_MODE, false));
130            updateDebugMode();
131            mServiceNeedsRestart = true;
132            return;
133        }
134        if (key.equals(DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH)) {
135            mServiceNeedsRestart = true;
136            return;
137        }
138    }
139
140    private void updateDebugMode() {
141        boolean isDebugMode = mDebugMode.isChecked();
142        final String version = getString(
143                R.string.version_text, ApplicationUtils.getVersionName(getActivity()));
144        if (!isDebugMode) {
145            mDebugMode.setTitle(version);
146            mDebugMode.setSummary(null);
147        } else {
148            mDebugMode.setTitle(getString(R.string.prefs_debug_mode));
149            mDebugMode.setSummary(version);
150        }
151    }
152
153    private void setupKeyPreviewAnimationScale(final String prefKey, final float defaultValue) {
154        final SharedPreferences prefs = getSharedPreferences();
155        final Resources res = getResources();
156        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey);
157        if (pref == null) {
158            return;
159        }
160        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
161            private static final float PERCENTAGE_FLOAT = 100.0f;
162
163            private float getValueFromPercentage(final int percentage) {
164                return percentage / PERCENTAGE_FLOAT;
165            }
166
167            private int getPercentageFromValue(final float floatValue) {
168                return (int)(floatValue * PERCENTAGE_FLOAT);
169            }
170
171            @Override
172            public void writeValue(final int value, final String key) {
173                prefs.edit().putFloat(key, getValueFromPercentage(value)).apply();
174            }
175
176            @Override
177            public void writeDefaultValue(final String key) {
178                prefs.edit().remove(key).apply();
179            }
180
181            @Override
182            public int readValue(final String key) {
183                return getPercentageFromValue(
184                        Settings.readKeyPreviewAnimationScale(prefs, key, defaultValue));
185            }
186
187            @Override
188            public int readDefaultValue(final String key) {
189                return getPercentageFromValue(defaultValue);
190            }
191
192            @Override
193            public String getValueText(final int value) {
194                if (value < 0) {
195                    return res.getString(R.string.settings_system_default);
196                }
197                return String.format(Locale.ROOT, "%d%%", value);
198            }
199
200            @Override
201            public void feedbackValue(final int value) {}
202        });
203    }
204
205    private void setupKeyPreviewAnimationDuration(final String prefKey, final int defaultValue) {
206        final SharedPreferences prefs = getSharedPreferences();
207        final Resources res = getResources();
208        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey);
209        if (pref == null) {
210            return;
211        }
212        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
213            @Override
214            public void writeValue(final int value, final String key) {
215                prefs.edit().putInt(key, value).apply();
216            }
217
218            @Override
219            public void writeDefaultValue(final String key) {
220                prefs.edit().remove(key).apply();
221            }
222
223            @Override
224            public int readValue(final String key) {
225                return Settings.readKeyPreviewAnimationDuration(prefs, key, defaultValue);
226            }
227
228            @Override
229            public int readDefaultValue(final String key) {
230                return defaultValue;
231            }
232
233            @Override
234            public String getValueText(final int value) {
235                return res.getString(R.string.abbreviation_unit_milliseconds, value);
236            }
237
238            @Override
239            public void feedbackValue(final int value) {}
240        });
241    }
242
243    private void setupKeyboardHeight(final String prefKey, final float defaultValue) {
244        final SharedPreferences prefs = getSharedPreferences();
245        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey);
246        if (pref == null) {
247            return;
248        }
249        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
250            private static final float PERCENTAGE_FLOAT = 100.0f;
251            private float getValueFromPercentage(final int percentage) {
252                return percentage / PERCENTAGE_FLOAT;
253            }
254
255            private int getPercentageFromValue(final float floatValue) {
256                return (int)(floatValue * PERCENTAGE_FLOAT);
257            }
258
259            @Override
260            public void writeValue(final int value, final String key) {
261                prefs.edit().putFloat(key, getValueFromPercentage(value)).apply();
262            }
263
264            @Override
265            public void writeDefaultValue(final String key) {
266                prefs.edit().remove(key).apply();
267            }
268
269            @Override
270            public int readValue(final String key) {
271                return getPercentageFromValue(Settings.readKeyboardHeight(prefs, defaultValue));
272            }
273
274            @Override
275            public int readDefaultValue(final String key) {
276                return getPercentageFromValue(defaultValue);
277            }
278
279            @Override
280            public String getValueText(final int value) {
281                return String.format(Locale.ROOT, "%d%%", value);
282            }
283
284            @Override
285            public void feedbackValue(final int value) {}
286        });
287    }
288}
289