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