Merge "Implement a functionality to add an entry to the user dictionary"
This commit is contained in:
commit
30f0f3a92a
15 changed files with 1242 additions and 5 deletions
BIN
java/res/drawable-hdpi/ic_menu_add.png
Normal file
BIN
java/res/drawable-hdpi/ic_menu_add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 667 B |
BIN
java/res/drawable-mdpi/ic_menu_add.png
Normal file
BIN
java/res/drawable-mdpi/ic_menu_add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 596 B |
BIN
java/res/drawable-xhdpi/ic_menu_add.png
Normal file
BIN
java/res/drawable-xhdpi/ic_menu_add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 761 B |
99
java/res/layout/user_dictionary_add_word.xml
Normal file
99
java/res/layout/user_dictionary_add_word.xml
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/user_dict_settings_add_dialog_top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<com.android.internal.widget.DialogTitle
|
||||
style="?android:attr/windowTitleStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dip"
|
||||
android:layout_marginEnd="16dip"
|
||||
android:layout_marginStart="16dip"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical|start"
|
||||
android:singleLine="true"
|
||||
android:text="@string/user_dict_settings_add_dialog_title" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dip"
|
||||
android:background="@android:color/holo_blue_light" />
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/user_dictionary_add_word_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="fill_horizontal|center_vertical"
|
||||
android:layout_marginBottom="8dip"
|
||||
android:layout_marginStart="8dip"
|
||||
android:layout_marginTop="8dip"
|
||||
android:hint="@string/user_dict_settings_add_word_hint"
|
||||
android:imeOptions="flagNoFullscreen"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:maxLength="@integer/user_dictionary_max_word_length" >
|
||||
|
||||
<requestFocus />
|
||||
</EditText>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="?android:attr/dividerHorizontal"
|
||||
android:dividerPadding="0dip"
|
||||
android:orientation="vertical"
|
||||
android:showDividers="beginning" >
|
||||
|
||||
<LinearLayout
|
||||
style="?android:attr/buttonBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:measureWithLargestChild="true"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<Button
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="2"
|
||||
android:onClick="onClickCancel"
|
||||
android:text="@string/cancel"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="2"
|
||||
android:onClick="onClickConfirm"
|
||||
android:text="@string/user_dict_settings_add_dialog_confirm"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
91
java/res/layout/user_dictionary_add_word_fullscreen.xml
Normal file
91
java/res/layout/user_dictionary_add_word_fullscreen.xml
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/user_dict_settings_add_dialog_top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
style="?android:attr/listSeparatorTextViewStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/user_dict_settings_add_screen_title" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/user_dictionary_add_word_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="fill_horizontal|center_vertical"
|
||||
android:layout_marginBottom="8dip"
|
||||
android:layout_marginStart="8dip"
|
||||
android:layout_marginTop="8dip"
|
||||
android:hint="@string/user_dict_settings_add_word_hint"
|
||||
android:imeOptions="flagNoFullscreen"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:maxLength="@integer/user_dictionary_max_word_length" >
|
||||
|
||||
<requestFocus />
|
||||
</EditText>
|
||||
|
||||
<GridLayout
|
||||
android:id="@+id/user_dictionary_add_word_grid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dip"
|
||||
android:layout_marginStart="8dip"
|
||||
android:columnCount="2" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/user_dictionary_add_shortcut_label"
|
||||
style="?android:attr/textAppearanceSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:text="@string/user_dict_settings_add_shortcut_option_name" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/user_dictionary_add_shortcut"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="fill_horizontal|center_vertical"
|
||||
android:layout_marginBottom="8dip"
|
||||
android:layout_marginStart="8dip"
|
||||
android:layout_marginTop="8dip"
|
||||
android:hint="@string/user_dict_settings_add_shortcut_hint"
|
||||
android:imeOptions="flagNoFullscreen"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:maxLength="@integer/user_dictionary_max_word_length" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/user_dictionary_add_locale_label"
|
||||
style="?android:attr/textAppearanceSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:text="@string/user_dict_settings_add_locale_option_name"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/user_dictionary_add_locale"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="fill_horizontal|center_vertical"
|
||||
android:layout_marginBottom="8dip"
|
||||
android:layout_marginStart="8dip"
|
||||
android:layout_marginTop="8dip"
|
||||
android:visibility="gone" />
|
||||
</GridLayout>
|
||||
|
||||
</LinearLayout>
|
52
java/res/layout/user_dictionary_item.xml
Normal file
52
java/res/layout/user_dictionary_item.xml
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingEnd="?android:attr/scrollbarSize"
|
||||
android:background="?android:attr/selectableItemBackground" >
|
||||
|
||||
<RelativeLayout android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dip"
|
||||
android:layout_marginEnd="6dip"
|
||||
android:layout_marginTop="6dip"
|
||||
android:layout_marginBottom="6dip"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView android:id="@+android:id/text1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal" />
|
||||
|
||||
<TextView android:id="@+android:id/text2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/text1"
|
||||
android:layout_alignStart="@android:id/text1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:maxLines="1" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
45
java/res/layout/user_dictionary_preference_list_fragment.xml
Normal file
45
java/res/layout/user_dictionary_preference_list_fragment.xml
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright 2013, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<ListView
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0px"
|
||||
android:layout_weight="1"
|
||||
android:cacheColorHint="@android:color/transparent"
|
||||
android:clipToPadding="false"
|
||||
android:drawSelectorOnTop="false"
|
||||
android:paddingTop="0dip"
|
||||
android:scrollbarAlwaysDrawVerticalTrack="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:padding="5dip"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
|
@ -117,4 +117,6 @@
|
|||
|
||||
<!-- Inset used in Accessibility mode to avoid accidental key presses when a finger slides off the screen. -->
|
||||
<dimen name="accessibility_edge_slop">8dp</dimen>
|
||||
|
||||
<integer name="user_dictionary_max_word_length" translatable="false">48</integer>
|
||||
</resources>
|
||||
|
|
|
@ -564,4 +564,76 @@ Tip: You can download and remove dictionaries by going to <b>Language & i
|
|||
|
||||
<!-- Version text [CHAR LIMIT=30]-->
|
||||
<string name="version_text">Version <xliff:g id="version_number" example="1.0.1864.643521">%1$s</xliff:g></string>
|
||||
|
||||
<!-- User dictionary settings -->
|
||||
<!-- User dictionary settings, The titlebar text of the User dictionary settings screen. -->
|
||||
<!-- This resource is corresponding to msgid="765659257455000490" -->
|
||||
<string name="user_dict_settings_titlebar">User dictionary</string>
|
||||
<!-- User dictionary settings, The title of the list item to go into the User dictionary settings screen when there is only one user dictionary. [CHAR LIMIT=35] -->
|
||||
<!-- This resource is corresponding to msgid="524997218433540614" -->
|
||||
<string name="user_dict_single_settings_title">Personal dictionary</string>
|
||||
<!-- User dictionary settings, The title of the list item to go into the User dictionary list when there are several user dictionaries. [CHAR LIMIT=35] -->
|
||||
<!-- This resource is corresponding to msgid="3735224433307996276" -->
|
||||
<string name="user_dict_multiple_settings_title">Personal dictionaries</string>
|
||||
<!-- User dictionary settings. The summary of the listem item to go into the User dictionary settings screen. -->
|
||||
<string name="user_dict_settings_summary" translatable="false">""</string>
|
||||
<!-- User dictionary settings. The title of the menu item to add a new word to the user dictionary. -->
|
||||
<!-- This resource is corresponding to msgid="4056762757149923551" -->
|
||||
<string name="user_dict_settings_add_menu_title">Add</string>
|
||||
<!-- User dictionary settings. The title of the dialog to add a new word to the user dictionary. [CHAR LIMIT=25] -->
|
||||
<!-- This resource is corresponding to msgid="4702613990174126482" -->
|
||||
<string name="user_dict_settings_add_dialog_title">Add to dictionary</string>
|
||||
<!-- User dictionary settings. The title of the screen to add/edit a new word to the user dictionary; it describes the phrase that will be added to the user dictionary. [CHAR LIMIT=25] -->
|
||||
<!-- This resource is corresponding to msgid="742580720124344291" -->
|
||||
<string name="user_dict_settings_add_screen_title">Phrase</string>
|
||||
<!-- User dictionary settings. Text on the dialog button to pop more options for adding a word. [CHAR LIMIT=16] -->
|
||||
<!-- This resource is corresponding to msgid="8848798370746019825" -->
|
||||
<string name="user_dict_settings_add_dialog_more_options">More options</string>
|
||||
<!-- User dictionary settings. Text on the dialog button mask advanced options. [CHAR LIMIT=15] -->
|
||||
<!-- This resource is corresponding to msgid="2441785268726036101" -->
|
||||
<string name="user_dict_settings_add_dialog_less_options">Less options</string>
|
||||
<!-- User dictionary settings. Text on the dialog button to confirm adding a word. [CHAR LIMIT=15] -->
|
||||
<!-- This resource is corresponding to msgid="6225823625332416144" -->
|
||||
<string name="user_dict_settings_add_dialog_confirm">OK</string>
|
||||
<!-- User dictionary settings. Label to put before the word field (that's the word that will actually be added to the user dictionary when OK is pressed). [CHAR LIMIT=20] -->
|
||||
<!-- This resource is corresponding to msgid="7868879174905963135" -->
|
||||
<string name="user_dict_settings_add_word_option_name">Word:</string>
|
||||
<!-- User dictionary settings. Label to put before the shortcut field (once a shortcut is registered, the user can type the shortcut and get the word it points to in the suggestions). [CHAR LIMIT=20] -->
|
||||
<!-- This resource is corresponding to msgid="660089258866063925" -->
|
||||
<string name="user_dict_settings_add_shortcut_option_name">Shortcut:</string>
|
||||
<!-- User dictionary settings. Label to put before the language field. [CHAR LIMIT=20] -->
|
||||
<!-- This resource is corresponding to msgid="5696358317061318532" -->
|
||||
<string name="user_dict_settings_add_locale_option_name">Language:</string>
|
||||
<!-- User dictionary settings. Hint for the text field to type the word to add to the user dictionary. [CHAR LIMIT=35] -->
|
||||
<!-- This resource is corresponding to msgid="5725254076556821247" -->
|
||||
<string name="user_dict_settings_add_word_hint">Type a word</string>
|
||||
<!-- User dictionary settings. Hint for the text field to type the optional shortcut to add to the user dictionary. [CHAR LIMIT=35] -->
|
||||
<!-- This resource is corresponding to msgid="7333763456561873445" -->
|
||||
<string name="user_dict_settings_add_shortcut_hint">Optional shortcut</string>
|
||||
<!-- User dictionary settings. The title of the dialog to edit an existing word in the user dictionary. -->
|
||||
<!-- This resource is corresponding to msgid="8967476444840548674" -->
|
||||
<string name="user_dict_settings_edit_dialog_title">Edit word</string>
|
||||
<!-- User dictionary settings. The title of the context menu item to edit the current word -->
|
||||
<!-- This resource is corresponding to msgid="2210564879320004837" -->
|
||||
<string name="user_dict_settings_context_menu_edit_title">Edit</string>
|
||||
<!-- User dictionary settings. The title of the context menu item to delete the current word -->
|
||||
<!-- This resource is corresponding to msgid="9140703913776549054" -->
|
||||
<string name="user_dict_settings_context_menu_delete_title">Delete</string>
|
||||
<!-- User dictionary settings. The text to show when there are no user-defined words in the dictionary [CHAR LIMIT=200] -->
|
||||
<!-- This resource is corresponding to msgid="8165273379942105271" -->
|
||||
<string name="user_dict_settings_empty_text">You don\'t have any words in the user dictionary. Add a word by touching the Add (+) button.</string>
|
||||
<!-- User dictionary settings. The list item to choose to insert a word into the user dictionary for all languages -->
|
||||
<!-- This resource is corresponding to msgid="6742000040975959247" -->
|
||||
<string name="user_dict_settings_all_languages">For all languages</string>
|
||||
<!-- User dictionary settings. The text to show for the option that shows the entire list of supported locales to choose one [CHAR LIMIT=30] -->
|
||||
<!-- This resource is corresponding to msgid="7316375944684977910" -->
|
||||
<string name="user_dict_settings_more_languages">More languages…</string>
|
||||
<!-- User dictionary settings. Label to delete an entry in the user dictionary [CHAR LIMIT=30]
|
||||
This resource is copied from packages/apps/Settings/res/values/strings.xml -->
|
||||
<!-- This resource is corresponding to msgid="4219243412325163003" -->
|
||||
<string name="user_dict_settings_delete">Delete</string>
|
||||
<!-- User dictionary settings. Index of the user dictionary [CHAR LIMIT=30]
|
||||
This resource is copied from packages/apps/Settings/res/values/strings.xml -->
|
||||
<!-- This resource is corresponding to msgid="5433275485499039199" -->
|
||||
<string name="user_dict_fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
|
||||
</resources>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.backup.BackupManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -24,6 +25,7 @@ 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;
|
||||
|
@ -31,17 +33,20 @@ import android.preference.Preference;
|
|||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.util.Log;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.android.inputmethod.dictionarypack.DictionarySettingsActivity;
|
||||
import com.android.inputmethod.latin.define.ProductionFlag;
|
||||
import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager;
|
||||
import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
|
||||
import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
|
||||
import com.android.inputmethodcommon.InputMethodSettingsFragment;
|
||||
|
||||
public final class SettingsFragment extends InputMethodSettingsFragment
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
private static final String TAG = SettingsFragment.class.getSimpleName();
|
||||
private static final boolean DBG_USE_INTERNAL_USER_SETTINGS = false;
|
||||
|
||||
private ListPreference mVoicePreference;
|
||||
private ListPreference mShowCorrectionSuggestionsPreference;
|
||||
|
@ -197,9 +202,13 @@ public final class SettingsFragment extends InputMethodSettingsFragment
|
|||
final Intent editPersonalDictionaryIntent = editPersonalDictionary.getIntent();
|
||||
final ResolveInfo ri = context.getPackageManager().resolveActivity(
|
||||
editPersonalDictionaryIntent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
if (ri == null) {
|
||||
// TODO: Set a intent that invokes our own edit personal dictionary activity.
|
||||
Log.w(TAG, "No activity that responds to " + editPersonalDictionaryIntent.getAction());
|
||||
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 (!Settings.readFromBuildConfigIfGestureInputEnabled(res)) {
|
||||
|
@ -408,4 +417,33 @@ public final class SettingsFragment extends InputMethodSettingsFragment
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateUserDictionaryPreference(Preference userDictionaryPreference) {
|
||||
final Activity activity = getActivity();
|
||||
final TreeSet<String> localeList = UserDictionaryList.getUserDictionaryLocalesSet(activity);
|
||||
if (null == localeList) {
|
||||
// The locale list is null if and only if the user dictionary service is
|
||||
// not present or disabled. In this case we need to remove the preference.
|
||||
getPreferenceScreen().removePreference(userDictionaryPreference);
|
||||
} else if (localeList.size() <= 1) {
|
||||
final Intent intent =
|
||||
new Intent(UserDictionaryList.USER_DICTIONARY_SETTINGS_INTENT_ACTION);
|
||||
userDictionaryPreference.setTitle(R.string.user_dict_single_settings_title);
|
||||
userDictionaryPreference.setIntent(intent);
|
||||
userDictionaryPreference.setFragment(UserDictionarySettings.class.getName());
|
||||
// If the size of localeList is 0, we don't set the locale parameter in the
|
||||
// extras. This will be interpreted by the UserDictionarySettings class as
|
||||
// meaning "the current locale".
|
||||
// Note that with the current code for UserDictionaryList#getUserDictionaryLocalesSet()
|
||||
// the locale list always has at least one element, since it always includes the current
|
||||
// locale explicitly. @see UserDictionaryList.getUserDictionaryLocalesSet().
|
||||
if (localeList.size() == 1) {
|
||||
final String locale = (String)localeList.toArray()[0];
|
||||
userDictionaryPreference.getExtras().putString("locale", locale);
|
||||
}
|
||||
} else {
|
||||
userDictionaryPreference.setTitle(R.string.user_dict_multiple_settings_title);
|
||||
userDictionaryPreference.setFragment(UserDictionaryList.class.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin.userdictionary;
|
||||
|
||||
import com.android.inputmethod.latin.LocaleUtils;
|
||||
import com.android.inputmethod.latin.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.provider.UserDictionary;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.TreeSet;
|
||||
|
||||
// Caveat: This class is basically taken from
|
||||
// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java
|
||||
// in order to deal with some devices that have issues with the user dictionary handling
|
||||
|
||||
/**
|
||||
* A container class to factor common code to UserDictionaryAddWordFragment
|
||||
* and UserDictionaryAddWordActivity.
|
||||
*/
|
||||
public class UserDictionaryAddWordContents {
|
||||
public static final String EXTRA_MODE = "mode";
|
||||
public static final String EXTRA_WORD = "word";
|
||||
public static final String EXTRA_SHORTCUT = "shortcut";
|
||||
public static final String EXTRA_LOCALE = "locale";
|
||||
public static final String EXTRA_ORIGINAL_WORD = "originalWord";
|
||||
public static final String EXTRA_ORIGINAL_SHORTCUT = "originalShortcut";
|
||||
|
||||
public static final int MODE_EDIT = 0;
|
||||
public static final int MODE_INSERT = 1;
|
||||
|
||||
/* package */ static final int CODE_WORD_ADDED = 0;
|
||||
/* package */ static final int CODE_CANCEL = 1;
|
||||
/* package */ static final int CODE_ALREADY_PRESENT = 2;
|
||||
|
||||
private static final int FREQUENCY_FOR_USER_DICTIONARY_ADDS = 250;
|
||||
|
||||
private final int mMode; // Either MODE_EDIT or MODE_INSERT
|
||||
private final EditText mWordEditText;
|
||||
private final EditText mShortcutEditText;
|
||||
private String mLocale;
|
||||
private final String mOldWord;
|
||||
private final String mOldShortcut;
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
// locale may be null, this means default locale
|
||||
// It may also be the empty string, which means "all locales"
|
||||
/* package */ void updateLocale(final String locale) {
|
||||
mLocale = null == locale ? Locale.getDefault().toString() : locale;
|
||||
}
|
||||
|
||||
/* package */ void saveStateIntoBundle(final Bundle outState) {
|
||||
outState.putString(EXTRA_WORD, mWordEditText.getText().toString());
|
||||
outState.putString(EXTRA_ORIGINAL_WORD, mOldWord);
|
||||
if (null != mShortcutEditText) {
|
||||
outState.putString(EXTRA_SHORTCUT, mShortcutEditText.getText().toString());
|
||||
}
|
||||
if (null != mOldShortcut) {
|
||||
outState.putString(EXTRA_ORIGINAL_SHORTCUT, mOldShortcut);
|
||||
}
|
||||
outState.putString(EXTRA_LOCALE, mLocale);
|
||||
}
|
||||
|
||||
/* package */ void delete(final Context context) {
|
||||
if (MODE_EDIT == mMode && !TextUtils.isEmpty(mOldWord)) {
|
||||
// Mode edit: remove the old entry.
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
UserDictionarySettings.deleteWord(mOldWord, mOldShortcut, resolver);
|
||||
}
|
||||
// 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) {
|
||||
if (null != outParameters) saveStateIntoBundle(outParameters);
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
if (MODE_EDIT == mMode && !TextUtils.isEmpty(mOldWord)) {
|
||||
// Mode edit: remove the old entry.
|
||||
UserDictionarySettings.deleteWord(mOldWord, mOldShortcut, resolver);
|
||||
}
|
||||
final String newWord = mWordEditText.getText().toString();
|
||||
final String newShortcut;
|
||||
if (null == mShortcutEditText) {
|
||||
newShortcut = null;
|
||||
} else {
|
||||
final String tmpShortcut = mShortcutEditText.getText().toString();
|
||||
if (TextUtils.isEmpty(tmpShortcut)) {
|
||||
newShortcut = null;
|
||||
} else {
|
||||
newShortcut = tmpShortcut;
|
||||
}
|
||||
}
|
||||
if (TextUtils.isEmpty(newWord)) {
|
||||
// If the word is somehow empty, don't insert it.
|
||||
return CODE_CANCEL;
|
||||
}
|
||||
// If there is no shortcut, and the word already exists in the database, then we
|
||||
// should not insert, because either A. the word exists with no shortcut, in which
|
||||
// case the exact same thing we want to insert is already there, or B. the word
|
||||
// exists with at least one shortcut, in which case it has priority on our word.
|
||||
if (hasWord(newWord, context)) return CODE_ALREADY_PRESENT;
|
||||
|
||||
// Disallow duplicates. If the same word with no shortcut is defined, remove it; if
|
||||
// the same word with the same shortcut is defined, remove it; but we don't mind if
|
||||
// there is the same word with a different, non-empty shortcut.
|
||||
UserDictionarySettings.deleteWord(newWord, null, resolver);
|
||||
if (!TextUtils.isEmpty(newShortcut)) {
|
||||
// If newShortcut is empty we just deleted this, no need to do it again
|
||||
UserDictionarySettings.deleteWord(newWord, newShortcut, resolver);
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
return CODE_WORD_ADDED;
|
||||
}
|
||||
|
||||
private static final String[] HAS_WORD_PROJECTION = { UserDictionary.Words.WORD };
|
||||
private static final String HAS_WORD_SELECTION_ONE_LOCALE = UserDictionary.Words.WORD
|
||||
+ "=? AND " + UserDictionary.Words.LOCALE + "=?";
|
||||
private static final String HAS_WORD_SELECTION_ALL_LOCALES = UserDictionary.Words.WORD
|
||||
+ "=? AND " + UserDictionary.Words.LOCALE + " is null";
|
||||
private boolean hasWord(final String word, final Context context) {
|
||||
final Cursor cursor;
|
||||
// mLocale == "" indicates this is an entry for all languages. Here, mLocale can't
|
||||
// be null at all (it's ensured by the updateLocale method).
|
||||
if ("".equals(mLocale)) {
|
||||
cursor = context.getContentResolver().query(UserDictionary.Words.CONTENT_URI,
|
||||
HAS_WORD_PROJECTION, HAS_WORD_SELECTION_ALL_LOCALES,
|
||||
new String[] { word }, null /* sort order */);
|
||||
} else {
|
||||
cursor = context.getContentResolver().query(UserDictionary.Words.CONTENT_URI,
|
||||
HAS_WORD_PROJECTION, HAS_WORD_SELECTION_ONE_LOCALE,
|
||||
new String[] { word, mLocale }, null /* sort order */);
|
||||
}
|
||||
try {
|
||||
if (null == cursor) return false;
|
||||
return cursor.getCount() > 0;
|
||||
} finally {
|
||||
if (null != cursor) cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static class LocaleRenderer {
|
||||
private final String mLocaleString;
|
||||
private final String mDescription;
|
||||
// LocaleString may NOT be null.
|
||||
public LocaleRenderer(final Context context, final String localeString) {
|
||||
mLocaleString = localeString;
|
||||
if (null == localeString) {
|
||||
mDescription = context.getString(R.string.user_dict_settings_more_languages);
|
||||
} else if ("".equals(localeString)) {
|
||||
mDescription = context.getString(R.string.user_dict_settings_all_languages);
|
||||
} else {
|
||||
mDescription = LocaleUtils.constructLocaleFromString(localeString).getDisplayName();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return mDescription;
|
||||
}
|
||||
public String getLocaleString() {
|
||||
return mLocaleString;
|
||||
}
|
||||
// "More languages..." is null ; "All languages" is the empty string.
|
||||
public boolean isMoreLanguages() {
|
||||
return null == mLocaleString;
|
||||
}
|
||||
}
|
||||
|
||||
private static void addLocaleDisplayNameToList(final Context context,
|
||||
final ArrayList<LocaleRenderer> list, final String locale) {
|
||||
if (null != locale) {
|
||||
list.add(new LocaleRenderer(context, locale));
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to get the list of locales to display for this word
|
||||
public ArrayList<LocaleRenderer> getLocalesList(final Activity activity) {
|
||||
final TreeSet<String> locales = UserDictionaryList.getUserDictionaryLocalesSet(activity);
|
||||
// Remove our locale if it's in, because we're always gonna put it at the top
|
||||
locales.remove(mLocale); // mLocale may not be null
|
||||
final String systemLocale = Locale.getDefault().toString();
|
||||
// The system locale should be inside. We want it at the 2nd spot.
|
||||
locales.remove(systemLocale); // system locale may not be null
|
||||
locales.remove(""); // Remove the empty string if it's there
|
||||
final ArrayList<LocaleRenderer> localesList = new ArrayList<LocaleRenderer>();
|
||||
// Add the passed locale, then the system locale at the top of the list. Add an
|
||||
// "all languages" entry at the bottom of the list.
|
||||
addLocaleDisplayNameToList(activity, localesList, mLocale);
|
||||
if (!systemLocale.equals(mLocale)) {
|
||||
addLocaleDisplayNameToList(activity, localesList, systemLocale);
|
||||
}
|
||||
for (final String l : locales) {
|
||||
// TODO: sort in unicode order
|
||||
addLocaleDisplayNameToList(activity, localesList, l);
|
||||
}
|
||||
if (!"".equals(mLocale)) {
|
||||
// If mLocale is "", then we already inserted the "all languages" item, so don't do it
|
||||
addLocaleDisplayNameToList(activity, localesList, ""); // meaning: all languages
|
||||
}
|
||||
localesList.add(new LocaleRenderer(activity, null)); // meaning: select another locale
|
||||
return localesList;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin.userdictionary;
|
||||
|
||||
import com.android.inputmethod.latin.R;
|
||||
import com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordContents.LocaleRenderer;
|
||||
import com.android.inputmethod.latin.userdictionary.UserDictionaryLocalePicker.LocationChangedListener;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
// Caveat: This class is basically taken from
|
||||
// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryAddWordFragment.java
|
||||
// in order to deal with some devices that have issues with the user dictionary handling
|
||||
|
||||
/**
|
||||
* Fragment to add a word/shortcut to the user dictionary.
|
||||
*
|
||||
* As opposed to the UserDictionaryActivity, this is only invoked within Settings
|
||||
* from the UserDictionarySettings.
|
||||
*/
|
||||
public class UserDictionaryAddWordFragment extends Fragment
|
||||
implements AdapterView.OnItemSelectedListener, LocationChangedListener {
|
||||
|
||||
private static final int OPTIONS_MENU_DELETE = Menu.FIRST;
|
||||
|
||||
private UserDictionaryAddWordContents mContents;
|
||||
private View mRootView;
|
||||
private boolean mIsDeleting = false;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
|
||||
mRootView = inflater.inflate(R.layout.user_dictionary_add_word_fullscreen, null);
|
||||
mIsDeleting = false;
|
||||
if (null == mContents) {
|
||||
mContents = new UserDictionaryAddWordContents(mRootView, getArguments());
|
||||
}
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
MenuItem actionItem = 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_DELETE) {
|
||||
mContents.delete(getActivity());
|
||||
mIsDeleting = true;
|
||||
getActivity().onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
// We are being shown: display the word
|
||||
updateSpinner();
|
||||
}
|
||||
|
||||
private void updateSpinner() {
|
||||
final ArrayList<LocaleRenderer> localesList = mContents.getLocalesList(getActivity());
|
||||
|
||||
final Spinner localeSpinner =
|
||||
(Spinner)mRootView.findViewById(R.id.user_dictionary_add_locale);
|
||||
final ArrayAdapter<LocaleRenderer> adapter = new ArrayAdapter<LocaleRenderer>(getActivity(),
|
||||
android.R.layout.simple_spinner_item, localesList);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
localeSpinner.setAdapter(adapter);
|
||||
localeSpinner.setOnItemSelectedListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
// We are being hidden: commit changes to the user dictionary, unless we were deleting it
|
||||
if (!mIsDeleting) {
|
||||
mContents.apply(getActivity(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemSelected(final AdapterView<?> parent, final View view, final int pos,
|
||||
final long id) {
|
||||
final LocaleRenderer locale = (LocaleRenderer)parent.getItemAtPosition(pos);
|
||||
if (locale.isMoreLanguages()) {
|
||||
PreferenceActivity preferenceActivity = (PreferenceActivity)getActivity();
|
||||
preferenceActivity.startPreferenceFragment(new UserDictionaryLocalePicker(), true);
|
||||
} else {
|
||||
mContents.updateLocale(locale.getLocaleString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(final AdapterView<?> parent) {
|
||||
// I'm not sure we can come here, but if we do, that's the right thing to do.
|
||||
final Bundle args = getArguments();
|
||||
mContents.updateLocale(args.getString(UserDictionaryAddWordContents.EXTRA_LOCALE));
|
||||
}
|
||||
|
||||
// Called by the locale picker
|
||||
@Override
|
||||
public void onLocaleSelected(final Locale locale) {
|
||||
mContents.updateLocale(locale.toString());
|
||||
getActivity().onBackPressed();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin.userdictionary;
|
||||
|
||||
import com.android.inputmethod.latin.LocaleUtils;
|
||||
import com.android.inputmethod.latin.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.provider.UserDictionary;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TreeSet;
|
||||
|
||||
// Caveat: This class is basically taken from
|
||||
// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryList.java
|
||||
// in order to deal with some devices that have issues with the user dictionary handling
|
||||
|
||||
public class UserDictionaryList extends PreferenceFragment {
|
||||
|
||||
public static final String USER_DICTIONARY_SETTINGS_INTENT_ACTION =
|
||||
"android.settings.USER_DICTIONARY_SETTINGS";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
|
||||
}
|
||||
|
||||
public static TreeSet<String> getUserDictionaryLocalesSet(Activity activity) {
|
||||
@SuppressWarnings("deprecation")
|
||||
final Cursor cursor = activity.managedQuery(UserDictionary.Words.CONTENT_URI,
|
||||
new String[] { UserDictionary.Words.LOCALE },
|
||||
null, null, null);
|
||||
final TreeSet<String> localeList = new TreeSet<String>();
|
||||
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 : "");
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
localeList.add(Locale.getDefault().toString());
|
||||
return localeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the entries that allow the user to go into the user dictionary for each locale.
|
||||
* @param userDictGroup The group to put the settings in.
|
||||
*/
|
||||
protected void createUserDictSettings(PreferenceGroup userDictGroup) {
|
||||
final Activity activity = getActivity();
|
||||
userDictGroup.removeAll();
|
||||
final TreeSet<String> localeList =
|
||||
UserDictionaryList.getUserDictionaryLocalesSet(activity);
|
||||
|
||||
if (localeList.isEmpty()) {
|
||||
userDictGroup.addPreference(createUserDictionaryPreference(null, activity));
|
||||
} else {
|
||||
for (String locale : localeList) {
|
||||
userDictGroup.addPreference(createUserDictionaryPreference(locale, activity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single User Dictionary Preference object, with its parameters set.
|
||||
* @param locale The locale for which this user dictionary is for.
|
||||
* @return The corresponding preference.
|
||||
*/
|
||||
protected Preference createUserDictionaryPreference(String locale, Activity activity) {
|
||||
final Preference newPref = new Preference(getActivity());
|
||||
final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION);
|
||||
if (null == locale) {
|
||||
newPref.setTitle(Locale.getDefault().getDisplayName());
|
||||
} else {
|
||||
if ("".equals(locale))
|
||||
newPref.setTitle(getString(R.string.user_dict_settings_all_languages));
|
||||
else
|
||||
newPref.setTitle(LocaleUtils.constructLocaleFromString(locale).getDisplayName());
|
||||
intent.putExtra("locale", locale);
|
||||
newPref.getExtras().putString("locale", locale);
|
||||
}
|
||||
newPref.setIntent(intent);
|
||||
newPref.setFragment(UserDictionarySettings.class.getName());
|
||||
return newPref;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
createUserDictSettings(getPreferenceScreen());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin.userdictionary;
|
||||
|
||||
import android.app.Fragment;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
// Caveat: This class is basically taken from
|
||||
// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryLocalePicker.java
|
||||
// in order to deal with some devices that have issues with the user dictionary handling
|
||||
|
||||
public class UserDictionaryLocalePicker extends Fragment {
|
||||
public UserDictionaryLocalePicker() {
|
||||
super();
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
public interface LocationChangedListener {
|
||||
public void onLocaleSelected(Locale locale);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,286 @@
|
|||
/**
|
||||
* Copyright (C) 2013 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin.userdictionary;
|
||||
|
||||
import com.android.inputmethod.latin.R;
|
||||
|
||||
import android.app.ListFragment;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.provider.UserDictionary;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AlphabetIndexer;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SectionIndexer;
|
||||
import android.widget.SimpleCursorAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
// Caveat: This class is basically taken from
|
||||
// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionarySettings.java
|
||||
// in order to deal with some devices that have issues with the user dictionary handling
|
||||
|
||||
public class UserDictionarySettings extends ListFragment {
|
||||
|
||||
private static final String[] QUERY_PROJECTION = {
|
||||
UserDictionary.Words._ID, UserDictionary.Words.WORD, UserDictionary.Words.SHORTCUT
|
||||
};
|
||||
|
||||
// The index of the shortcut in the above array.
|
||||
private static final int INDEX_SHORTCUT = 2;
|
||||
|
||||
// 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 =
|
||||
UserDictionary.Words.LOCALE + "=?";
|
||||
private static final String QUERY_SELECTION_ALL_LOCALES =
|
||||
UserDictionary.Words.LOCALE + " is null";
|
||||
|
||||
private static final String DELETE_SELECTION_WITH_SHORTCUT = UserDictionary.Words.WORD
|
||||
+ "=? AND " + UserDictionary.Words.SHORTCUT + "=?";
|
||||
private static final String DELETE_SELECTION_WITHOUT_SHORTCUT = UserDictionary.Words.WORD
|
||||
+ "=? AND " + UserDictionary.Words.SHORTCUT + " is null OR "
|
||||
+ UserDictionary.Words.SHORTCUT + "=''";
|
||||
|
||||
private static final int OPTIONS_MENU_ADD = Menu.FIRST;
|
||||
|
||||
private Cursor mCursor;
|
||||
|
||||
protected String mLocale;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(
|
||||
R.layout.user_dictionary_preference_list_fragment, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
final Intent intent = getActivity().getIntent();
|
||||
final String localeFromIntent =
|
||||
null == intent ? null : intent.getStringExtra("locale");
|
||||
|
||||
final Bundle arguments = getArguments();
|
||||
final String localeFromArguments =
|
||||
null == arguments ? null : arguments.getString("locale");
|
||||
|
||||
final String locale;
|
||||
if (null != localeFromArguments) {
|
||||
locale = localeFromArguments;
|
||||
} else if (null != localeFromIntent) {
|
||||
locale = localeFromIntent;
|
||||
} else {
|
||||
locale = null;
|
||||
}
|
||||
|
||||
mLocale = locale;
|
||||
mCursor = createCursor(locale);
|
||||
TextView emptyView = (TextView) getView().findViewById(android.R.id.empty);
|
||||
emptyView.setText(R.string.user_dict_settings_empty_text);
|
||||
|
||||
final ListView listView = getListView();
|
||||
listView.setAdapter(createAdapter());
|
||||
listView.setFastScrollEnabled(true);
|
||||
listView.setEmptyView(emptyView);
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private Cursor createCursor(final String locale) {
|
||||
// Locale can be any of:
|
||||
// - The string representation of a locale, as returned by Locale#toString()
|
||||
// - The empty string. This means we want a cursor returning words valid for all locales.
|
||||
// - null. This means we want a cursor for the current locale, whatever this is.
|
||||
// Note that this contrasts with the data inside the database, where NULL means "all
|
||||
// locales" and there should never be an empty string. The confusion is called by the
|
||||
// historical use of null for "all locales".
|
||||
// TODO: it should be easy to make this more readable by making the special values
|
||||
// human-readable, like "all_locales" and "current_locales" strings, provided they
|
||||
// can be guaranteed not to match locales that may exist.
|
||||
if ("".equals(locale)) {
|
||||
// Case-insensitive sort
|
||||
return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
|
||||
QUERY_SELECTION_ALL_LOCALES, null,
|
||||
"UPPER(" + UserDictionary.Words.WORD + ")");
|
||||
} else {
|
||||
final String queryLocale = null != locale ? locale : Locale.getDefault().toString();
|
||||
return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
|
||||
QUERY_SELECTION, new String[] { queryLocale },
|
||||
"UPPER(" + UserDictionary.Words.WORD + ")");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
final String word = getWord(position);
|
||||
final String shortcut = getShortcut(position);
|
||||
if (word != null) {
|
||||
showAddOrEditDialog(word, shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == OPTIONS_MENU_ADD) {
|
||||
showAddOrEditDialog(null, null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or edit a word. If editingWord is null, it's an add; otherwise, it's an edit.
|
||||
* @param editingWord the word to edit, or null if it's an add.
|
||||
* @param editingShortcut the shortcut for this entry, or null if none.
|
||||
*/
|
||||
private void showAddOrEditDialog(final String editingWord, final String editingShortcut) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putInt(UserDictionaryAddWordContents.EXTRA_MODE, null == editingWord
|
||||
? UserDictionaryAddWordContents.MODE_INSERT
|
||||
: UserDictionaryAddWordContents.MODE_EDIT);
|
||||
args.putString(UserDictionaryAddWordContents.EXTRA_WORD, editingWord);
|
||||
args.putString(UserDictionaryAddWordContents.EXTRA_SHORTCUT, editingShortcut);
|
||||
args.putString(UserDictionaryAddWordContents.EXTRA_LOCALE, mLocale);
|
||||
android.preference.PreferenceActivity pa =
|
||||
(android.preference.PreferenceActivity)getActivity();
|
||||
pa.startPreferencePanel(UserDictionaryAddWordFragment.class.getName(),
|
||||
args, R.string.user_dict_settings_add_dialog_title, null, null, 0);
|
||||
}
|
||||
|
||||
private String getWord(final int position) {
|
||||
if (null == mCursor) return null;
|
||||
mCursor.moveToPosition(position);
|
||||
// Handle a possible race-condition
|
||||
if (mCursor.isAfterLast()) return null;
|
||||
|
||||
return mCursor.getString(
|
||||
mCursor.getColumnIndexOrThrow(UserDictionary.Words.WORD));
|
||||
}
|
||||
|
||||
private String getShortcut(final int position) {
|
||||
if (null == mCursor) return null;
|
||||
mCursor.moveToPosition(position);
|
||||
// Handle a possible race-condition
|
||||
if (mCursor.isAfterLast()) return null;
|
||||
|
||||
return mCursor.getString(
|
||||
mCursor.getColumnIndexOrThrow(UserDictionary.Words.SHORTCUT));
|
||||
}
|
||||
|
||||
public static void deleteWord(final String word, final String shortcut,
|
||||
final ContentResolver resolver) {
|
||||
if (TextUtils.isEmpty(shortcut)) {
|
||||
resolver.delete(
|
||||
UserDictionary.Words.CONTENT_URI, DELETE_SELECTION_WITHOUT_SHORTCUT,
|
||||
new String[] { word });
|
||||
} else {
|
||||
resolver.delete(
|
||||
UserDictionary.Words.CONTENT_URI, DELETE_SELECTION_WITH_SHORTCUT,
|
||||
new String[] { word, shortcut });
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyAdapter extends SimpleCursorAdapter implements SectionIndexer {
|
||||
|
||||
private AlphabetIndexer mIndexer;
|
||||
|
||||
private ViewBinder mViewBinder = new ViewBinder() {
|
||||
|
||||
@Override
|
||||
public boolean setViewValue(View v, Cursor c, int columnIndex) {
|
||||
if (columnIndex == INDEX_SHORTCUT) {
|
||||
final String shortcut = c.getString(INDEX_SHORTCUT);
|
||||
if (TextUtils.isEmpty(shortcut)) {
|
||||
v.setVisibility(View.GONE);
|
||||
} else {
|
||||
((TextView)v).setText(shortcut);
|
||||
v.setVisibility(View.VISIBLE);
|
||||
}
|
||||
v.invalidate();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to,
|
||||
UserDictionarySettings settings) {
|
||||
super(context, layout, c, from, to);
|
||||
|
||||
if (null != c) {
|
||||
final String alphabet = context.getString(R.string.user_dict_fast_scroll_alphabet);
|
||||
final int wordColIndex = c.getColumnIndexOrThrow(UserDictionary.Words.WORD);
|
||||
mIndexer = new AlphabetIndexer(c, wordColIndex, alphabet);
|
||||
}
|
||||
setViewBinder(mViewBinder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPositionForSection(int section) {
|
||||
return null == mIndexer ? 0 : mIndexer.getPositionForSection(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSectionForPosition(int position) {
|
||||
return null == mIndexer ? 0 : mIndexer.getSectionForPosition(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getSections() {
|
||||
return null == mIndexer ? null : mIndexer.getSections();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue