Home | History | Annotate | Download | only in inputmethod
      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.inputmethod;
     18 
     19 import com.android.settings.R;
     20 import com.android.settings.SettingsPreferenceFragment;
     21 
     22 import android.app.AlertDialog;
     23 import android.app.Fragment;
     24 import android.content.ActivityNotFoundException;
     25 import android.content.DialogInterface;
     26 import android.content.Intent;
     27 import android.content.res.Configuration;
     28 import android.os.Bundle;
     29 import android.preference.CheckBoxPreference;
     30 import android.preference.PreferenceActivity;
     31 import android.provider.Settings;
     32 import android.text.TextUtils;
     33 import android.util.Log;
     34 import android.view.View;
     35 import android.view.View.OnClickListener;
     36 import android.view.View.OnLongClickListener;
     37 import android.view.inputmethod.InputMethodInfo;
     38 import android.view.inputmethod.InputMethodManager;
     39 import android.view.inputmethod.InputMethodSubtype;
     40 import android.widget.ImageView;
     41 import android.widget.TextView;
     42 
     43 import java.util.Comparator;
     44 import java.util.List;
     45 
     46 public class InputMethodPreference extends CheckBoxPreference
     47         implements Comparator<InputMethodPreference> {
     48     private static final String TAG = InputMethodPreference.class.getSimpleName();
     49     private static final float DISABLED_ALPHA = 0.4f;
     50     private final SettingsPreferenceFragment mFragment;
     51     private final InputMethodInfo mImi;
     52     private final InputMethodManager mImm;
     53     private final Intent mSettingsIntent;
     54     private final boolean mIsSystemIme;
     55 
     56     private AlertDialog mDialog = null;
     57     private ImageView mInputMethodSettingsButton;
     58     private TextView mTitleText;
     59     private TextView mSummaryText;
     60     private View mInputMethodPref;
     61 
     62     private final OnClickListener mPrefOnclickListener = new OnClickListener() {
     63         @Override
     64         public void onClick(View arg0) {
     65             if (!isEnabled()) {
     66                 return;
     67             }
     68             if (isChecked()) {
     69                 setChecked(false);
     70             } else {
     71                 if (mIsSystemIme) {
     72                     setChecked(true);
     73                 } else {
     74                     showSecurityWarnDialog(mImi, InputMethodPreference.this);
     75                 }
     76             }
     77         }
     78     };
     79 
     80     public InputMethodPreference(SettingsPreferenceFragment fragment, Intent settingsIntent,
     81             InputMethodManager imm, InputMethodInfo imi, int imiCount) {
     82         super(fragment.getActivity(), null, R.style.InputMethodPreferenceStyle);
     83         setLayoutResource(R.layout.preference_inputmethod);
     84         setWidgetLayoutResource(R.layout.preference_inputmethod_widget);
     85         mFragment = fragment;
     86         mSettingsIntent = settingsIntent;
     87         mImm = imm;
     88         mImi = imi;
     89         updateSummary();
     90         mIsSystemIme = InputMethodAndSubtypeUtil.isSystemIme(imi);
     91         final boolean isAuxIme = InputMethodAndSubtypeUtil.isAuxiliaryIme(imi);
     92         if (imiCount <= 1 || (mIsSystemIme && !isAuxIme)) {
     93             setEnabled(false);
     94         }
     95     }
     96 
     97     @Override
     98     protected void onBindView(View view) {
     99         super.onBindView(view);
    100         mInputMethodPref = view.findViewById(R.id.inputmethod_pref);
    101         mInputMethodPref.setOnClickListener(mPrefOnclickListener);
    102         mInputMethodSettingsButton = (ImageView)view.findViewById(R.id.inputmethod_settings);
    103         mTitleText = (TextView)view.findViewById(android.R.id.title);
    104         mSummaryText = (TextView)view.findViewById(android.R.id.summary);
    105         final boolean hasSubtypes = mImi.getSubtypeCount() > 1;
    106         final String imiId = mImi.getId();
    107         if (hasSubtypes) {
    108             mInputMethodPref.setOnLongClickListener(new OnLongClickListener() {
    109                 @Override
    110                 public boolean onLongClick(View arg0) {
    111                     final Bundle bundle = new Bundle();
    112                     bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
    113                     startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
    114                             0, bundle);
    115                     return true;
    116                 }
    117             });
    118         }
    119 
    120         if (mSettingsIntent != null) {
    121             mInputMethodSettingsButton.setOnClickListener(
    122                     new OnClickListener() {
    123                         @Override
    124                         public void onClick(View arg0) {
    125                             try {
    126                                 mFragment.startActivity(mSettingsIntent);
    127                             } catch (ActivityNotFoundException e) {
    128                                 Log.d(TAG, "IME's Settings Activity Not Found: " + e);
    129                                 // If the IME's settings activity does not exist, we can just
    130                                 // do nothing...
    131                             }
    132                         }
    133                     });
    134         }
    135         if (hasSubtypes) {
    136             final OnLongClickListener listener = new OnLongClickListener() {
    137                 @Override
    138                 public boolean onLongClick(View arg0) {
    139                     final Bundle bundle = new Bundle();
    140                     bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
    141                     startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
    142                             0, bundle);
    143                     return true;
    144                 }
    145             };
    146             mInputMethodSettingsButton.setOnLongClickListener(listener);
    147         }
    148         if (mSettingsIntent == null) {
    149             mInputMethodSettingsButton.setVisibility(View.GONE);
    150         } else {
    151             updatePreferenceViews();
    152         }
    153     }
    154 
    155     @Override
    156     public void setEnabled(boolean enabled) {
    157         super.setEnabled(enabled);
    158         updatePreferenceViews();
    159     }
    160 
    161     private void updatePreferenceViews() {
    162         final boolean checked = isChecked();
    163         if (mInputMethodSettingsButton != null) {
    164             mInputMethodSettingsButton.setEnabled(checked);
    165             mInputMethodSettingsButton.setClickable(checked);
    166             mInputMethodSettingsButton.setFocusable(checked);
    167             if (!checked) {
    168                 mInputMethodSettingsButton.setAlpha(DISABLED_ALPHA);
    169             }
    170         }
    171         if (mTitleText != null) {
    172             mTitleText.setEnabled(true);
    173         }
    174         if (mSummaryText != null) {
    175             mSummaryText.setEnabled(checked);
    176         }
    177         if (mInputMethodPref != null) {
    178             mInputMethodPref.setEnabled(true);
    179             mInputMethodPref.setLongClickable(checked);
    180             final boolean enabled = isEnabled();
    181             mInputMethodPref.setOnClickListener(enabled ? mPrefOnclickListener : null);
    182             if (!enabled) {
    183                 mInputMethodPref.setBackgroundColor(0);
    184             }
    185         }
    186     }
    187 
    188     public static boolean startFragment(
    189             Fragment fragment, String fragmentClass, int requestCode, Bundle extras) {
    190         if (fragment.getActivity() instanceof PreferenceActivity) {
    191             PreferenceActivity preferenceActivity = (PreferenceActivity)fragment.getActivity();
    192             preferenceActivity.startPreferencePanel(fragmentClass, extras, 0, null, fragment,
    193                     requestCode);
    194             return true;
    195         } else {
    196             Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
    197                     + "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
    198                     + ")");
    199             return false;
    200         }
    201     }
    202 
    203     public String getSummaryString() {
    204         final StringBuilder builder = new StringBuilder();
    205         final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(mImi, true);
    206         for (InputMethodSubtype subtype : subtypes) {
    207             if (builder.length() > 0) {
    208                 builder.append(", ");
    209             }
    210             final CharSequence subtypeLabel = subtype.getDisplayName(mFragment.getActivity(),
    211                     mImi.getPackageName(), mImi.getServiceInfo().applicationInfo);
    212             builder.append(subtypeLabel);
    213         }
    214         return builder.toString();
    215     }
    216 
    217     public void updateSummary() {
    218         final String summary = getSummaryString();
    219         if (TextUtils.isEmpty(summary)) {
    220             return;
    221         }
    222         setSummary(summary);
    223     }
    224 
    225     @Override
    226     public void setChecked(boolean checked) {
    227         super.setChecked(checked);
    228         saveImeSettings();
    229         updateSummary();
    230     }
    231 
    232     private void showSecurityWarnDialog(InputMethodInfo imi, final CheckBoxPreference chkPref) {
    233         if (mDialog != null && mDialog.isShowing()) {
    234             mDialog.dismiss();
    235         }
    236         mDialog = (new AlertDialog.Builder(mFragment.getActivity()))
    237                 .setTitle(android.R.string.dialog_alert_title)
    238                 .setIcon(android.R.drawable.ic_dialog_alert)
    239                 .setCancelable(true)
    240                 .setPositiveButton(android.R.string.ok,
    241                         new DialogInterface.OnClickListener() {
    242                     @Override
    243                     public void onClick(DialogInterface dialog, int which) {
    244                         chkPref.setChecked(true);
    245                     }
    246                 })
    247                 .setNegativeButton(android.R.string.cancel,
    248                         new DialogInterface.OnClickListener() {
    249                     @Override
    250                     public void onClick(DialogInterface dialog, int which) {
    251                     }
    252                 })
    253                 .create();
    254         mDialog.setMessage(mFragment.getResources().getString(R.string.ime_security_warning,
    255                 imi.getServiceInfo().applicationInfo.loadLabel(
    256                         mFragment.getActivity().getPackageManager())));
    257         mDialog.show();
    258     }
    259 
    260     @Override
    261     public int compare(InputMethodPreference arg0, InputMethodPreference arg1) {
    262         if (arg0.isEnabled() == arg0.isEnabled()) {
    263             return arg0.mImi.getId().compareTo(arg1.mImi.getId());
    264         } else {
    265             // Prefer system IMEs
    266             return arg0.isEnabled() ? 1 : -1;
    267         }
    268     }
    269 
    270     private void saveImeSettings() {
    271         InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
    272                 mFragment, mFragment.getActivity().getContentResolver(), mImm.getInputMethodList(),
    273                 mFragment.getResources().getConfiguration().keyboard
    274                         == Configuration.KEYBOARD_QWERTY);
    275     }
    276 }
    277