Add an option to use contacts or not while spell checking
Bug: 5447495 Change-Id: Iffb09895676c3dd1a79d1699b0eac865282508d4main
parent
70b8934f0e
commit
db5aedb5a5
|
@ -31,11 +31,11 @@
|
|||
<!-- Title for the spell checking service settings screen -->
|
||||
<string name="android_spell_checker_settings">Spell checking settings</string>
|
||||
|
||||
<!-- Title for the "use proximity" option for spell checking [CHAR LIMIT=25] -->
|
||||
<string name="use_proximity_option_title">Use proximity data</string>
|
||||
<!-- Title for the spell checker option to turn on/off contact names lookup [CHAR LIMIT=25] -->
|
||||
<string name="use_contacts_for_spellchecking_option_title">Look up contact names</string>
|
||||
|
||||
<!-- Description for the "use proximity" option for spell checking [CHAR LIMIT=65] -->
|
||||
<string name="use_proximity_option_summary">Use a keyboard-like proximity algorithm for spell checking</string>
|
||||
<!-- Description for the spell checker option to turn on/off contact names lookup. [CHAR LIMIT=65] -->
|
||||
<string name="use_contacts_for_spellchecking_option_summary">Spell checker uses entries from your contact list</string>
|
||||
|
||||
<!-- Option to provide vibrate/haptic feedback on keypress -->
|
||||
<string name="vibrate_on_keypress">Vibrate on keypress</string>
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/android_spell_checker_settings">
|
||||
<CheckBoxPreference
|
||||
android:key="use_proximity"
|
||||
android:title="@string/use_proximity_option_title"
|
||||
android:summary="@string/use_proximity_option_summary"
|
||||
android:key="pref_spellcheck_use_contacts"
|
||||
android:title="@string/use_contacts_for_spellchecking_option_title"
|
||||
android:summary="@string/use_contacts_for_spellchecking_option_summary"
|
||||
android:persistent="true"
|
||||
android:defaultValue="true" />
|
||||
</PreferenceScreen>
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
<!-- for the spell checker -->
|
||||
|
||||
<spell-checker xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:label="@string/spell_checker_service_name">
|
||||
android:label="@string/spell_checker_service_name"
|
||||
android:settingsActivity="com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsActivity">
|
||||
<subtype
|
||||
android:label="@string/subtype_generic"
|
||||
android:subtypeLocale="en"
|
||||
|
|
|
@ -18,6 +18,8 @@ package com.android.inputmethod.latin;
|
|||
|
||||
import com.android.inputmethod.keyboard.ProximityInfo;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -27,7 +29,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||
* Class for a collection of dictionaries that behave like one dictionary.
|
||||
*/
|
||||
public class DictionaryCollection extends Dictionary {
|
||||
|
||||
private final String TAG = DictionaryCollection.class.getSimpleName();
|
||||
protected final List<Dictionary> mDictionaries;
|
||||
|
||||
public DictionaryCollection() {
|
||||
|
@ -75,7 +77,21 @@ public class DictionaryCollection extends Dictionary {
|
|||
dict.close();
|
||||
}
|
||||
|
||||
public void addDictionary(Dictionary newDict) {
|
||||
if (null != newDict) mDictionaries.add(newDict);
|
||||
// Warning: this is not thread-safe. Take necessary precaution when calling.
|
||||
public void addDictionary(final Dictionary newDict) {
|
||||
if (null == newDict) return;
|
||||
if (mDictionaries.contains(newDict)) {
|
||||
Log.w(TAG, "This collection already contains this dictionary: " + newDict);
|
||||
}
|
||||
mDictionaries.add(newDict);
|
||||
}
|
||||
|
||||
// Warning: this is not thread-safe. Take necessary precaution when calling.
|
||||
public void removeDictionary(final Dictionary dict) {
|
||||
if (mDictionaries.contains(dict)) {
|
||||
mDictionaries.remove(dict);
|
||||
} else {
|
||||
Log.w(TAG, "This collection does not contain this dictionary: " + dict);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
package com.android.inputmethod.latin.spellcheck;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.service.textservice.SpellCheckerService;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
@ -41,21 +43,27 @@ import com.android.inputmethod.latin.Utils;
|
|||
import com.android.inputmethod.latin.WhitelistDictionary;
|
||||
import com.android.inputmethod.latin.WordComposer;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* Service for spell checking, using LatinIME's dictionaries and mechanisms.
|
||||
*/
|
||||
public class AndroidSpellCheckerService extends SpellCheckerService {
|
||||
public class AndroidSpellCheckerService extends SpellCheckerService
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
private static final String TAG = AndroidSpellCheckerService.class.getSimpleName();
|
||||
private static final boolean DBG = false;
|
||||
private static final int POOL_SIZE = 2;
|
||||
|
||||
public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts";
|
||||
|
||||
private static final int CAPITALIZE_NONE = 0; // No caps, or mixed case
|
||||
private static final int CAPITALIZE_FIRST = 1; // First only
|
||||
private static final int CAPITALIZE_ALL = 2; // All caps
|
||||
|
@ -84,6 +92,12 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
|
|||
private double mSuggestionThreshold;
|
||||
// The threshold for a suggestion to be considered "recommended".
|
||||
private double mRecommendedThreshold;
|
||||
// Whether to use the contacts dictionary
|
||||
private boolean mUseContactsDictionary;
|
||||
private final Object mUseContactsLock = new Object();
|
||||
|
||||
private final HashSet<WeakReference<DictionaryCollection>> mDictionaryCollectionsList =
|
||||
new HashSet<WeakReference<DictionaryCollection>>();
|
||||
|
||||
@Override public void onCreate() {
|
||||
super.onCreate();
|
||||
|
@ -91,6 +105,57 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
|
|||
Double.parseDouble(getString(R.string.spellchecker_suggestion_threshold_value));
|
||||
mRecommendedThreshold =
|
||||
Double.parseDouble(getString(R.string.spellchecker_recommended_threshold_value));
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
prefs.registerOnSharedPreferenceChangeListener(this);
|
||||
onSharedPreferenceChanged(prefs, PREF_USE_CONTACTS_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
|
||||
if (!PREF_USE_CONTACTS_KEY.equals(key)) return;
|
||||
synchronized(mUseContactsLock) {
|
||||
mUseContactsDictionary = prefs.getBoolean(PREF_USE_CONTACTS_KEY, true);
|
||||
if (mUseContactsDictionary) {
|
||||
startUsingContactsDictionaryLocked();
|
||||
} else {
|
||||
stopUsingContactsDictionaryLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startUsingContactsDictionaryLocked() {
|
||||
if (null == mContactsDictionary) {
|
||||
mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
|
||||
}
|
||||
final Iterator<WeakReference<DictionaryCollection>> iterator =
|
||||
mDictionaryCollectionsList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final WeakReference<DictionaryCollection> dictRef = iterator.next();
|
||||
final DictionaryCollection dict = dictRef.get();
|
||||
if (null == dict) {
|
||||
iterator.remove();
|
||||
} else {
|
||||
dict.addDictionary(mContactsDictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void stopUsingContactsDictionaryLocked() {
|
||||
if (null == mContactsDictionary) return;
|
||||
final SynchronouslyLoadedContactsDictionary contactsDict = mContactsDictionary;
|
||||
mContactsDictionary = null;
|
||||
final Iterator<WeakReference<DictionaryCollection>> iterator =
|
||||
mDictionaryCollectionsList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final WeakReference<DictionaryCollection> dictRef = iterator.next();
|
||||
final DictionaryCollection dict = dictRef.get();
|
||||
if (null == dict) {
|
||||
iterator.remove();
|
||||
} else {
|
||||
dict.removeDictionary(contactsDict);
|
||||
}
|
||||
}
|
||||
contactsDict.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -274,6 +339,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
|
|||
for (Dictionary dict : oldWhitelistDictionaries.values()) {
|
||||
dict.close();
|
||||
}
|
||||
synchronized(mUseContactsLock) {
|
||||
if (null != mContactsDictionary) {
|
||||
// The synchronously loaded contacts dictionary should have been in one
|
||||
// or several pools, but it is shielded against multiple closing and it's
|
||||
|
@ -282,6 +348,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
|
|||
mContactsDictionary = null;
|
||||
dictToClose.close();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -315,11 +382,16 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
|
|||
mWhitelistDictionaries.put(localeStr, whitelistDictionary);
|
||||
}
|
||||
dictionaryCollection.addDictionary(whitelistDictionary);
|
||||
synchronized(mUseContactsLock) {
|
||||
if (mUseContactsDictionary) {
|
||||
if (null == mContactsDictionary) {
|
||||
mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
|
||||
}
|
||||
// TODO: add a setting to use or not contacts when checking spelling
|
||||
}
|
||||
dictionaryCollection.addDictionary(mContactsDictionary);
|
||||
mDictionaryCollectionsList.add(
|
||||
new WeakReference<DictionaryCollection>(dictionaryCollection));
|
||||
}
|
||||
return new DictAndProximity(dictionaryCollection, proximityInfo);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue