• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.tts;
18 
19 import com.android.settings.R;
20 
21 import android.content.Context;
22 import android.content.Intent;
23 import android.os.Bundle;
24 import android.preference.Preference;
25 import android.preference.PreferenceActivity;
26 import android.speech.tts.TextToSpeech.EngineInfo;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.widget.Checkable;
30 import android.widget.CompoundButton;
31 import android.widget.RadioButton;
32 
33 
34 public class TtsEnginePreference extends Preference {
35 
36     /**
37      * Key for the name of the TTS engine passed in to the engine
38      * settings fragment {@link TtsEngineSettingsFragment}.
39      */
40     static final String FRAGMENT_ARGS_NAME = "name";
41 
42     /**
43      * Key for the label of the TTS engine passed in to the engine
44      * settings fragment. This is used as the title of the fragment
45      * {@link TtsEngineSettingsFragment}.
46      */
47     static final String FRAGMENT_ARGS_LABEL = "label";
48 
49     /**
50      * Key for the voice data data passed in to the engine settings
51      * fragmetn {@link TtsEngineSettingsFragment}.
52      */
53     static final String FRAGMENT_ARGS_VOICES = "voices";
54 
55     /**
56      * The preference activity that owns this preference. Required
57      * for instantiating the engine specific settings screen.
58      */
59     private final PreferenceActivity mPreferenceActivity;
60 
61     /**
62      * The engine information for the engine this preference represents.
63      * Contains it's name, label etc. which are used for display.
64      */
65     private final EngineInfo mEngineInfo;
66 
67     /**
68      * The shared radio button state, which button is checked etc.
69      */
70     private final RadioButtonGroupState mSharedState;
71 
72     /**
73      * When true, the change callbacks on the radio button will not
74      * fire.
75      */
76     private volatile boolean mPreventRadioButtonCallbacks;
77 
78     private View mSettingsIcon;
79     private RadioButton mRadioButton;
80     private Intent mVoiceCheckData;
81 
82     private final CompoundButton.OnCheckedChangeListener mRadioChangeListener =
83         new CompoundButton.OnCheckedChangeListener() {
84             @Override
85             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
86                 onRadioButtonClicked(buttonView, isChecked);
87             }
88         };
89 
TtsEnginePreference(Context context, EngineInfo info, RadioButtonGroupState state, PreferenceActivity prefActivity)90     public TtsEnginePreference(Context context, EngineInfo info, RadioButtonGroupState state,
91             PreferenceActivity prefActivity) {
92         super(context);
93         setLayoutResource(R.layout.preference_tts_engine);
94 
95         mSharedState = state;
96         mPreferenceActivity = prefActivity;
97         mEngineInfo = info;
98         mPreventRadioButtonCallbacks = false;
99 
100         setKey(mEngineInfo.name);
101         setTitle(mEngineInfo.label);
102     }
103 
104     @Override
getView(View convertView, ViewGroup parent)105     public View getView(View convertView, ViewGroup parent) {
106         if (mSharedState == null) {
107             throw new IllegalStateException("Call to getView() before a call to" +
108                     "setSharedState()");
109         }
110 
111         View view = super.getView(convertView, parent);
112         final RadioButton rb = (RadioButton) view.findViewById(R.id.tts_engine_radiobutton);
113         rb.setOnCheckedChangeListener(mRadioChangeListener);
114 
115         boolean isChecked = getKey().equals(mSharedState.getCurrentKey());
116         if (isChecked) {
117             mSharedState.setCurrentChecked(rb);
118         }
119 
120         mPreventRadioButtonCallbacks = true;
121         rb.setChecked(isChecked);
122         mPreventRadioButtonCallbacks = false;
123 
124         mRadioButton = rb;
125 
126         View textLayout = view.findViewById(R.id.tts_engine_pref_text);
127         textLayout.setOnClickListener(new View.OnClickListener() {
128             @Override
129             public void onClick(View v) {
130                 onRadioButtonClicked(rb, !rb.isChecked());
131             }
132         });
133 
134         mSettingsIcon = view.findViewById(R.id.tts_engine_settings);
135         // Will be enabled only the engine has passed the voice check, and
136         // is currently enabled.
137         mSettingsIcon.setEnabled(isChecked && mVoiceCheckData != null);
138         mSettingsIcon.setOnClickListener(new View.OnClickListener() {
139             @Override
140             public void onClick(View v) {
141                 Bundle args = new Bundle();
142                 args.putString(FRAGMENT_ARGS_NAME, mEngineInfo.name);
143                 args.putString(FRAGMENT_ARGS_LABEL, mEngineInfo.label);
144                 if (mVoiceCheckData != null) {
145                     args.putParcelable(FRAGMENT_ARGS_VOICES, mVoiceCheckData);
146                 }
147 
148                 // Note that we use this instead of the (easier to use)
149                 // PreferenceActivity.startPreferenceFragment because the
150                 // title will not be updated correctly in the fragment
151                 // breadcrumb since it isn't inflated from the XML layout.
152                 mPreferenceActivity.startPreferencePanel(
153                         TtsEngineSettingsFragment.class.getName(),
154                         args, 0, mEngineInfo.label, null, 0);
155             }
156         });
157 
158         if (mVoiceCheckData != null) {
159             mSettingsIcon.setEnabled(mRadioButton.isChecked());
160         }
161 
162         return view;
163     }
164 
setVoiceDataDetails(Intent data)165     public void setVoiceDataDetails(Intent data) {
166         mVoiceCheckData = data;
167         // This might end up running before getView aboive, in which
168         // case mSettingsIcon && mRadioButton will be null. In this case
169         // getView will set the right values.
170         if (mSettingsIcon != null && mRadioButton != null) {
171             mSettingsIcon.setEnabled(mRadioButton.isChecked());
172         }
173     }
174 
onRadioButtonClicked(CompoundButton buttonView, boolean isChecked)175     private void onRadioButtonClicked(CompoundButton buttonView, boolean isChecked) {
176         if (mPreventRadioButtonCallbacks) {
177             return;
178         }
179 
180         if (isChecked) {
181             if (mSharedState.getCurrentChecked() != null) {
182                 mSharedState.getCurrentChecked().setChecked(false);
183             }
184             mSharedState.setCurrentChecked(buttonView);
185             mSharedState.setCurrentKey(getKey());
186             callChangeListener(mSharedState.getCurrentKey());
187         }
188 
189         mSettingsIcon.setEnabled(isChecked);
190     }
191 
192 
193     /**
194      * Holds all state that is common to this group of radio buttons, such
195      * as the currently selected key and the currently checked compound button.
196      * (which corresponds to this key).
197      */
198     public interface RadioButtonGroupState {
getCurrentKey()199         String getCurrentKey();
getCurrentChecked()200         Checkable getCurrentChecked();
201 
setCurrentKey(String key)202         void setCurrentKey(String key);
setCurrentChecked(Checkable current)203         void setCurrentChecked(Checkable current);
204     }
205 
206 }
207