• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16 
17 package com.android.inputmethod.latin;
18 
19 import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
20 
21 import android.app.AlertDialog;
22 import android.app.Dialog;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.content.SharedPreferences;
27 import android.content.res.Resources;
28 import android.os.Bundle;
29 import android.os.Parcel;
30 import android.os.Parcelable;
31 import android.preference.DialogPreference;
32 import android.preference.Preference;
33 import android.preference.PreferenceFragment;
34 import android.preference.PreferenceGroup;
35 import android.util.Pair;
36 import android.view.Menu;
37 import android.view.MenuInflater;
38 import android.view.MenuItem;
39 import android.view.View;
40 import android.view.inputmethod.InputMethodInfo;
41 import android.view.inputmethod.InputMethodSubtype;
42 import android.widget.ArrayAdapter;
43 import android.widget.Spinner;
44 import android.widget.SpinnerAdapter;
45 import android.widget.Toast;
46 
47 import com.android.inputmethod.compat.CompatUtils;
48 
49 import java.util.ArrayList;
50 import java.util.TreeSet;
51 
52 public class AdditionalSubtypeSettings extends PreferenceFragment {
53     private SharedPreferences mPrefs;
54     private SubtypeLocaleAdapter mSubtypeLocaleAdapter;
55     private KeyboardLayoutSetAdapter mKeyboardLayoutSetAdapter;
56 
57     private boolean mIsAddingNewSubtype;
58     private AlertDialog mSubtypeEnablerNotificationDialog;
59     private String mSubtypePreferenceKeyForSubtypeEnabler;
60 
61     private static final int MENU_ADD_SUBTYPE = Menu.FIRST;
62     private static final String KEY_IS_ADDING_NEW_SUBTYPE = "is_adding_new_subtype";
63     private static final String KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN =
64             "is_subtype_enabler_notification_dialog_open";
65     private static final String KEY_SUBTYPE_FOR_SUBTYPE_ENABLER = "subtype_for_subtype_enabler";
66     static class SubtypeLocaleItem extends Pair<String, String>
67             implements Comparable<SubtypeLocaleItem> {
SubtypeLocaleItem(String localeString, String displayName)68         public SubtypeLocaleItem(String localeString, String displayName) {
69             super(localeString, displayName);
70         }
71 
SubtypeLocaleItem(String localeString)72         public SubtypeLocaleItem(String localeString) {
73             this(localeString, SubtypeLocale.getSubtypeLocaleDisplayName(localeString));
74         }
75 
76         @Override
toString()77         public String toString() {
78             return second;
79         }
80 
81         @Override
compareTo(SubtypeLocaleItem o)82         public int compareTo(SubtypeLocaleItem o) {
83             return first.compareTo(o.first);
84         }
85     }
86 
87     static class SubtypeLocaleAdapter extends ArrayAdapter<SubtypeLocaleItem> {
SubtypeLocaleAdapter(Context context)88         public SubtypeLocaleAdapter(Context context) {
89             super(context, android.R.layout.simple_spinner_item);
90             setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
91 
92             final TreeSet<SubtypeLocaleItem> items = new TreeSet<SubtypeLocaleItem>();
93             final InputMethodInfo imi = ImfUtils.getInputMethodInfoOfThisIme(context);
94             final int count = imi.getSubtypeCount();
95             for (int i = 0; i < count; i++) {
96                 final InputMethodSubtype subtype = imi.getSubtypeAt(i);
97                 if (subtype.containsExtraValueKey(ASCII_CAPABLE)) {
98                     items.add(createItem(context, subtype.getLocale()));
99                 }
100             }
101             // TODO: Should filter out already existing combinations of locale and layout.
102             addAll(items);
103         }
104 
createItem(Context context, String localeString)105         public static SubtypeLocaleItem createItem(Context context, String localeString) {
106             if (localeString.equals(SubtypeLocale.NO_LANGUAGE)) {
107                 final String displayName = context.getString(R.string.subtype_no_language);
108                 return new SubtypeLocaleItem(localeString, displayName);
109             } else {
110                 return new SubtypeLocaleItem(localeString);
111             }
112         }
113     }
114 
115     static class KeyboardLayoutSetItem extends Pair<String, String> {
KeyboardLayoutSetItem(InputMethodSubtype subtype)116         public KeyboardLayoutSetItem(InputMethodSubtype subtype) {
117             super(SubtypeLocale.getKeyboardLayoutSetName(subtype),
118                     SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype));
119         }
120 
121         @Override
toString()122         public String toString() {
123             return second;
124         }
125     }
126 
127     static class KeyboardLayoutSetAdapter extends ArrayAdapter<KeyboardLayoutSetItem> {
KeyboardLayoutSetAdapter(Context context)128         public KeyboardLayoutSetAdapter(Context context) {
129             super(context, android.R.layout.simple_spinner_item);
130             setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
131 
132             // TODO: Should filter out already existing combinations of locale and layout.
133             for (final String layout : SubtypeLocale.getPredefinedKeyboardLayoutSet()) {
134                 // This is a dummy subtype with NO_LANGUAGE, only for display.
135                 final InputMethodSubtype subtype = AdditionalSubtype.createAdditionalSubtype(
136                         SubtypeLocale.NO_LANGUAGE, layout, null);
137                 add(new KeyboardLayoutSetItem(subtype));
138             }
139         }
140     }
141 
142     private interface SubtypeDialogProxy {
onRemovePressed(SubtypePreference subtypePref)143         public void onRemovePressed(SubtypePreference subtypePref);
onSavePressed(SubtypePreference subtypePref)144         public void onSavePressed(SubtypePreference subtypePref);
onAddPressed(SubtypePreference subtypePref)145         public void onAddPressed(SubtypePreference subtypePref);
getSubtypeLocaleAdapter()146         public SubtypeLocaleAdapter getSubtypeLocaleAdapter();
getKeyboardLayoutSetAdapter()147         public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter();
148     }
149 
150     static class SubtypePreference extends DialogPreference
151             implements DialogInterface.OnCancelListener {
152         private static final String KEY_PREFIX = "subtype_pref_";
153         private static final String KEY_NEW_SUBTYPE = KEY_PREFIX + "new";
154 
155         private InputMethodSubtype mSubtype;
156         private InputMethodSubtype mPreviousSubtype;
157 
158         private final SubtypeDialogProxy mProxy;
159         private Spinner mSubtypeLocaleSpinner;
160         private Spinner mKeyboardLayoutSetSpinner;
161 
newIncompleteSubtypePreference( Context context, SubtypeDialogProxy proxy)162         public static SubtypePreference newIncompleteSubtypePreference(
163                 Context context, SubtypeDialogProxy proxy) {
164             return new SubtypePreference(context, null, proxy);
165         }
166 
SubtypePreference(Context context, InputMethodSubtype subtype, SubtypeDialogProxy proxy)167         public SubtypePreference(Context context, InputMethodSubtype subtype,
168                 SubtypeDialogProxy proxy) {
169             super(context, null);
170             setDialogLayoutResource(R.layout.additional_subtype_dialog);
171             setPersistent(false);
172             mProxy = proxy;
173             setSubtype(subtype);
174         }
175 
show()176         public void show() {
177             showDialog(null);
178         }
179 
isIncomplete()180         public final boolean isIncomplete() {
181             return mSubtype == null;
182         }
183 
getSubtype()184         public InputMethodSubtype getSubtype() {
185             return mSubtype;
186         }
187 
setSubtype(InputMethodSubtype subtype)188         public void setSubtype(InputMethodSubtype subtype) {
189             mPreviousSubtype = mSubtype;
190             mSubtype = subtype;
191             if (isIncomplete()) {
192                 setTitle(null);
193                 setDialogTitle(R.string.add_style);
194                 setKey(KEY_NEW_SUBTYPE);
195             } else {
196                 final String displayName = SubtypeLocale.getSubtypeDisplayName(
197                         subtype, getContext().getResources());
198                 setTitle(displayName);
199                 setDialogTitle(displayName);
200                 setKey(KEY_PREFIX + subtype.getLocale() + "_"
201                         + SubtypeLocale.getKeyboardLayoutSetName(subtype));
202             }
203         }
204 
revert()205         public void revert() {
206             setSubtype(mPreviousSubtype);
207         }
208 
hasBeenModified()209         public boolean hasBeenModified() {
210             return mSubtype != null && !mSubtype.equals(mPreviousSubtype);
211         }
212 
213         @Override
onCreateDialogView()214         protected View onCreateDialogView() {
215             final View v = super.onCreateDialogView();
216             mSubtypeLocaleSpinner = (Spinner) v.findViewById(R.id.subtype_locale_spinner);
217             mSubtypeLocaleSpinner.setAdapter(mProxy.getSubtypeLocaleAdapter());
218             mKeyboardLayoutSetSpinner = (Spinner) v.findViewById(R.id.keyboard_layout_set_spinner);
219             mKeyboardLayoutSetSpinner.setAdapter(mProxy.getKeyboardLayoutSetAdapter());
220             return v;
221         }
222 
223         @Override
onPrepareDialogBuilder(AlertDialog.Builder builder)224         protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
225             final Context context = builder.getContext();
226             builder.setCancelable(true).setOnCancelListener(this);
227             if (isIncomplete()) {
228                 builder.setPositiveButton(R.string.add, this)
229                         .setNegativeButton(android.R.string.cancel, this);
230             } else {
231                 builder.setPositiveButton(R.string.save, this)
232                         .setNeutralButton(android.R.string.cancel, this)
233                         .setNegativeButton(R.string.remove, this);
234                 final SubtypeLocaleItem localeItem = SubtypeLocaleAdapter.createItem(
235                         context, mSubtype.getLocale());
236                 final KeyboardLayoutSetItem layoutItem = new KeyboardLayoutSetItem(mSubtype);
237                 setSpinnerPosition(mSubtypeLocaleSpinner, localeItem);
238                 setSpinnerPosition(mKeyboardLayoutSetSpinner, layoutItem);
239             }
240         }
241 
setSpinnerPosition(Spinner spinner, Object itemToSelect)242         private static void setSpinnerPosition(Spinner spinner, Object itemToSelect) {
243             final SpinnerAdapter adapter = spinner.getAdapter();
244             final int count = adapter.getCount();
245             for (int i = 0; i < count; i++) {
246                 final Object item = spinner.getItemAtPosition(i);
247                 if (item.equals(itemToSelect)) {
248                     spinner.setSelection(i);
249                     return;
250                 }
251             }
252         }
253 
254         @Override
onCancel(DialogInterface dialog)255         public void onCancel(DialogInterface dialog) {
256             if (isIncomplete()) {
257                 mProxy.onRemovePressed(this);
258             }
259         }
260 
261         @Override
onClick(DialogInterface dialog, int which)262         public void onClick(DialogInterface dialog, int which) {
263             super.onClick(dialog, which);
264             switch (which) {
265             case DialogInterface.BUTTON_POSITIVE:
266                 final boolean isEditing = !isIncomplete();
267                 final SubtypeLocaleItem locale =
268                         (SubtypeLocaleItem) mSubtypeLocaleSpinner.getSelectedItem();
269                 final KeyboardLayoutSetItem layout =
270                         (KeyboardLayoutSetItem) mKeyboardLayoutSetSpinner.getSelectedItem();
271                 final InputMethodSubtype subtype = AdditionalSubtype.createAdditionalSubtype(
272                         locale.first, layout.first, ASCII_CAPABLE);
273                 setSubtype(subtype);
274                 notifyChanged();
275                 if (isEditing) {
276                     mProxy.onSavePressed(this);
277                 } else {
278                     mProxy.onAddPressed(this);
279                 }
280                 break;
281             case DialogInterface.BUTTON_NEUTRAL:
282                 // Nothing to do
283                 break;
284             case DialogInterface.BUTTON_NEGATIVE:
285                 mProxy.onRemovePressed(this);
286                 break;
287             }
288         }
289 
getSpinnerPosition(Spinner spinner)290         private static int getSpinnerPosition(Spinner spinner) {
291             if (spinner == null) return -1;
292             return spinner.getSelectedItemPosition();
293         }
294 
setSpinnerPosition(Spinner spinner, int position)295         private static void setSpinnerPosition(Spinner spinner, int position) {
296             if (spinner == null || position < 0) return;
297             spinner.setSelection(position);
298         }
299 
300         @Override
onSaveInstanceState()301         protected Parcelable onSaveInstanceState() {
302             final Parcelable superState = super.onSaveInstanceState();
303             final Dialog dialog = getDialog();
304             if (dialog == null || !dialog.isShowing()) {
305                 return superState;
306             }
307 
308             final SavedState myState = new SavedState(superState);
309             myState.mSubtype = mSubtype;
310             myState.mSubtypeLocaleSelectedPos = getSpinnerPosition(mSubtypeLocaleSpinner);
311             myState.mKeyboardLayoutSetSelectedPos = getSpinnerPosition(mKeyboardLayoutSetSpinner);
312             return myState;
313         }
314 
315         @Override
onRestoreInstanceState(Parcelable state)316         protected void onRestoreInstanceState(Parcelable state) {
317             if (!(state instanceof SavedState)) {
318                 super.onRestoreInstanceState(state);
319                 return;
320             }
321 
322             final SavedState myState = (SavedState) state;
323             super.onRestoreInstanceState(myState.getSuperState());
324             setSpinnerPosition(mSubtypeLocaleSpinner, myState.mSubtypeLocaleSelectedPos);
325             setSpinnerPosition(mKeyboardLayoutSetSpinner, myState.mKeyboardLayoutSetSelectedPos);
326             setSubtype(myState.mSubtype);
327         }
328 
329         static class SavedState extends Preference.BaseSavedState {
330             InputMethodSubtype mSubtype;
331             int mSubtypeLocaleSelectedPos;
332             int mKeyboardLayoutSetSelectedPos;
333 
SavedState(Parcelable superState)334             public SavedState(Parcelable superState) {
335                 super(superState);
336             }
337 
338             @Override
writeToParcel(Parcel dest, int flags)339             public void writeToParcel(Parcel dest, int flags) {
340                 super.writeToParcel(dest, flags);
341                 dest.writeInt(mSubtypeLocaleSelectedPos);
342                 dest.writeInt(mKeyboardLayoutSetSelectedPos);
343                 dest.writeParcelable(mSubtype, 0);
344             }
345 
SavedState(Parcel source)346             public SavedState(Parcel source) {
347                 super(source);
348                 mSubtypeLocaleSelectedPos = source.readInt();
349                 mKeyboardLayoutSetSelectedPos = source.readInt();
350                 mSubtype = (InputMethodSubtype)source.readParcelable(null);
351             }
352 
353             @SuppressWarnings("hiding")
354             public static final Parcelable.Creator<SavedState> CREATOR =
355                     new Parcelable.Creator<SavedState>() {
356                         @Override
357                         public SavedState createFromParcel(Parcel source) {
358                             return new SavedState(source);
359                         }
360 
361                         @Override
362                         public SavedState[] newArray(int size) {
363                             return new SavedState[size];
364                         }
365                     };
366         }
367     }
368 
AdditionalSubtypeSettings()369     public AdditionalSubtypeSettings() {
370         // Empty constructor for fragment generation.
371     }
372 
373     @Override
onCreate(Bundle savedInstanceState)374     public void onCreate(Bundle savedInstanceState) {
375         super.onCreate(savedInstanceState);
376 
377         addPreferencesFromResource(R.xml.additional_subtype_settings);
378         setHasOptionsMenu(true);
379 
380         mPrefs = getPreferenceManager().getSharedPreferences();
381     }
382 
383     @Override
onActivityCreated(Bundle savedInstanceState)384     public void onActivityCreated(Bundle savedInstanceState) {
385         final Context context = getActivity();
386         mSubtypeLocaleAdapter = new SubtypeLocaleAdapter(context);
387         mKeyboardLayoutSetAdapter = new KeyboardLayoutSetAdapter(context);
388 
389         final String prefSubtypes =
390                 SettingsValues.getPrefAdditionalSubtypes(mPrefs, getResources());
391         setPrefSubtypes(prefSubtypes, context);
392 
393         mIsAddingNewSubtype = (savedInstanceState != null)
394                 && savedInstanceState.containsKey(KEY_IS_ADDING_NEW_SUBTYPE);
395         if (mIsAddingNewSubtype) {
396             getPreferenceScreen().addPreference(
397                     SubtypePreference.newIncompleteSubtypePreference(context, mSubtypeProxy));
398         }
399 
400         super.onActivityCreated(savedInstanceState);
401 
402         if (savedInstanceState != null && savedInstanceState.containsKey(
403                 KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN)) {
404             mSubtypePreferenceKeyForSubtypeEnabler = savedInstanceState.getString(
405                     KEY_SUBTYPE_FOR_SUBTYPE_ENABLER);
406             final SubtypePreference subtypePref = (SubtypePreference)findPreference(
407                     mSubtypePreferenceKeyForSubtypeEnabler);
408             mSubtypeEnablerNotificationDialog = createDialog(subtypePref);
409             mSubtypeEnablerNotificationDialog.show();
410         }
411     }
412 
413     @Override
onSaveInstanceState(Bundle outState)414     public void onSaveInstanceState(Bundle outState) {
415         super.onSaveInstanceState(outState);
416         if (mIsAddingNewSubtype) {
417             outState.putBoolean(KEY_IS_ADDING_NEW_SUBTYPE, true);
418         }
419         if (mSubtypeEnablerNotificationDialog != null
420                 && mSubtypeEnablerNotificationDialog.isShowing()) {
421             outState.putBoolean(KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN, true);
422             outState.putString(
423                     KEY_SUBTYPE_FOR_SUBTYPE_ENABLER, mSubtypePreferenceKeyForSubtypeEnabler);
424         }
425     }
426 
427     private final SubtypeDialogProxy mSubtypeProxy = new SubtypeDialogProxy() {
428         @Override
429         public void onRemovePressed(SubtypePreference subtypePref) {
430             mIsAddingNewSubtype = false;
431             final PreferenceGroup group = getPreferenceScreen();
432             group.removePreference(subtypePref);
433             ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), getSubtypes());
434         }
435 
436         @Override
437         public void onSavePressed(SubtypePreference subtypePref) {
438             final InputMethodSubtype subtype = subtypePref.getSubtype();
439             if (!subtypePref.hasBeenModified()) {
440                 return;
441             }
442             if (findDuplicatedSubtype(subtype) == null) {
443                 ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), getSubtypes());
444                 return;
445             }
446 
447             // Saved subtype is duplicated.
448             final PreferenceGroup group = getPreferenceScreen();
449             group.removePreference(subtypePref);
450             subtypePref.revert();
451             group.addPreference(subtypePref);
452             showSubtypeAlreadyExistsToast(subtype);
453         }
454 
455         @Override
456         public void onAddPressed(SubtypePreference subtypePref) {
457             mIsAddingNewSubtype = false;
458             final InputMethodSubtype subtype = subtypePref.getSubtype();
459             if (findDuplicatedSubtype(subtype) == null) {
460                 ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), getSubtypes());
461                 mSubtypePreferenceKeyForSubtypeEnabler = subtypePref.getKey();
462                 mSubtypeEnablerNotificationDialog = createDialog(subtypePref);
463                 mSubtypeEnablerNotificationDialog.show();
464                 return;
465             }
466 
467             // Newly added subtype is duplicated.
468             final PreferenceGroup group = getPreferenceScreen();
469             group.removePreference(subtypePref);
470             showSubtypeAlreadyExistsToast(subtype);
471         }
472 
473         @Override
474         public SubtypeLocaleAdapter getSubtypeLocaleAdapter() {
475             return mSubtypeLocaleAdapter;
476         }
477 
478         @Override
479         public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter() {
480             return mKeyboardLayoutSetAdapter;
481         }
482     };
483 
showSubtypeAlreadyExistsToast(InputMethodSubtype subtype)484     private void showSubtypeAlreadyExistsToast(InputMethodSubtype subtype) {
485         final Context context = getActivity();
486         final Resources res = context.getResources();
487         final String message = res.getString(R.string.custom_input_style_already_exists,
488                 SubtypeLocale.getSubtypeDisplayName(subtype, res));
489         Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
490     }
491 
findDuplicatedSubtype(InputMethodSubtype subtype)492     private InputMethodSubtype findDuplicatedSubtype(InputMethodSubtype subtype) {
493         final String localeString = subtype.getLocale();
494         final String keyboardLayoutSetName = SubtypeLocale.getKeyboardLayoutSetName(subtype);
495         return ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
496                 getActivity(), localeString, keyboardLayoutSetName);
497     }
498 
createDialog(SubtypePreference subtypePref)499     private AlertDialog createDialog(SubtypePreference subtypePref) {
500         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
501         builder.setTitle(R.string.custom_input_styles_title)
502                 .setMessage(R.string.custom_input_style_note_message)
503                 .setNegativeButton(R.string.not_now, null)
504                 .setPositiveButton(R.string.enable, new DialogInterface.OnClickListener() {
505                     @Override
506                     public void onClick(DialogInterface dialog, int which) {
507                         final Intent intent = CompatUtils.getInputLanguageSelectionIntent(
508                                 ImfUtils.getInputMethodIdOfThisIme(getActivity()),
509                                 Intent.FLAG_ACTIVITY_NEW_TASK
510                                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
511                                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
512                         // TODO: Add newly adding subtype to extra value of the intent as a hint
513                         // for the input language selection activity.
514                         // intent.putExtra("newlyAddedSubtype", subtypePref.getSubtype());
515                         startActivity(intent);
516                     }
517                 });
518 
519         return builder.create();
520     }
521 
setPrefSubtypes(String prefSubtypes, Context context)522     private void setPrefSubtypes(String prefSubtypes, Context context) {
523         final PreferenceGroup group = getPreferenceScreen();
524         group.removeAll();
525         final InputMethodSubtype[] subtypesArray =
526                 AdditionalSubtype.createAdditionalSubtypesArray(prefSubtypes);
527         for (final InputMethodSubtype subtype : subtypesArray) {
528             final SubtypePreference pref = new SubtypePreference(
529                     context, subtype, mSubtypeProxy);
530             group.addPreference(pref);
531         }
532     }
533 
getSubtypes()534     private InputMethodSubtype[] getSubtypes() {
535         final PreferenceGroup group = getPreferenceScreen();
536         final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
537         final int count = group.getPreferenceCount();
538         for (int i = 0; i < count; i++) {
539             final Preference pref = group.getPreference(i);
540             if (pref instanceof SubtypePreference) {
541                 final SubtypePreference subtypePref = (SubtypePreference)pref;
542                 // We should not save newly adding subtype to preference because it is incomplete.
543                 if (subtypePref.isIncomplete()) continue;
544                 subtypes.add(subtypePref.getSubtype());
545             }
546         }
547         return subtypes.toArray(new InputMethodSubtype[subtypes.size()]);
548     }
549 
getPrefSubtypes(InputMethodSubtype[] subtypes)550     private String getPrefSubtypes(InputMethodSubtype[] subtypes) {
551         final StringBuilder sb = new StringBuilder();
552         for (final InputMethodSubtype subtype : subtypes) {
553             if (sb.length() > 0) {
554                 sb.append(AdditionalSubtype.PREF_SUBTYPE_SEPARATOR);
555             }
556             sb.append(AdditionalSubtype.getPrefSubtype(subtype));
557         }
558         return sb.toString();
559     }
560 
561     @Override
onPause()562     public void onPause() {
563         super.onPause();
564         final String oldSubtypes = SettingsValues.getPrefAdditionalSubtypes(mPrefs, getResources());
565         final InputMethodSubtype[] subtypes = getSubtypes();
566         final String prefSubtypes = getPrefSubtypes(subtypes);
567         if (prefSubtypes.equals(oldSubtypes)) {
568             return;
569         }
570 
571         final SharedPreferences.Editor editor = mPrefs.edit();
572         try {
573             editor.putString(Settings.PREF_CUSTOM_INPUT_STYLES, prefSubtypes);
574         } finally {
575             editor.apply();
576         }
577         ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), subtypes);
578     }
579 
580     @Override
onCreateOptionsMenu(Menu menu, MenuInflater inflater)581     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
582         final MenuItem addSubtypeMenu = menu.add(0, MENU_ADD_SUBTYPE, 0, R.string.add_style);
583         addSubtypeMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
584     }
585 
586     @Override
onOptionsItemSelected(MenuItem item)587     public boolean onOptionsItemSelected(MenuItem item) {
588         final int itemId = item.getItemId();
589         if (itemId == MENU_ADD_SUBTYPE) {
590             final SubtypePreference newSubtype =
591                     SubtypePreference.newIncompleteSubtypePreference(getActivity(), mSubtypeProxy);
592             getPreferenceScreen().addPreference(newSubtype);
593             newSubtype.show();
594             mIsAddingNewSubtype = true;
595             return true;
596         }
597         return super.onOptionsItemSelected(item);
598     }
599 }
600