10cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath/* 20cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * Copyright (C) 2011 The Android Open Source Project 30cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * 40cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * Licensed under the Apache License, Version 2.0 (the "License"); 50cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * you may not use this file except in compliance with the License. 60cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * You may obtain a copy of the License at 70cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * 80cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * http://www.apache.org/licenses/LICENSE-2.0 90cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * 100cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * Unless required by applicable law or agreed to in writing, software 110cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * distributed under the License is distributed on an "AS IS" BASIS, 120cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * See the License for the specific language governing permissions and 140cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * limitations under the License. 150cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath */ 160cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 170cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathpackage com.android.settings.tts; 180cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 190cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport com.android.settings.R; 200cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 210cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.content.Context; 220cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.content.Intent; 230cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.os.Bundle; 240cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.preference.Preference; 250cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.preference.PreferenceActivity; 260cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.speech.tts.TextToSpeech.EngineInfo; 270cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.view.View; 280cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.view.ViewGroup; 290cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.widget.Checkable; 300cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.widget.CompoundButton; 310cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathimport android.widget.RadioButton; 320cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 330cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 340cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamathpublic class TtsEnginePreference extends Preference { 350cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 360cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath /** 370cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * Key for the name of the TTS engine passed in to the engine 380cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * settings fragment {@link TtsEngineSettingsFragment}. 390cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath */ 400cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath static final String FRAGMENT_ARGS_NAME = "name"; 410cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 420cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath /** 430cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * Key for the label of the TTS engine passed in to the engine 440cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * settings fragment. This is used as the title of the fragment 450cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * {@link TtsEngineSettingsFragment}. 460cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath */ 470cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath static final String FRAGMENT_ARGS_LABEL = "label"; 480cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 490cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath /** 500cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * Key for the voice data data passed in to the engine settings 510cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * fragmetn {@link TtsEngineSettingsFragment}. 520cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath */ 530cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath static final String FRAGMENT_ARGS_VOICES = "voices"; 540cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 550cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath /** 560cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * The preference activity that owns this preference. Required 570cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * for instantiating the engine specific settings screen. 580cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath */ 590cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath private final PreferenceActivity mPreferenceActivity; 600cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 610cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath /** 620cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * The engine information for the engine this preference represents. 630cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * Contains it's name, label etc. which are used for display. 640cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath */ 650cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath private final EngineInfo mEngineInfo; 660cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 670cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath /** 680cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * The shared radio button state, which button is checked etc. 690cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath */ 700cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath private final RadioButtonGroupState mSharedState; 710cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 720cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath /** 730cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * When true, the change callbacks on the radio button will not 740cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * fire. 750cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath */ 760cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath private volatile boolean mPreventRadioButtonCallbacks; 770cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 780cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath private View mSettingsIcon; 790cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath private RadioButton mRadioButton; 800cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath private Intent mVoiceCheckData; 810cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 820cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath private final CompoundButton.OnCheckedChangeListener mRadioChangeListener = 830cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath new CompoundButton.OnCheckedChangeListener() { 840cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath @Override 850cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 860cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath onRadioButtonClicked(buttonView, isChecked); 870cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 880cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath }; 890cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 900cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath public TtsEnginePreference(Context context, EngineInfo info, RadioButtonGroupState state, 910cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath PreferenceActivity prefActivity) { 920cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath super(context); 930cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath setLayoutResource(R.layout.preference_tts_engine); 940cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 950cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mSharedState = state; 960cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mPreferenceActivity = prefActivity; 970cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mEngineInfo = info; 980cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mPreventRadioButtonCallbacks = false; 990cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1000cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath setKey(mEngineInfo.name); 1010cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath setTitle(mEngineInfo.label); 1020cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1030cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1040cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath @Override 1050cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath public View getView(View convertView, ViewGroup parent) { 1060cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath if (mSharedState == null) { 1070cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath throw new IllegalStateException("Call to getView() before a call to" + 1080cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath "setSharedState()"); 1090cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1100cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1110cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath View view = super.getView(convertView, parent); 1120cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath final RadioButton rb = (RadioButton) view.findViewById(R.id.tts_engine_radiobutton); 1130cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath rb.setOnCheckedChangeListener(mRadioChangeListener); 1140cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1150cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath boolean isChecked = getKey().equals(mSharedState.getCurrentKey()); 1160cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath if (isChecked) { 1170cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mSharedState.setCurrentChecked(rb); 1180cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1190cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1200cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mPreventRadioButtonCallbacks = true; 1210cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath rb.setChecked(isChecked); 1220cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mPreventRadioButtonCallbacks = false; 1230cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1240cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mRadioButton = rb; 1250cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1260cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath View textLayout = view.findViewById(R.id.tts_engine_pref_text); 1270cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath textLayout.setOnClickListener(new View.OnClickListener() { 1280cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath @Override 1290cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath public void onClick(View v) { 1300cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath onRadioButtonClicked(rb, !rb.isChecked()); 1310cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1320cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath }); 1330cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1340cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mSettingsIcon = view.findViewById(R.id.tts_engine_settings); 1350cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath // Will be enabled only the engine has passed the voice check, and 1360cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath // is currently enabled. 1370cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mSettingsIcon.setEnabled(isChecked && mVoiceCheckData != null); 1380cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mSettingsIcon.setOnClickListener(new View.OnClickListener() { 1390cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath @Override 1400cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath public void onClick(View v) { 1410cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath Bundle args = new Bundle(); 1420cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath args.putString(FRAGMENT_ARGS_NAME, mEngineInfo.name); 1430cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath args.putString(FRAGMENT_ARGS_LABEL, mEngineInfo.label); 1440cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath if (mVoiceCheckData != null) { 1450cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath args.putParcelable(FRAGMENT_ARGS_VOICES, mVoiceCheckData); 1460cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1470cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1480cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath // Note that we use this instead of the (easier to use) 1490cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath // PreferenceActivity.startPreferenceFragment because the 1500cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath // title will not be updated correctly in the fragment 1510cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath // breadcrumb since it isn't inflated from the XML layout. 1520cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mPreferenceActivity.startPreferencePanel( 1530cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath TtsEngineSettingsFragment.class.getName(), 1540cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath args, 0, mEngineInfo.label, null, 0); 1550cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1560cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath }); 1570cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1580cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath return view; 1590cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1600cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1610cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath public void setVoiceDataDetails(Intent data) { 1620cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mVoiceCheckData = data; 1630cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mSettingsIcon.setEnabled(mRadioButton.isChecked()); 1640cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1650cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1660cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath private void onRadioButtonClicked(CompoundButton buttonView, boolean isChecked) { 1670cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath if (mPreventRadioButtonCallbacks) { 1680cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath return; 1690cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1700cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1710cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath if (isChecked) { 1720cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath if (mSharedState.getCurrentChecked() != null) { 1730cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mSharedState.getCurrentChecked().setChecked(false); 1740cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1750cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mSharedState.setCurrentChecked(buttonView); 1760cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mSharedState.setCurrentKey(getKey()); 1770cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath callChangeListener(mSharedState.getCurrentKey()); 1780cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1790cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1800cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath mSettingsIcon.setEnabled(isChecked); 1810cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1820cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1830cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1840cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath /** 1850cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * Holds all state that is common to this group of radio buttons, such 1860cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * as the currently selected key and the currently checked compound button. 1870cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath * (which corresponds to this key). 1880cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath */ 1890cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath public interface RadioButtonGroupState { 1900cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath String getCurrentKey(); 1910cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath Checkable getCurrentChecked(); 1920cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1930cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath void setCurrentKey(String key); 1940cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath void setCurrentChecked(Checkable current); 1950cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath } 1960cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath 1970cfbb0f10aca100795169891c9a152d56390a3cfNarayan Kamath} 198