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