From dcef94165b256c2bc8d3a05e2fe0caf0795c7155 Mon Sep 17 00:00:00 2001 From: Satoshi Kataoka Date: Thu, 25 Apr 2013 15:21:31 +0900 Subject: [PATCH] Support ICS on the user dictionary settings Bug: 8600958 Change-Id: I50e9228afc7b04147eb7c4734d3145abe8859a30 --- java/res/layout/user_dictionary_item.xml | 55 ++++++++------- .../compat/UserDictionaryCompatUtils.java | 10 ++- .../inputmethod/latin/SettingsFragment.java | 12 +--- .../UserDictionaryAddWordContents.java | 32 ++++++--- .../UserDictionaryAddWordFragment.java | 19 ++++-- .../userdictionary/UserDictionaryList.java | 15 ++++- .../UserDictionarySettings.java | 67 ++++++++++++++++--- 7 files changed, 145 insertions(+), 65 deletions(-) diff --git a/java/res/layout/user_dictionary_item.xml b/java/res/layout/user_dictionary_item.xml index 3062ed89a..56bad7743 100644 --- a/java/res/layout/user_dictionary_item.xml +++ b/java/res/layout/user_dictionary_item.xml @@ -13,40 +13,39 @@ See the License for the specific language governing permissions and limitations under the License. --> - + android:minHeight="?android:attr/listPreferredItemHeight" + android:paddingEnd="?android:attr/scrollbarSize" > - + - + - - - + + diff --git a/java/src/com/android/inputmethod/compat/UserDictionaryCompatUtils.java b/java/src/com/android/inputmethod/compat/UserDictionaryCompatUtils.java index ff6561c58..a0d76415c 100644 --- a/java/src/com/android/inputmethod/compat/UserDictionaryCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/UserDictionaryCompatUtils.java @@ -28,6 +28,7 @@ public final class UserDictionaryCompatUtils { private static final Method METHOD_addWord = CompatUtils.getMethod(Words.class, "addWord", Context.class, String.class, Integer.TYPE, String.class, Locale.class); + @SuppressWarnings("deprecation") public static void addWord(final Context context, final String word, final int freq, final String shortcut, final Locale locale) { if (hasNewerAddWord()) { @@ -39,13 +40,18 @@ public final class UserDictionaryCompatUtils { if (null == locale) { localeType = Words.LOCALE_TYPE_ALL; } else { - localeType = Words.LOCALE_TYPE_CURRENT; + final Locale currentLocale = context.getResources().getConfiguration().locale; + if (locale.equals(currentLocale)) { + localeType = Words.LOCALE_TYPE_CURRENT; + } else { + localeType = Words.LOCALE_TYPE_ALL; + } } Words.addWord(context, word, freq, localeType); } } - private static final boolean hasNewerAddWord() { + public static final boolean hasNewerAddWord() { return null != METHOD_addWord; } } diff --git a/java/src/com/android/inputmethod/latin/SettingsFragment.java b/java/src/com/android/inputmethod/latin/SettingsFragment.java index c78064b23..830cae9b8 100644 --- a/java/src/com/android/inputmethod/latin/SettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/SettingsFragment.java @@ -25,7 +25,6 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.media.AudioManager; -import android.os.Build; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.ListPreference; @@ -46,7 +45,7 @@ import com.android.inputmethodcommon.InputMethodSettingsFragment; public final class SettingsFragment extends InputMethodSettingsFragment implements SharedPreferences.OnSharedPreferenceChangeListener { - private static final boolean DBG_USE_INTERNAL_USER_SETTINGS = false; + private static final boolean DBG_USE_INTERNAL_USER_DICTIONARY_SETTINGS = false; private ListPreference mVoicePreference; private ListPreference mShowCorrectionSuggestionsPreference; @@ -202,13 +201,8 @@ public final class SettingsFragment extends InputMethodSettingsFragment final Intent editPersonalDictionaryIntent = editPersonalDictionary.getIntent(); final ResolveInfo ri = context.getPackageManager().resolveActivity( editPersonalDictionaryIntent, PackageManager.MATCH_DEFAULT_ONLY); - if (DBG_USE_INTERNAL_USER_SETTINGS || ri == null) { - // TODO: Support ICS - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - updateUserDictionaryPreference(editPersonalDictionary); - } else { - removePreference(Settings.PREF_EDIT_PERSONAL_DICTIONARY, getPreferenceScreen()); - } + if (DBG_USE_INTERNAL_USER_DICTIONARY_SETTINGS || ri == null) { + updateUserDictionaryPreference(editPersonalDictionary); } if (!Settings.readFromBuildConfigIfGestureInputEnabled(res)) { diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java index f0dc526e4..2b6fda381 100644 --- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java +++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin.userdictionary; +import com.android.inputmethod.compat.UserDictionaryCompatUtils; import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.R; @@ -68,18 +69,28 @@ public class UserDictionaryAddWordContents { /* package */ UserDictionaryAddWordContents(final View view, final Bundle args) { mWordEditText = (EditText)view.findViewById(R.id.user_dictionary_add_word_text); mShortcutEditText = (EditText)view.findViewById(R.id.user_dictionary_add_shortcut); + if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) { + mShortcutEditText.setVisibility(View.GONE); + view.findViewById(R.id.user_dictionary_add_shortcut_label).setVisibility(View.GONE); + } final String word = args.getString(EXTRA_WORD); if (null != word) { mWordEditText.setText(word); mWordEditText.setSelection(word.length()); } - final String shortcut = args.getString(EXTRA_SHORTCUT); - if (null != shortcut && null != mShortcutEditText) { - mShortcutEditText.setText(shortcut); + final String shortcut; + if (UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) { + shortcut = args.getString(EXTRA_SHORTCUT); + if (null != shortcut && null != mShortcutEditText) { + mShortcutEditText.setText(shortcut); + } + mOldShortcut = args.getString(EXTRA_SHORTCUT); + } else { + shortcut = null; + mOldShortcut = null; } mMode = args.getInt(EXTRA_MODE); // default return value for #getInt() is 0 = MODE_EDIT mOldWord = args.getString(EXTRA_WORD); - mOldShortcut = args.getString(EXTRA_SHORTCUT); updateLocale(args.getString(EXTRA_LOCALE)); } @@ -110,7 +121,8 @@ public class UserDictionaryAddWordContents { // If we are in add mode, nothing was added, so we don't need to do anything. } - /* package */ int apply(final Context context, final Bundle outParameters) { + /* package */ + int apply(final Context context, final Bundle outParameters) { if (null != outParameters) saveStateIntoBundle(outParameters); final ContentResolver resolver = context.getContentResolver(); if (MODE_EDIT == mMode && !TextUtils.isEmpty(mOldWord)) { @@ -119,7 +131,9 @@ public class UserDictionaryAddWordContents { } final String newWord = mWordEditText.getText().toString(); final String newShortcut; - if (null == mShortcutEditText) { + if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) { + newShortcut = null; + } else if (null == mShortcutEditText) { newShortcut = null; } else { final String tmpShortcut = mShortcutEditText.getText().toString(); @@ -150,9 +164,9 @@ public class UserDictionaryAddWordContents { // In this class we use the empty string to represent 'all locales' and mLocale cannot // be null. However the addWord method takes null to mean 'all locales'. - UserDictionary.Words.addWord(context, newWord.toString(), - FREQUENCY_FOR_USER_DICTIONARY_ADDS, newShortcut, - TextUtils.isEmpty(mLocale) ? null : LocaleUtils.constructLocaleFromString(mLocale)); + UserDictionaryCompatUtils.addWord(context, newWord.toString(), + FREQUENCY_FOR_USER_DICTIONARY_ADDS, newShortcut, TextUtils.isEmpty(mLocale) ? + null : LocaleUtils.constructLocaleFromString(mLocale)); return CODE_WORD_ADDED; } diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java index 7970a365c..5f4c44636 100644 --- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java +++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java @@ -49,7 +49,8 @@ import java.util.Locale; public class UserDictionaryAddWordFragment extends Fragment implements AdapterView.OnItemSelectedListener, LocationChangedListener { - private static final int OPTIONS_MENU_DELETE = Menu.FIRST; + private static final int OPTIONS_MENU_ADD = Menu.FIRST; + private static final int OPTIONS_MENU_DELETE = Menu.FIRST + 1; private UserDictionaryAddWordContents mContents; private View mRootView; @@ -73,21 +74,29 @@ public class UserDictionaryAddWordFragment extends Fragment @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - MenuItem actionItem = menu.add(0, OPTIONS_MENU_DELETE, 0, + final MenuItem actionItemDelete = menu.add(0, OPTIONS_MENU_DELETE, 0, R.string.user_dict_settings_delete).setIcon(android.R.drawable.ic_menu_delete); - actionItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | - MenuItem.SHOW_AS_ACTION_WITH_TEXT); + actionItemDelete.setShowAsAction( + MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + final MenuItem actionItemAdd = menu.add(0, OPTIONS_MENU_ADD, 0, + R.string.user_dict_settings_delete).setIcon(R.drawable.ic_menu_add); + actionItemAdd.setShowAsAction( + MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); } /** * Callback for the framework when a menu option is pressed. * - * This class only supports the delete menu item. * @param MenuItem the item that was pressed * @return false to allow normal menu processing to proceed, true to consume it here */ @Override public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == OPTIONS_MENU_ADD) { + // added the entry in "onPause" + getActivity().onBackPressed(); + return true; + } if (item.getItemId() == OPTIONS_MENU_DELETE) { mContents.delete(getActivity()); mIsDeleting = true; diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java index 2d147aada..6e64882b6 100644 --- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java +++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java @@ -27,6 +27,7 @@ import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceGroup; import android.provider.UserDictionary; +import android.text.TextUtils; import java.util.Locale; import java.util.TreeSet; @@ -52,16 +53,26 @@ public class UserDictionaryList extends PreferenceFragment { new String[] { UserDictionary.Words.LOCALE }, null, null, null); final TreeSet localeList = new TreeSet(); + boolean addedAllLocale = false; if (null == cursor) { // The user dictionary service is not present or disabled. Return null. return null; } else if (cursor.moveToFirst()) { final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE); do { - String locale = cursor.getString(columnIndex); - localeList.add(null != locale ? locale : ""); + final String locale = cursor.getString(columnIndex); + final boolean allLocale = TextUtils.isEmpty(locale); + localeList.add(allLocale ? "" : locale); + if (allLocale) { + addedAllLocale = true; + } } while (cursor.moveToNext()); } + if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED && !addedAllLocale) { + // For ICS, we need to show "For all languages" in case that the keyboard locale + // is different from the system locale + localeList.add(""); + } localeList.add(Locale.getDefault().toString()); return localeList; } diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java index a250c246e..36bc5ba49 100644 --- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java +++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java @@ -23,6 +23,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; +import android.os.Build; import android.os.Bundle; import android.provider.UserDictionary; import android.text.TextUtils; @@ -47,13 +48,42 @@ import java.util.Locale; public class UserDictionarySettings extends ListFragment { - private static final String[] QUERY_PROJECTION = { - UserDictionary.Words._ID, UserDictionary.Words.WORD, UserDictionary.Words.SHORTCUT - }; + public static final boolean IS_SHORTCUT_API_SUPPORTED = + Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; + + private static final String[] QUERY_PROJECTION_SHORTCUT_UNSUPPORTED = + { UserDictionary.Words._ID, UserDictionary.Words.WORD}; + private static final String[] QUERY_PROJECTION_SHORTCUT_SUPPORTED = + { UserDictionary.Words._ID, UserDictionary.Words.WORD, UserDictionary.Words.SHORTCUT}; + private static final String[] QUERY_PROJECTION = + IS_SHORTCUT_API_SUPPORTED ? + QUERY_PROJECTION_SHORTCUT_SUPPORTED : QUERY_PROJECTION_SHORTCUT_UNSUPPORTED; // The index of the shortcut in the above array. private static final int INDEX_SHORTCUT = 2; + private static final String[] ADAPTER_FROM_SHORTCUT_UNSUPPORTED = { + UserDictionary.Words.WORD, + }; + + private static final String[] ADAPTER_FROM_SHORTCUT_SUPPORTED = { + UserDictionary.Words.WORD, UserDictionary.Words.SHORTCUT + }; + + private static final String[] ADAPTER_FROM = IS_SHORTCUT_API_SUPPORTED ? + ADAPTER_FROM_SHORTCUT_SUPPORTED : ADAPTER_FROM_SHORTCUT_UNSUPPORTED; + + private static final int[] ADAPTER_TO_SHORTCUT_UNSUPPORTED = { + android.R.id.text1, + }; + + private static final int[] ADAPTER_TO_SHORTCUT_SUPPORTED = { + android.R.id.text1, android.R.id.text2 + }; + + private static final int[] ADAPTER_TO = IS_SHORTCUT_API_SUPPORTED ? + ADAPTER_TO_SHORTCUT_SUPPORTED : ADAPTER_TO_SHORTCUT_UNSUPPORTED; + // Either the locale is empty (means the word is applicable to all locales) // or the word equals our current locale private static final String QUERY_SELECTION = @@ -66,6 +96,8 @@ public class UserDictionarySettings extends ListFragment { private static final String DELETE_SELECTION_WITHOUT_SHORTCUT = UserDictionary.Words.WORD + "=? AND " + UserDictionary.Words.SHORTCUT + " is null OR " + UserDictionary.Words.SHORTCUT + "=''"; + private static final String DELETE_SELECTION_SHORTCUT_UNSUPPORTED = + UserDictionary.Words.WORD + "=?"; private static final int OPTIONS_MENU_ADD = Menu.FIRST; @@ -146,10 +178,8 @@ public class UserDictionarySettings extends ListFragment { } private ListAdapter createAdapter() { - return new MyAdapter(getActivity(), - R.layout.user_dictionary_item, mCursor, - new String[] { UserDictionary.Words.WORD, UserDictionary.Words.SHORTCUT }, - new int[] { android.R.id.text1, android.R.id.text2 }, this); + return new MyAdapter(getActivity(), R.layout.user_dictionary_item, mCursor, + ADAPTER_FROM, ADAPTER_TO, this); } @Override @@ -163,11 +193,20 @@ public class UserDictionarySettings extends ListFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) { + final Locale systemLocale = getResources().getConfiguration().locale; + if (!TextUtils.isEmpty(mLocale) && !mLocale.equals(systemLocale.toString())) { + // Hide the add button for ICS because it doesn't support specifying a locale + // for an entry. This new "locale"-aware API has been added in conjunction + // with the shortcut API. + return; + } + } MenuItem actionItem = menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title) .setIcon(R.drawable.ic_menu_add); - actionItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | - MenuItem.SHOW_AS_ACTION_WITH_TEXT); + actionItem.setShowAsAction( + MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); } @Override @@ -209,6 +248,7 @@ public class UserDictionarySettings extends ListFragment { } private String getShortcut(final int position) { + if (!IS_SHORTCUT_API_SUPPORTED) return null; if (null == mCursor) return null; mCursor.moveToPosition(position); // Handle a possible race-condition @@ -220,7 +260,10 @@ public class UserDictionarySettings extends ListFragment { public static void deleteWord(final String word, final String shortcut, final ContentResolver resolver) { - if (TextUtils.isEmpty(shortcut)) { + if (!IS_SHORTCUT_API_SUPPORTED) { + resolver.delete(UserDictionary.Words.CONTENT_URI, DELETE_SELECTION_SHORTCUT_UNSUPPORTED, + new String[] { word }); + } else if (TextUtils.isEmpty(shortcut)) { resolver.delete( UserDictionary.Words.CONTENT_URI, DELETE_SELECTION_WITHOUT_SHORTCUT, new String[] { word }); @@ -239,6 +282,10 @@ public class UserDictionarySettings extends ListFragment { @Override public boolean setViewValue(View v, Cursor c, int columnIndex) { + if (!IS_SHORTCUT_API_SUPPORTED) { + // just let SimpleCursorAdapter set the view values + return false; + } if (columnIndex == INDEX_SHORTCUT) { final String shortcut = c.getString(INDEX_SHORTCUT); if (TextUtils.isEmpty(shortcut)) {