Home | History | Annotate | Download | only in tts
      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 
     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
    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 
    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 
    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 {
    199         String getCurrentKey();
    200         Checkable getCurrentChecked();
    201 
    202         void setCurrentKey(String key);
    203         void setCurrentChecked(Checkable current);
    204     }
    205 
    206 }
    207