aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod')
-rw-r--r--java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java56
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java (renamed from java/src/com/android/inputmethod/keyboard/EmojiKeyboardView.java)98
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java30
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java40
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java69
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/ScrollKeyboardView.java3
-rw-r--r--java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java11
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java4
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java4
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryWriter.java4
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java15
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableDictionary.java30
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java43
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java8
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java6
-rw-r--r--java/src/com/android/inputmethod/latin/UserBinaryDictionary.java9
-rw-r--r--java/src/com/android/inputmethod/latin/about/AboutPreferences.java28
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java5
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java6
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java10
-rw-r--r--java/src/com/android/inputmethod/latin/settings/DebugSettingsActivity.java3
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SettingsActivity.java4
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SettingsValues.java4
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java14
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java42
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java4
-rw-r--r--java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java18
-rw-r--r--java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java20
-rw-r--r--java/src/com/android/inputmethod/latin/utils/FragmentUtils.java52
-rw-r--r--java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java13
33 files changed, 507 insertions, 154 deletions
diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
new file mode 100644
index 000000000..b119d6c82
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
@@ -0,0 +1,56 @@
+/*
+ * 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.compat;
+
+import android.os.Build;
+import android.view.inputmethod.InputMethodSubtype;
+
+import java.lang.reflect.Constructor;
+
+public final class InputMethodSubtypeCompatUtils {
+ private static final String TAG = InputMethodSubtypeCompatUtils.class.getSimpleName();
+ // Note that InputMethodSubtype(int nameId, int iconId, String locale, String mode,
+ // String extraValue, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, int id)
+ // has been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
+ private static final Constructor<?> CONSTRUCTOR_INPUT_METHOD_SUBTYPE =
+ CompatUtils.getConstructor(InputMethodSubtype.class,
+ Integer.TYPE, Integer.TYPE, String.class, String.class, String.class,
+ Boolean.TYPE, Boolean.TYPE, Integer.TYPE);
+ static {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ if (CONSTRUCTOR_INPUT_METHOD_SUBTYPE == null) {
+ android.util.Log.w(TAG, "Warning!!! Constructor is not defined.");
+ }
+ }
+ }
+ private InputMethodSubtypeCompatUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale,
+ String mode, String extraValue, boolean isAuxiliary,
+ boolean overridesImplicitlyEnabledSubtype, int id) {
+ if (CONSTRUCTOR_INPUT_METHOD_SUBTYPE == null
+ || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ return new InputMethodSubtype(nameId, iconId, locale, mode, extraValue, isAuxiliary,
+ overridesImplicitlyEnabledSubtype);
+ }
+ return (InputMethodSubtype) CompatUtils.newInstance(CONSTRUCTOR_INPUT_METHOD_SUBTYPE,
+ nameId, iconId, locale, mode, extraValue, isAuxiliary,
+ overridesImplicitlyEnabledSubtype, id);
+ }
+}
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java
index c28d72949..4366348d5 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.dictionarypack;
+import com.android.inputmethod.latin.utils.FragmentUtils;
+
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceActivity;
@@ -45,6 +47,6 @@ public final class DictionarySettingsActivity extends PreferenceActivity {
// TODO: Uncomment the override annotation once we start using SDK version 19.
// @Override
public boolean isValidFragment(String fragmentName) {
- return fragmentName.equals(DEFAULT_FRAGMENT);
+ return FragmentUtils.isValidFragment(fragmentName);
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/EmojiKeyboardView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
index db7c845bc..9779c683c 100644
--- a/java/src/com/android/inputmethod/keyboard/EmojiKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
@@ -60,8 +60,8 @@ import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
/**
- * View class to implement Emoji keyboards.
- * The Emoji keyboard consists of group of views {@link R.layout#emoji_keyboard_view}.
+ * View class to implement Emoji palettes.
+ * The Emoji keyboard consists of group of views {@link R.layout#emoji_palettes_view}.
* <ol>
* <li> Emoji category tabs.
* <li> Delete button.
@@ -70,19 +70,21 @@ import java.util.concurrent.ConcurrentHashMap;
* </ol>
* Because of the above reasons, this class doesn't extend {@link KeyboardView}.
*/
-public final class EmojiKeyboardView extends LinearLayout implements OnTabChangeListener,
+public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener,
ViewPager.OnPageChangeListener, View.OnClickListener,
ScrollKeyboardView.OnKeyClickListener {
- private static final String TAG = EmojiKeyboardView.class.getSimpleName();
+ private static final String TAG = EmojiPalettesView.class.getSimpleName();
+ private static final boolean DEBUG_PAGER = false;
private final int mKeyBackgroundId;
private final int mEmojiFunctionalKeyBackgroundId;
private final KeyboardLayoutSet mLayoutSet;
private final ColorStateList mTabLabelColor;
private final DeleteKeyOnTouchListener mDeleteKeyOnTouchListener;
- private EmojiKeyboardAdapter mEmojiKeyboardAdapter;
+ private EmojiPalettesAdapter mEmojiPalettesAdapter;
private TabHost mTabHost;
private ViewPager mEmojiPager;
+ private int mCurrentPagerPosition = 0;
private EmojiCategoryPageIndicatorView mEmojiCategoryPageIndicatorView;
private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER;
@@ -378,11 +380,11 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
private final EmojiCategory mEmojiCategory;
- public EmojiKeyboardView(final Context context, final AttributeSet attrs) {
- this(context, attrs, R.attr.emojiKeyboardViewStyle);
+ public EmojiPalettesView(final Context context, final AttributeSet attrs) {
+ this(context, attrs, R.attr.emojiPalettesViewStyle);
}
- public EmojiKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) {
+ public EmojiPalettesView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
final TypedArray keyboardViewAttr = context.obtainStyledAttributes(attrs,
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
@@ -391,11 +393,11 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
mEmojiFunctionalKeyBackgroundId = keyboardViewAttr.getResourceId(
R.styleable.KeyboardView_keyBackgroundEmojiFunctional, 0);
keyboardViewAttr.recycle();
- final TypedArray emojiKeyboardViewAttr = context.obtainStyledAttributes(attrs,
- R.styleable.EmojiKeyboardView, defStyle, R.style.EmojiKeyboardView);
- mTabLabelColor = emojiKeyboardViewAttr.getColorStateList(
- R.styleable.EmojiKeyboardView_emojiTabLabelColor);
- emojiKeyboardViewAttr.recycle();
+ final TypedArray emojiPalettesViewAttr = context.obtainStyledAttributes(attrs,
+ R.styleable.EmojiPalettesView, defStyle, R.style.EmojiPalettesView);
+ mTabLabelColor = emojiPalettesViewAttr.getColorStateList(
+ R.styleable.EmojiPalettesView_emojiTabLabelColor);
+ emojiPalettesViewAttr.recycle();
final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
context, null /* editorInfo */);
final Resources res = context.getResources();
@@ -453,12 +455,13 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
mTabHost.setOnTabChangedListener(this);
mTabHost.getTabWidget().setStripEnabled(true);
- mEmojiKeyboardAdapter = new EmojiKeyboardAdapter(mEmojiCategory, mLayoutSet, this);
+ mEmojiPalettesAdapter = new EmojiPalettesAdapter(mEmojiCategory, mLayoutSet, this);
mEmojiPager = (ViewPager)findViewById(R.id.emoji_keyboard_pager);
- mEmojiPager.setAdapter(mEmojiKeyboardAdapter);
+ mEmojiPager.setAdapter(mEmojiPalettesAdapter);
mEmojiPager.setOnPageChangeListener(this);
mEmojiPager.setOffscreenPageLimit(0);
+ mEmojiPager.setPersistentDrawingCache(ViewPager.PERSISTENT_NO_CACHE);
final Resources res = getResources();
final EmojiLayoutParams emojiLp = new EmojiLayoutParams(res);
emojiLp.setPagerProperties(mEmojiPager);
@@ -484,10 +487,10 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
spaceKey.setTag(Constants.CODE_SPACE);
spaceKey.setOnClickListener(this);
emojiLp.setKeyProperties(spaceKey);
- final ImageView sendKey = (ImageView)findViewById(R.id.emoji_keyboard_send);
- sendKey.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
- sendKey.setTag(Constants.CODE_ENTER);
- sendKey.setOnClickListener(this);
+ final ImageView alphabetKey2 = (ImageView)findViewById(R.id.emoji_keyboard_alphabet2);
+ alphabetKey2.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
+ alphabetKey2.setTag(Constants.CODE_SWITCH_ALPHA_SYMBOL);
+ alphabetKey2.setOnClickListener(this);
}
@Override
@@ -505,6 +508,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
setCurrentCategoryId(newPos.first /* categoryId */, false /* force */);
mEmojiCategory.setCurrentCategoryPageId(newPos.second /* categoryPageId */);
updateEmojiCategoryPageIdView();
+ mCurrentPagerPosition = position;
}
@Override
@@ -551,7 +555,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
@Override
public void onKeyClick(final Key key) {
- mEmojiKeyboardAdapter.addRecentKey(key);
+ mEmojiPalettesAdapter.addRecentKey(key);
mEmojiCategory.saveLastTypedCategoryPage();
final int code = key.getCode();
if (code == Constants.CODE_OUTPUT_TEXT) {
@@ -565,6 +569,22 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
// TODO:
}
+ public void startEmojiPalettes() {
+ if (DEBUG_PAGER) {
+ Log.d(TAG, "allocate emoji palettes memory " + mCurrentPagerPosition);
+ }
+ mEmojiPager.setAdapter(mEmojiPalettesAdapter);
+ mEmojiPager.setCurrentItem(mCurrentPagerPosition);
+ }
+
+ public void stopEmojiPalettes() {
+ if (DEBUG_PAGER) {
+ Log.d(TAG, "deallocate emoji palettes memory");
+ }
+ mEmojiPalettesAdapter.flushPendingRecentKeys();
+ mEmojiPager.setAdapter(null);
+ }
+
public void setKeyboardActionListener(final KeyboardActionListener listener) {
mKeyboardActionListener = listener;
mDeleteKeyOnTouchListener.setKeyboardActionListener(mKeyboardActionListener);
@@ -589,7 +609,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
// Needs to save pending updates for recent keys when we get out of the recents
// category because we don't want to move the recent emojis around while the user
// is in the recents category.
- mEmojiKeyboardAdapter.flushPendingRecentKeys();
+ mEmojiPalettesAdapter.flushPendingRecentKeys();
}
mEmojiCategory.setCurrentCategoryId(categoryId);
@@ -604,15 +624,15 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
}
}
- private static class EmojiKeyboardAdapter extends PagerAdapter {
+ private static class EmojiPalettesAdapter extends PagerAdapter {
private final ScrollKeyboardView.OnKeyClickListener mListener;
private final DynamicGridKeyboard mRecentsKeyboard;
- private final SparseArray<ScrollKeyboardView> mActiveKeyboardView =
+ private final SparseArray<ScrollKeyboardView> mActiveKeyboardViews =
CollectionUtils.newSparseArray();
private final EmojiCategory mEmojiCategory;
private int mActivePosition = 0;
- public EmojiKeyboardAdapter(final EmojiCategory emojiCategory,
+ public EmojiPalettesAdapter(final EmojiCategory emojiCategory,
final KeyboardLayoutSet layoutSet,
final ScrollKeyboardView.OnKeyClickListener listener) {
mEmojiCategory = emojiCategory;
@@ -623,7 +643,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
public void flushPendingRecentKeys() {
mRecentsKeyboard.flushPendingRecentKeys();
final KeyboardView recentKeyboardView =
- mActiveKeyboardView.get(mEmojiCategory.getRecentTabId());
+ mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
if (recentKeyboardView != null) {
recentKeyboardView.invalidateAllKeys();
}
@@ -636,7 +656,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
}
mRecentsKeyboard.addKeyFirst(key);
final KeyboardView recentKeyboardView =
- mActiveKeyboardView.get(mEmojiCategory.getRecentTabId());
+ mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
if (recentKeyboardView != null) {
recentKeyboardView.invalidateAllKeys();
}
@@ -652,7 +672,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
if (mActivePosition == position) {
return;
}
- final ScrollKeyboardView oldKeyboardView = mActiveKeyboardView.get(mActivePosition);
+ final ScrollKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition);
if (oldKeyboardView != null) {
oldKeyboardView.releaseCurrentKey();
oldKeyboardView.deallocateMemory();
@@ -662,6 +682,15 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
@Override
public Object instantiateItem(final ViewGroup container, final int position) {
+ if (DEBUG_PAGER) {
+ Log.d(TAG, "instantiate item: " + position);
+ }
+ final ScrollKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position);
+ if (oldKeyboardView != null) {
+ oldKeyboardView.deallocateMemory();
+ // This may be redundant but wanted to be safer..
+ mActiveKeyboardViews.remove(position);
+ }
final Keyboard keyboard =
mEmojiCategory.getKeyboardFromPagePosition(position);
final LayoutInflater inflater = LayoutInflater.from(container.getContext());
@@ -675,7 +704,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
R.id.emoji_keyboard_scroller);
keyboardView.setScrollView(scrollView);
container.addView(view);
- mActiveKeyboardView.put(position, keyboardView);
+ mActiveKeyboardViews.put(position, keyboardView);
return view;
}
@@ -687,12 +716,19 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
@Override
public void destroyItem(final ViewGroup container, final int position,
final Object object) {
- final ScrollKeyboardView keyboardView = mActiveKeyboardView.get(position);
+ if (DEBUG_PAGER) {
+ Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName());
+ }
+ final ScrollKeyboardView keyboardView = mActiveKeyboardViews.get(position);
if (keyboardView != null) {
keyboardView.deallocateMemory();
- mActiveKeyboardView.remove(position);
+ mActiveKeyboardViews.remove(position);
+ }
+ if (object instanceof View) {
+ container.removeView((View)object);
+ } else {
+ Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object);
}
- container.removeView(keyboardView);
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index ad6e2c0f2..97609837e 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -68,7 +68,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
private InputView mCurrentInputView;
private View mMainKeyboardFrame;
private MainKeyboardView mKeyboardView;
- private EmojiKeyboardView mEmojiKeyboardView;
+ private EmojiPalettesView mEmojiPalettesView;
private LatinIME mLatinIME;
private Resources mResources;
@@ -169,7 +169,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
}
private void setKeyboard(final Keyboard keyboard) {
- // Make {@link MainKeyboardView} visible and hide {@link EmojiKeyboardView}.
+ // Make {@link MainKeyboardView} visible and hide {@link EmojiPalettesView}.
setMainKeyboardFrame();
final MainKeyboardView keyboardView = mKeyboardView;
final Keyboard oldKeyboard = keyboardView.getKeyboard();
@@ -259,14 +259,16 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
private void setMainKeyboardFrame() {
mMainKeyboardFrame.setVisibility(View.VISIBLE);
- mEmojiKeyboardView.setVisibility(View.GONE);
+ mEmojiPalettesView.setVisibility(View.GONE);
+ mEmojiPalettesView.stopEmojiPalettes();
}
// Implements {@link KeyboardState.SwitchActions}.
@Override
public void setEmojiKeyboard() {
mMainKeyboardFrame.setVisibility(View.GONE);
- mEmojiKeyboardView.setVisibility(View.VISIBLE);
+ mEmojiPalettesView.startEmojiPalettes();
+ mEmojiPalettesView.setVisibility(View.VISIBLE);
}
// Implements {@link KeyboardState.SwitchActions}.
@@ -315,7 +317,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
}
public boolean isShowingEmojiKeyboard() {
- return mEmojiKeyboardView != null && mEmojiKeyboardView.getVisibility() == View.VISIBLE;
+ return mEmojiPalettesView != null && mEmojiPalettesView.getVisibility() == View.VISIBLE;
}
public boolean isShowingMoreKeysPanel() {
@@ -327,7 +329,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
public View getVisibleKeyboardView() {
if (isShowingEmojiKeyboard()) {
- return mEmojiKeyboardView;
+ return mEmojiPalettesView;
}
return mKeyboardView;
}
@@ -336,6 +338,16 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
return mKeyboardView;
}
+ public void deallocateMemory() {
+ if (mKeyboardView != null) {
+ mKeyboardView.cancelAllOngoingEvents();
+ mKeyboardView.deallocateMemory();
+ }
+ if (mEmojiPalettesView != null) {
+ mEmojiPalettesView.stopEmojiPalettes();
+ }
+ }
+
public View onCreateInputView(final boolean isHardwareAcceleratedDrawingEnabled) {
if (mKeyboardView != null) {
mKeyboardView.closing();
@@ -345,15 +357,15 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
R.layout.input_view, null);
mMainKeyboardFrame = mCurrentInputView.findViewById(R.id.main_keyboard_frame);
- mEmojiKeyboardView = (EmojiKeyboardView)mCurrentInputView.findViewById(
+ mEmojiPalettesView = (EmojiPalettesView)mCurrentInputView.findViewById(
R.id.emoji_keyboard_view);
mKeyboardView = (MainKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
mKeyboardView.setHardwareAcceleratedDrawingEnabled(isHardwareAcceleratedDrawingEnabled);
mKeyboardView.setKeyboardActionListener(mLatinIME);
- mEmojiKeyboardView.setHardwareAcceleratedDrawingEnabled(
+ mEmojiPalettesView.setHardwareAcceleratedDrawingEnabled(
isHardwareAcceleratedDrawingEnabled);
- mEmojiKeyboardView.setKeyboardActionListener(mLatinIME);
+ mEmojiPalettesView.setKeyboardActionListener(mLatinIME);
// This always needs to be set since the accessibility state can
// potentially change without the input view being re-created.
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index aeb9e67b2..5578713a0 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -243,6 +243,8 @@ public class KeyboardView extends View {
}
private void freeOffscreenBuffer() {
+ mOffscreenCanvas.setBitmap(null);
+ mOffscreenCanvas.setMatrix(null);
if (mOffscreenBuffer != null) {
mOffscreenBuffer.recycle();
mOffscreenBuffer = null;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java b/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java
index 587f95a39..3133e54be 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java
@@ -20,7 +20,7 @@ import android.content.SharedPreferences;
import android.text.TextUtils;
import android.util.Log;
-import com.android.inputmethod.keyboard.EmojiKeyboardView;
+import com.android.inputmethod.keyboard.EmojiPalettesView;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.settings.Settings;
@@ -42,7 +42,6 @@ public class DynamicGridKeyboard extends Keyboard {
private final Object mLock = new Object();
private final SharedPreferences mPrefs;
- private final int mLeftPadding;
private final int mHorizontalStep;
private final int mVerticalStep;
private final int mColumnsNum;
@@ -58,12 +57,11 @@ public class DynamicGridKeyboard extends Keyboard {
super(templateKeyboard);
final Key key0 = getTemplateKey(TEMPLATE_KEY_CODE_0);
final Key key1 = getTemplateKey(TEMPLATE_KEY_CODE_1);
- mLeftPadding = key0.getX();
mHorizontalStep = Math.abs(key1.getX() - key0.getX());
mVerticalStep = key0.getHeight() + mVerticalGap;
mColumnsNum = mBaseWidth / mHorizontalStep;
mMaxKeyCount = maxKeyCount;
- mIsRecents = categoryId == EmojiKeyboardView.CATEGORY_ID_RECENTS;
+ mIsRecents = categoryId == EmojiPalettesView.CATEGORY_ID_RECENTS;
mPrefs = prefs;
}
@@ -122,9 +120,11 @@ public class DynamicGridKeyboard extends Keyboard {
}
int index = 0;
for (final GridKey gridKey : mGridKeys) {
- final int keyX = getKeyX(index);
- final int keyY = getKeyY(index);
- gridKey.updateCorrdinates(keyX, keyY);
+ final int keyX0 = getKeyX0(index);
+ final int keyY0 = getKeyY0(index);
+ final int keyX1 = getKeyX1(index);
+ final int keyY1 = getKeyY1(index);
+ gridKey.updateCorrdinates(keyX0, keyY0, keyX1, keyY1);
index++;
}
}
@@ -172,14 +172,24 @@ public class DynamicGridKeyboard extends Keyboard {
}
}
- private int getKeyX(final int index) {
+ private int getKeyX0(final int index) {
final int column = index % mColumnsNum;
- return column * mHorizontalStep + mLeftPadding;
+ return column * mHorizontalStep;
}
- private int getKeyY(final int index) {
+ private int getKeyX1(final int index) {
+ final int column = index % mColumnsNum + 1;
+ return column * mHorizontalStep;
+ }
+
+ private int getKeyY0(final int index) {
final int row = index / mColumnsNum;
- return row * mVerticalStep + mTopPadding;
+ return row * mVerticalStep + mVerticalGap / 2;
+ }
+
+ private int getKeyY1(final int index) {
+ final int row = index / mColumnsNum + 1;
+ return row * mVerticalStep + mVerticalGap / 2;
}
@Override
@@ -207,10 +217,10 @@ public class DynamicGridKeyboard extends Keyboard {
super(originalKey);
}
- public void updateCorrdinates(final int x, final int y) {
- mCurrentX = x;
- mCurrentY = y;
- getHitBox().set(x, y, x + getWidth(), y + getHeight());
+ public void updateCorrdinates(final int x0, final int y0, final int x1, final int y1) {
+ mCurrentX = x0;
+ mCurrentY = y0;
+ getHitBox().set(x0, y0, x1, y1);
}
@Override
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 506dfa751..9f9fdaa6f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -178,8 +178,6 @@ public final class KeyboardState {
if (!state.mIsAlphabetShiftLocked) {
setShifted(state.mShiftMode);
}
- // TODO: is this the right place to do this? Should we do this in setShift* instead?
- mSwitchActions.requestUpdatingShiftState();
} else {
mPrevMainKeyboardWasShiftLocked = state.mIsAlphabetShiftLocked;
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index 684cf632b..e769e3cdd 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -251,6 +251,7 @@ public final class KeyboardTextsSet {
/* 146 */ "more_keys_for_single_quote",
/* 147 */ "more_keys_for_double_quote",
/* 148 */ "more_keys_for_tablet_double_quote",
+ /* 149 */ "emoji_key_as_more_key",
};
private static final String EMPTY = "";
@@ -277,7 +278,7 @@ public final class KeyboardTextsSet {
/* 50 */ "\u00A2,\u00A3,\u20AC,\u00A5,\u20B1",
/* 51 */ "$",
/* 52 */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1",
- /* 53 */ "!fixedColumnOrder!3,!,\\,,?,:,;,@",
+ /* 53 */ "!fixedColumnOrder!4,#,!,\\,,?,-,:,',@",
// U+2020: "†" DAGGER
// U+2021: "‡" DOUBLE DAGGER
// U+2605: "★" BLACK STAR
@@ -439,6 +440,7 @@ public final class KeyboardTextsSet {
/* 146 */ "!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes",
/* 147 */ "!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes",
/* 148 */ "!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes",
+ /* 149 */ "!icon/emoji_key|!code/key_emoji",
};
/* Language af: Afrikaans */
@@ -2893,33 +2895,69 @@ public final class KeyboardTextsSet {
/* Language sv: Swedish */
private static final String[] LANGUAGE_sv = {
- /* 0 */ null,
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ /* 0 */ "\u00E1,\u00E0,\u00E2,\u0105,\u00E3",
// U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
// U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
// U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
// U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
// U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
/* 1 */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119",
- /* 2 */ null,
- // U+0153: "œ" LATIN SMALL LIGATURE OE
- // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
- // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ /* 2 */ "\u00ED,\u00EC,\u00EE,\u00EF",
// U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
// U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
// U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
- /* 3 */ "\u0153,\u00F4,\u00F2,\u00F3,\u00F5,\u014D",
+ /* 3 */ "\u00F3,\u00F2,\u00F4,\u00F5,\u014D",
// U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
- // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
- // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
// U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
// U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
- /* 4 */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
- // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ /* 4 */ "\u00FC,\u00FA,\u00F9,\u00FB,\u016B",
// U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
// U+0161: "š" LATIN SMALL LETTER S WITH CARON
- /* 5 */ "\u00DF,\u015B,\u0161",
- /* 6~ */
- null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ /* 5 */ "\u015B,\u0161,\u015F,\u00DF",
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+ /* 6 */ "\u0144,\u00F1,\u0148",
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ /* 7 */ "\u00E7,\u0107,\u010D",
+ // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+ // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ /* 8 */ "\u00FD,\u00FF,\u00FC",
+ // U+00F0: "ð" LATIN SMALL LETTER ETH
+ // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+ /* 9 */ "\u00F0,\u010F",
+ // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
+ /* 10 */ "\u0159",
+ // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
+ // U+00FE: "þ" LATIN SMALL LETTER THORN
+ /* 11 */ "\u0165,\u00FE",
+ // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+ /* 12 */ "\u017A,\u017E,\u017C",
+ /* 13 */ null,
+ // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+ /* 14 */ "\u0142",
+ /* 15~ */
+ null, null, null, null, null,
/* ~19 */
// U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
/* 20 */ "\u00E5",
@@ -2928,7 +2966,8 @@ public final class KeyboardTextsSet {
// U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
/* 22 */ "\u00E4",
// U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
- /* 23 */ "\u00F8",
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ /* 23 */ "\u00F8,\u0153",
// U+00E6: "æ" LATIN SMALL LETTER AE
/* 24 */ "\u00E6",
/* 25~ */
diff --git a/java/src/com/android/inputmethod/keyboard/internal/ScrollKeyboardView.java b/java/src/com/android/inputmethod/keyboard/internal/ScrollKeyboardView.java
index b8ee976e8..9cf68d43d 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/ScrollKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/ScrollKeyboardView.java
@@ -30,8 +30,9 @@ import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.latin.R;
/**
- * This is an extended {@link KeyboardView} class that hosts a scroll keyboard.
+ * This is an extended {@link KeyboardView} class that hosts a vertical scroll keyboard.
* Multi-touch unsupported. No {@link PointerTracker}s. No gesture support.
+ * TODO: Vertical scroll capability should be removed from this class because it's no longer used.
*/
// TODO: Implement key popup preview.
public final class ScrollKeyboardView extends KeyboardView implements
diff --git a/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java b/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java
index 4a0ce3735..463d09344 100644
--- a/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java
+++ b/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java
@@ -41,8 +41,17 @@ abstract public class AbstractDictionaryWriter extends Dictionary {
abstract public void clear();
+ /**
+ * Add a unigram with an optional shortcut to the dictionary.
+ * @param word The word to add.
+ * @param shortcutTarget A shortcut target for this word, or null if none.
+ * @param frequency The frequency for this unigram.
+ * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored
+ * if shortcutTarget is null.
+ * @param isNotAWord true if this is not a word, i.e. shortcut only.
+ */
abstract public void addUnigramWord(final String word, final String shortcutTarget,
- final int frequency, final boolean isNotAWord);
+ final int frequency, final int shortcutFreq, final boolean isNotAWord);
// TODO: Remove lastModifiedTime after making binary dictionary support forgetting curve.
abstract public void addBigramWords(final String word0, final String word1,
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 541e69788..fd296988e 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -52,6 +52,10 @@ public final class BinaryDictionary extends Dictionary {
public static final String UNIGRAM_COUNT_QUERY = "UNIGRAM_COUNT";
@UsedForTesting
public static final String BIGRAM_COUNT_QUERY = "BIGRAM_COUNT";
+ @UsedForTesting
+ public static final String MAX_UNIGRAM_COUNT_QUERY = "MAX_UNIGRAM_COUNT";
+ @UsedForTesting
+ public static final String MAX_BIGRAM_COUNT_QUERY = "MAX_BIGRAM_COUNT";
private long mNativeDict;
private final Locale mLocale;
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index ffeb92784..47891c6b7 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -127,7 +127,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
if (DEBUG) {
Log.d(TAG, "loadAccountVocabulary: " + word);
}
- super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS,
+ super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS, 0 /* shortcutFreq */,
false /* isNotAWord */);
}
}
@@ -213,7 +213,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
Log.d(TAG, "addName " + name + ", " + word + ", " + prevWord);
}
super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS,
- false /* isNotAWord */);
+ 0 /* shortcutFreq */, false /* isNotAWord */);
if (!TextUtils.isEmpty(prevWord)) {
if (mUseFirstLastBigrams) {
super.addBigram(prevWord, word, FREQUENCY_FOR_CONTACTS_BIGRAM,
diff --git a/java/src/com/android/inputmethod/latin/DictionaryWriter.java b/java/src/com/android/inputmethod/latin/DictionaryWriter.java
index 84abfa66d..3df2a2b63 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryWriter.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryWriter.java
@@ -62,13 +62,13 @@ public class DictionaryWriter extends AbstractDictionaryWriter {
// considering performance regression.
@Override
public void addUnigramWord(final String word, final String shortcutTarget, final int frequency,
- final boolean isNotAWord) {
+ final int shortcutFreq, final boolean isNotAWord) {
if (shortcutTarget == null) {
mFusionDictionary.add(word, frequency, null, isNotAWord);
} else {
// TODO: Do this in the subclass, with this class taking an arraylist.
final ArrayList<WeightedString> shortcutTargets = CollectionUtils.newArrayList();
- shortcutTargets.add(new WeightedString(shortcutTarget, frequency));
+ shortcutTargets.add(new WeightedString(shortcutTarget, shortcutFreq));
mFusionDictionary.add(word, frequency, shortcutTargets, isNotAWord);
}
}
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index c79a4ff90..eb8650e6f 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -261,10 +261,16 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
/**
* Adds a word unigram to the dictionary. Used for loading a dictionary.
+ * @param word The word to add.
+ * @param shortcutTarget A shortcut target for this word, or null if none.
+ * @param frequency The frequency for this unigram.
+ * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored
+ * if shortcutTarget is null.
+ * @param isNotAWord true if this is not a word, i.e. shortcut only.
*/
protected void addWord(final String word, final String shortcutTarget,
- final int frequency, final boolean isNotAWord) {
- mDictionaryWriter.addUnigramWord(word, shortcutTarget, frequency, isNotAWord);
+ final int frequency, final int shortcutFreq, final boolean isNotAWord) {
+ mDictionaryWriter.addUnigramWord(word, shortcutTarget, frequency, shortcutFreq, isNotAWord);
}
/**
@@ -313,7 +319,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
* Dynamically adds a word unigram to the dictionary. May overwrite an existing entry.
*/
protected void addWordDynamically(final String word, final String shortcutTarget,
- final int frequency, final boolean isNotAWord) {
+ final int frequency, final int shortcutFreq, final boolean isNotAWord) {
if (!mIsUpdatable) {
Log.w(TAG, "addWordDynamically is called for non-updatable dictionary: " + mFilename);
return;
@@ -326,7 +332,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
mBinaryDictionary.addUnigramWord(word, frequency);
} else {
// TODO: Remove.
- mDictionaryWriter.addUnigramWord(word, shortcutTarget, frequency, isNotAWord);
+ mDictionaryWriter.addUnigramWord(word, shortcutTarget, frequency, shortcutFreq,
+ isNotAWord);
}
}
});
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index d491f988a..95c9bcab9 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -156,15 +156,36 @@ public class ExpandableDictionary extends Dictionary {
return Constants.DICTIONARY_MAX_WORD_LENGTH;
}
- public void addWord(final String word, final String shortcutTarget, final int frequency) {
+ /**
+ * Add a word with an optional shortcut to the dictionary.
+ * @param word The word to add.
+ * @param shortcutTarget A shortcut target for this word, or null if none.
+ * @param frequency The frequency for this unigram.
+ * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored
+ * if shortcutTarget is null.
+ */
+ public void addWord(final String word, final String shortcutTarget, final int frequency,
+ final int shortcutFreq) {
if (word.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH) {
return;
}
- addWordRec(mRoots, word, 0, shortcutTarget, frequency, null);
+ addWordRec(mRoots, word, 0, shortcutTarget, frequency, shortcutFreq, null);
}
+ /**
+ * Add a word, recursively searching for its correct place in the trie tree.
+ * @param children The node to recursively search for addition. Initially, the root of the tree.
+ * @param word The word to add.
+ * @param depth The current depth in the tree.
+ * @param shortcutTarget A shortcut target for this word, or null if none.
+ * @param frequency The frequency for this unigram.
+ * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored
+ * if shortcutTarget is null.
+ * @param parentNode The parent node, for up linking. Initially null, as the root has no parent.
+ */
private void addWordRec(final NodeArray children, final String word, final int depth,
- final String shortcutTarget, final int frequency, final Node parentNode) {
+ final String shortcutTarget, final int frequency, final int shortcutFreq,
+ final Node parentNode) {
final int wordLength = word.length();
if (wordLength <= depth) return;
final char c = word.charAt(depth);
@@ -204,7 +225,8 @@ public class ExpandableDictionary extends Dictionary {
if (childNode.mChildren == null) {
childNode.mChildren = new NodeArray();
}
- addWordRec(childNode.mChildren, word, depth + 1, shortcutTarget, frequency, childNode);
+ addWordRec(childNode.mChildren, word, depth + 1, shortcutTarget, frequency, shortcutFreq,
+ childNode);
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d51c63dd3..b668a7770 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -808,6 +808,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@SuppressWarnings("deprecation")
private void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
super.onStartInputView(editorInfo, restarting);
+ mRichImm.clearSubtypeCaches();
final KeyboardSwitcher switcher = mKeyboardSwitcher;
final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();
// If we are starting input in a different text field from before, we'll have to reload
@@ -903,12 +904,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Sometimes, while rotating, for some reason the framework tells the app we are not
// connected to it and that means we can't refresh the cache. In this case, schedule a
// refresh later.
+ final boolean canReachInputConnection;
if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(editorInfo.initialSelStart,
false /* shouldFinishComposition */)) {
// We try resetting the caches up to 5 times before giving up.
mHandler.postResetCaches(isDifferentTextField, 5 /* remainingTries */);
+ canReachInputConnection = false;
} else {
- if (isDifferentTextField) mHandler.postResumeSuggestions();
+ if (isDifferentTextField) {
+ mHandler.postResumeSuggestions();
+ }
+ canReachInputConnection = true;
}
if (isDifferentTextField) {
@@ -921,6 +927,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
switcher.loadKeyboard(editorInfo, currentSettingsValues);
+ if (!canReachInputConnection) {
+ // If we can't reach the input connection, we will call loadKeyboard again later,
+ // so we need to save its state now. The call will be done in #retryResetCaches.
+ switcher.saveKeyboardState();
+ }
} else if (restarting) {
// TODO: Come up with a more comprehensive way to reset the keyboard layout when
// a keyboard layout set doesn't get reloaded in this method.
@@ -1039,17 +1050,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void onFinishInputViewInternal(final boolean finishingInput) {
super.onFinishInputView(finishingInput);
mKeyboardSwitcher.onFinishInputView();
- final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
- if (mainKeyboardView != null) {
- mainKeyboardView.cancelAllOngoingEvents();
- mainKeyboardView.deallocateMemory();
- }
+ mKeyboardSwitcher.deallocateMemory();
// Remove pending messages related to update suggestions
mHandler.cancelUpdateSuggestionStrip();
// Should do the following in onFinishInputInternal but until JB MR2 it's not called :(
if (mWordComposer.isComposingWord()) mConnection.finishComposingText();
resetComposingState(true /* alsoResetLastComposedWord */);
- mRichImm.clearSubtypeCaches();
// Notify ResearchLogger
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_onFinishInputViewInternal(finishingInput, mLastSelectionStart,
@@ -1402,14 +1408,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Called from the KeyboardSwitcher which needs to know auto caps state to display
// the right layout.
public int getCurrentAutoCapsState() {
- if (!mSettings.getCurrent().mAutoCap) return Constants.TextUtils.CAP_MODE_OFF;
+ final SettingsValues currentSettingsValues = mSettings.getCurrent();
+ if (!currentSettingsValues.mAutoCap) return Constants.TextUtils.CAP_MODE_OFF;
final EditorInfo ei = getCurrentInputEditorInfo();
if (ei == null) return Constants.TextUtils.CAP_MODE_OFF;
final int inputType = ei.inputType;
// Warning: this depends on mSpaceState, which may not be the most current value. If
// mSpaceState gets updated later, whoever called this may need to be told about it.
- return mConnection.getCursorCapsMode(inputType, mSubtypeSwitcher.getCurrentSubtypeLocale(),
+ return mConnection.getCursorCapsMode(inputType, currentSettingsValues,
SPACE_STATE_PHANTOM == mSpaceState);
}
@@ -1450,9 +1457,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private boolean maybeDoubleSpacePeriod() {
- final SettingsValues settingsValues = mSettings.getCurrent();
- if (!settingsValues.mCorrectionEnabled) return false;
- if (!settingsValues.mUseDoubleSpacePeriod) return false;
+ final SettingsValues currentSettingsValues = mSettings.getCurrent();
+ if (!currentSettingsValues.mCorrectionEnabled) return false;
+ if (!currentSettingsValues.mUseDoubleSpacePeriod) return false;
if (!mHandler.isAcceptingDoubleSpacePeriod()) return false;
// We only do this when we see two spaces and an accepted code point before the cursor.
// The code point may be a surrogate pair but the two spaces may not, so we need 4 chars.
@@ -1471,7 +1478,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (canBeFollowedByDoubleSpacePeriod(firstCodePoint)) {
mHandler.cancelDoubleSpacePeriodTimer();
mConnection.deleteSurroundingText(2, 0);
- final String textToInsert = ". ";
+ final String textToInsert = new String(
+ new int[] { currentSettingsValues.mSentenceSeparator, Constants.CODE_SPACE },
+ 0, 2);
mConnection.commitText(textToInsert, 1);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_maybeDoubleSpacePeriod(textToInsert,
@@ -2296,9 +2305,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (!mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) {
mLastSelectionStart = mRecapitalizeStatus.getNewCursorStart();
mLastSelectionEnd = mRecapitalizeStatus.getNewCursorEnd();
- mConnection.setSelection(mLastSelectionStart, mLastSelectionEnd);
}
}
+ mConnection.finishComposingText();
mRecapitalizeStatus.rotate();
final int numCharsDeleted = mLastSelectionEnd - mLastSelectionStart;
mConnection.setSelection(mLastSelectionEnd, mLastSelectionEnd);
@@ -2955,11 +2964,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(mLastSelectionStart, false)) {
if (0 < remainingTries) {
mHandler.postResetCaches(tryResumeSuggestions, remainingTries - 1);
+ return;
}
- return;
+ // If remainingTries is 0, we should stop waiting for new tries, but it's still
+ // better to load the keyboard (less things will be broken).
}
tryFixLyingCursorPosition();
- mKeyboardSwitcher.updateShiftState();
+ mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettings.getCurrent());
if (tryResumeSuggestions) mHandler.postResumeSuggestions();
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 8580a6e54..e43cab5ca 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -245,11 +245,11 @@ public final class RichInputConnection {
* American English, it's just the most common set of rules for English).
*
* @param inputType a mask of the caps modes to test for.
- * @param locale what language should be considered.
+ * @param settingsValues the values of the settings to use for locale and separators.
* @param hasSpaceBefore if we should consider there should be a space after the string.
* @return the caps modes that should be on as a set of bits
*/
- public int getCursorCapsMode(final int inputType, final Locale locale,
+ public int getCursorCapsMode(final int inputType, final SettingsValues settingsValues,
final boolean hasSpaceBefore) {
mIC = mParent.getCurrentInputConnection();
if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF;
@@ -277,8 +277,8 @@ public final class RichInputConnection {
}
// This never calls InputConnection#getCapsMode - in fact, it's a static method that
// never blocks or initiates IPC.
- return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, locale,
- hasSpaceBefore);
+ return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType,
+ settingsValues, hasSpaceBefore);
}
public int getCodePointBeforeCursor() {
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 9fd1f53a2..c270d47d0 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -286,14 +286,16 @@ public final class Suggest {
// the word *would* have been auto-corrected.
if (!isCorrectionEnabled || !allowsToBeAutoCorrected || !wordComposer.isComposingWord()
|| suggestionsSet.isEmpty() || wordComposer.hasDigits()
- || wordComposer.isMostlyCaps() || wordComposer.isResumed()
- || !hasMainDictionary()) {
+ || wordComposer.isMostlyCaps() || wordComposer.isResumed() || !hasMainDictionary()
+ || SuggestedWordInfo.KIND_SHORTCUT == suggestionsSet.first().mKind) {
// If we don't have a main dictionary, we never want to auto-correct. The reason for
// this is, the user may have a contact whose name happens to match a valid word in
// their language, and it will unexpectedly auto-correct. For example, if the user
// types in English with no dictionary and has a "Will" in their contact list, "will"
// would always auto-correct to "Will" which is unwanted. Hence, no main dict => no
// auto-correct.
+ // Also, shortcuts should never auto-correct unless they are whitelist entries.
+ // TODO: we may want to have shortcut-only entries auto-correct in the future.
hasAutoCorrection = false;
} else {
hasAutoCorrection = AutoCorrectionUtils.suggestionExceedsAutoCorrectionThreshold(
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 864a17375..15b3d8d02 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -47,6 +47,9 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
private static final String USER_DICTIONARY_ALL_LANGUAGES = "";
private static final int HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY = 250;
private static final int LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY = 160;
+ // Shortcut frequency is 0~15, with 15 = whitelist. We don't want user dictionary entries
+ // to auto-correct, so we set this to the highest frequency that won't, i.e. 14.
+ private static final int USER_DICT_SHORTCUT_FREQUENCY = 14;
// TODO: use Words.SHORTCUT when we target JellyBean or above
final static String SHORTCUT = "shortcut";
@@ -243,10 +246,12 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
final int adjustedFrequency = scaleFrequencyFromDefaultToLatinIme(frequency);
// Safeguard against adding really long words.
if (word.length() < MAX_WORD_LENGTH) {
- super.addWord(word, null, adjustedFrequency, false /* isNotAWord */);
+ super.addWord(word, null, adjustedFrequency, 0 /* shortcutFreq */,
+ false /* isNotAWord */);
}
if (null != shortcut && shortcut.length() < MAX_WORD_LENGTH) {
- super.addWord(shortcut, word, adjustedFrequency, true /* isNotAWord */);
+ super.addWord(shortcut, word, adjustedFrequency, USER_DICT_SHORTCUT_FREQUENCY,
+ true /* isNotAWord */);
}
cursor.moveToNext();
}
diff --git a/java/src/com/android/inputmethod/latin/about/AboutPreferences.java b/java/src/com/android/inputmethod/latin/about/AboutPreferences.java
new file mode 100644
index 000000000..f60b189f1
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/about/AboutPreferences.java
@@ -0,0 +1,28 @@
+/*
+ * 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.about;
+
+import android.app.Fragment;
+
+/**
+ * Dummy class of AboutPreferences. Never use this.
+ */
+public final class AboutPreferences extends Fragment {
+ private AboutPreferences() {
+ // Prevents this from being instantiated
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index be653feec..3bb218bea 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -367,10 +367,11 @@ public final class FusionDictionary implements Iterable<Word> {
* Helper method to convert a String to an int array.
*/
static int[] getCodePoints(final String word) {
- // TODO: this is a copy-paste of the contents of StringUtils.toCodePointArray,
+ // TODO: this is a copy-paste of the old contents of StringUtils.toCodePointArray,
// which is not visible from the makedict package. Factor this code.
+ final int length = word.length();
+ if (length <= 0) return new int[] {};
final char[] characters = word.toCharArray();
- final int length = characters.length;
final int[] codePoints = new int[Character.codePointCount(characters, 0, length)];
int codePoint = Character.codePointAt(characters, 0);
int dsti = 0;
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index c8b62b6c8..a1e36006b 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -138,7 +138,7 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
final int frequency = ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE ?
(isValid ? FREQUENCY_FOR_WORDS_IN_DICTS : FREQUENCY_FOR_WORDS_NOT_IN_DICTS) :
FREQUENCY_FOR_TYPED;
- addWordDynamically(word1, null /* the "shortcut" parameter is null */, frequency,
+ addWordDynamically(word1, null /* shortcutTarget */, frequency, 0 /* shortcutFreq */,
false /* isNotAWord */);
// Do not insert a word as a bigram of itself
if (word1.equals(word0)) {
@@ -171,11 +171,11 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
final OnAddWordListener listener = new OnAddWordListener() {
@Override
public void setUnigram(final String word, final String shortcutTarget,
- final int frequency) {
+ final int frequency, final int shortcutFreq) {
if (DBG_SAVE_RESTORE) {
Log.d(TAG, "load unigram: " + word + "," + frequency);
}
- addWord(word, shortcutTarget, frequency, false /* isNotAWord */);
+ addWord(word, shortcutTarget, frequency, shortcutFreq, false /* isNotAWord */);
++profTotalCount[0];
}
diff --git a/java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java b/java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java
index 039b25337..6f152bb91 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java
@@ -75,15 +75,21 @@ public class DynamicPersonalizationDictionaryWriter extends AbstractDictionaryWr
/**
* Adds a word unigram to the fusion dictionary. Call updateBinaryDictionary when all changes
* are done to update the binary dictionary.
+ * @param word The word to add.
+ * @param shortcutTarget A shortcut target for this word, or null if none.
+ * @param frequency The frequency for this unigram.
+ * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored
+ * if shortcutTarget is null.
+ * @param isNotAWord true if this is not a word, i.e. shortcut only.
*/
@Override
public void addUnigramWord(final String word, final String shortcutTarget, final int frequency,
- final boolean isNotAWord) {
+ final int shortcutFreq, final boolean isNotAWord) {
if (mBigramList.size() > mMaxHistoryBigrams * 2) {
// Too many entries: just stop adding new vocabulary and wait next refresh.
return;
}
- mExpandableDictionary.addWord(word, shortcutTarget, frequency);
+ mExpandableDictionary.addWord(word, shortcutTarget, frequency, shortcutFreq);
mBigramList.addBigram(null, word, (byte)frequency);
}
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettingsActivity.java b/java/src/com/android/inputmethod/latin/settings/DebugSettingsActivity.java
index ef6ab2a38..a23e37795 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettingsActivity.java
@@ -21,6 +21,7 @@ import android.os.Bundle;
import android.preference.PreferenceActivity;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.utils.FragmentUtils;
public final class DebugSettingsActivity extends PreferenceActivity {
private static final String DEFAULT_FRAGMENT = DebugSettings.class.getName();
@@ -42,6 +43,6 @@ public final class DebugSettingsActivity extends PreferenceActivity {
// TODO: Uncomment the override annotation once we start using SDK version 19.
// @Override
public boolean isValidFragment(String fragmentName) {
- return fragmentName.equals(DEFAULT_FRAGMENT);
+ return FragmentUtils.isValidFragment(fragmentName);
}
}
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
index ad68f8c37..c899507e3 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.latin.settings;
+import com.android.inputmethod.latin.utils.FragmentUtils;
+
import android.content.Intent;
import android.preference.PreferenceActivity;
@@ -36,6 +38,6 @@ public final class SettingsActivity extends PreferenceActivity {
// TODO: Uncomment the override annotation once we start using SDK version 19.
// @Override
public boolean isValidFragment(String fragmentName) {
- return fragmentName.equals(DEFAULT_FRAGMENT);
+ return FragmentUtils.isValidFragment(fragmentName);
}
}
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 2abcdc7fa..f331c78e5 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -24,6 +24,7 @@ import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.internal.KeySpecParser;
+import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.InputAttributes;
import com.android.inputmethod.latin.R;
@@ -57,6 +58,7 @@ public final class SettingsValues {
public final int[] mWordConnectors;
public final SuggestedWords mSuggestPuncList;
public final String mWordSeparators;
+ public final int mSentenceSeparator;
public final CharSequence mHintToSaveText;
public final boolean mCurrentLanguageHasSpaces;
@@ -120,6 +122,7 @@ public final class SettingsValues {
R.string.suggested_punctuations));
mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
mWordSeparators = res.getString(R.string.symbols_word_separators);
+ mSentenceSeparator = res.getInteger(R.integer.sentence_separator);
mHintToSaveText = res.getText(R.string.hint_add_to_dictionary);
mCurrentLanguageHasSpaces = res.getBoolean(R.bool.current_language_has_spaces);
@@ -187,6 +190,7 @@ public final class SettingsValues {
Arrays.sort(mSymbolsFollowedBySpace);
mWordConnectors = new int[] { '\'', '-' };
Arrays.sort(mWordConnectors);
+ mSentenceSeparator = Constants.CODE_PERIOD;
final String[] suggestPuncsSpec = new String[] { "!", "?", ",", ":", ";" };
mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
mWordSeparators = "&\t \n()[]{}*&<>+=|.,;:!?/_\"";
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index eb6d7c106..503b18b1b 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -204,10 +204,20 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
return AndroidSpellCheckerSessionFactory.newInstance(this);
}
- public static SuggestionsInfo getNotInDictEmptySuggestions() {
- return new SuggestionsInfo(0, EMPTY_STRING_ARRAY);
+ /**
+ * Returns an empty SuggestionsInfo with flags signaling the word is not in the dictionary.
+ * @param reportAsTypo whether this should include the flag LOOKS_LIKE_TYPO, for red underline.
+ * @return the empty SuggestionsInfo with the appropriate flags set.
+ */
+ public static SuggestionsInfo getNotInDictEmptySuggestions(final boolean reportAsTypo) {
+ return new SuggestionsInfo(reportAsTypo ? SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO : 0,
+ EMPTY_STRING_ARRAY);
}
+ /**
+ * Returns an empty suggestionInfo with flags signaling the word is in the dictionary.
+ * @return the empty SuggestionsInfo with the appropriate flags set.
+ */
public static SuggestionsInfo getInDictEmptySuggestions() {
return new SuggestionsInfo(SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY,
EMPTY_STRING_ARRAY);
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index 69f9a467f..d6e5b75ad 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -161,6 +161,12 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
}
}
+ private static final int CHECKABILITY_CHECKABLE = 0;
+ private static final int CHECKABILITY_TOO_MANY_NON_LETTERS = 1;
+ private static final int CHECKABILITY_CONTAINS_PERIOD = 2;
+ private static final int CHECKABILITY_EMAIL_OR_URL = 3;
+ private static final int CHECKABILITY_FIRST_LETTER_UNCHECKABLE = 4;
+ private static final int CHECKABILITY_TOO_SHORT = 5;
/**
* Finds out whether a particular string should be filtered out of spell checking.
*
@@ -171,10 +177,10 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
*
* @param text the string to evaluate.
* @param script the identifier for the script this spell checker recognizes
- * @return true if we should filter this text out, false otherwise
+ * @return one of the FILTER_OUT_* constants above.
*/
- private static boolean shouldFilterOut(final String text, final int script) {
- if (TextUtils.isEmpty(text) || text.length() <= 1) return true;
+ private static int getCheckabilityInScript(final String text, final int script) {
+ if (TextUtils.isEmpty(text) || text.length() <= 1) return CHECKABILITY_TOO_SHORT;
// TODO: check if an equivalent processing can't be done more quickly with a
// compiled regexp.
@@ -182,7 +188,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
final int firstCodePoint = text.codePointAt(0);
// Filter out words that don't start with a letter or an apostrophe
if (!isLetterCheckableByLanguage(firstCodePoint, script)
- && '\'' != firstCodePoint) return true;
+ && '\'' != firstCodePoint) return CHECKABILITY_FIRST_LETTER_UNCHECKABLE;
// Filter contents
final int length = text.length();
@@ -193,13 +199,21 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
// Any word containing a SLASH is probably either an ad-hoc combination of two
// words or a URI - in either case we don't want to spell check that
if (Constants.CODE_COMMERCIAL_AT == codePoint || Constants.CODE_SLASH == codePoint) {
- return true;
+ return CHECKABILITY_EMAIL_OR_URL;
+ }
+ // If the string contains a period, native returns strange suggestions (it seems
+ // to return suggestions for everything up to the period only and to ignore the
+ // rest), so we suppress lookup if there is a period.
+ // TODO: investigate why native returns these suggestions and remove this code.
+ if (Constants.CODE_PERIOD == codePoint) {
+ return CHECKABILITY_CONTAINS_PERIOD;
}
if (isLetterCheckableByLanguage(codePoint, script)) ++letterCount;
}
// Guestimate heuristic: perform spell checking if at least 3/4 of the characters
// in this word are letters
- return (letterCount * 4 < length * 3);
+ return (letterCount * 4 < length * 3)
+ ? CHECKABILITY_TOO_MANY_NON_LETTERS : CHECKABILITY_CHECKABLE;
}
/**
@@ -256,16 +270,20 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
cachedSuggestionsParams.mFlags, cachedSuggestionsParams.mSuggestions);
}
- if (shouldFilterOut(inText, mScript)) {
+ final int checkability = getCheckabilityInScript(inText, mScript);
+ if (CHECKABILITY_CHECKABLE != checkability) {
DictAndKeyboard dictInfo = null;
try {
dictInfo = mDictionaryPool.pollWithDefaultTimeout();
if (!DictionaryPool.isAValidDictionary(dictInfo)) {
- return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
+ return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
+ false /* reportAsTypo */);
}
return dictInfo.mDictionary.isValidWord(inText)
? AndroidSpellCheckerService.getInDictEmptySuggestions()
- : AndroidSpellCheckerService.getNotInDictEmptySuggestions();
+ : AndroidSpellCheckerService.getNotInDictEmptySuggestions(
+ CHECKABILITY_CONTAINS_PERIOD == checkability
+ /* reportAsTypo */);
} finally {
if (null != dictInfo) {
if (!mDictionaryPool.offer(dictInfo)) {
@@ -290,7 +308,8 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
try {
dictInfo = mDictionaryPool.pollWithDefaultTimeout();
if (!DictionaryPool.isAValidDictionary(dictInfo)) {
- return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
+ return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
+ false /* reportAsTypo */);
}
final WordComposer composer = new WordComposer();
final int length = text.length();
@@ -351,7 +370,8 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
throw e;
} else {
Log.e(TAG, "Exception while spellcheking", e);
- return AndroidSpellCheckerService.getNotInDictEmptySuggestions();
+ return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
+ false /* reportAsTypo */);
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
index aba563746..df9a76119 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.latin.spellcheck;
+import com.android.inputmethod.latin.utils.FragmentUtils;
+
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceActivity;
@@ -42,6 +44,6 @@ public final class SpellCheckerSettingsActivity extends PreferenceActivity {
// TODO: Uncomment the override annotation once we start using SDK version 19.
// @Override
public boolean isValidFragment(String fragmentName) {
- return fragmentName.equals(DEFAULT_FRAGMENT);
+ return FragmentUtils.isValidFragment(fragmentName);
}
}
diff --git a/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java b/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java
index ff332cdee..d87f6f3c4 100644
--- a/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java
@@ -25,6 +25,7 @@ import android.os.Build;
import android.text.TextUtils;
import android.view.inputmethod.InputMethodSubtype;
+import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.R;
@@ -143,12 +144,17 @@ public final class AdditionalSubtypeUtils {
// from the current users. So, you should be really careful to change it.
final int subtypeId = getInputMethodSubtypeId(nameId, localeString, layoutExtraValue,
additionalSubtypeExtraValue);
- // TODO: Use InputMethodSubtypeBuilder once we use SDK version 19.
- return new InputMethodSubtype(nameId, R.drawable.ic_ime_switcher_dark,
- localeString, KEYBOARD_MODE, layoutExtraValue + "," + additionalSubtypeExtraValue
- + "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
- + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE, false, false,
- subtypeId);
+ final String extraValue;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ extraValue = layoutExtraValue + "," + additionalSubtypeExtraValue
+ + "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
+ + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
+ } else {
+ extraValue = layoutExtraValue + "," + additionalSubtypeExtraValue;
+ }
+ return InputMethodSubtypeCompatUtils.newInputMethodSubtype(nameId,
+ R.drawable.ic_ime_switcher_dark, localeString, KEYBOARD_MODE, extraValue,
+ false, false, subtypeId);
}
private static int getInputMethodSubtypeId(int nameId, String localeString,
diff --git a/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java b/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
index 60b24d5d5..3d4404a98 100644
--- a/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
@@ -21,6 +21,7 @@ import android.text.TextUtils;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.WordComposer;
+import com.android.inputmethod.latin.settings.SettingsValues;
import java.util.Locale;
@@ -60,11 +61,6 @@ public final class CapsModeUtils {
|| WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED == mode;
}
- private static boolean isPeriod(final int codePoint) {
- // TODO: make this a resource.
- return codePoint == Constants.CODE_PERIOD || codePoint == Constants.CODE_ARMENIAN_PERIOD;
- }
-
/**
* Determine what caps mode should be in effect at the current offset in
* the text. Only the mode bits set in <var>reqModes</var> will be
@@ -78,7 +74,7 @@ public final class CapsModeUtils {
* @param reqModes The modes to be checked: may be any combination of
* {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and
* {@link TextUtils#CAP_MODE_SENTENCES}.
- * @param locale The locale to consider for capitalization rules
+ * @param settingsValues The current settings values.
* @param hasSpaceBefore Whether we should consider there is a space inserted at the end of cs
*
* @return Returns the actual capitalization modes that can be in effect
@@ -86,8 +82,8 @@ public final class CapsModeUtils {
* {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and
* {@link TextUtils#CAP_MODE_SENTENCES}.
*/
- public static int getCapsMode(final CharSequence cs, final int reqModes, final Locale locale,
- final boolean hasSpaceBefore) {
+ public static int getCapsMode(final CharSequence cs, final int reqModes,
+ final SettingsValues settingsValues, final boolean hasSpaceBefore) {
// Quick description of what we want to do:
// CAP_MODE_CHARACTERS is always on.
// CAP_MODE_WORDS is on if there is some whitespace before the cursor.
@@ -172,7 +168,7 @@ public final class CapsModeUtils {
// mark as the exact thing quoted and handling the surrounding punctuation independently,
// e.g. <<Did he say, "let's go home"?>>
// Hence, specifically for English, we treat this special case here.
- if (Locale.ENGLISH.getLanguage().equals(locale.getLanguage())) {
+ if (Locale.ENGLISH.getLanguage().equals(settingsValues.mLocale.getLanguage())) {
for (; j > 0; j--) {
// Here we look to go over any closing punctuation. This is because in dominant
// variants of English, the final period is placed within double quotes and maybe
@@ -195,7 +191,7 @@ public final class CapsModeUtils {
if (c == Constants.CODE_QUESTION_MARK || c == Constants.CODE_EXCLAMATION_MARK) {
return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_SENTENCES) & reqModes;
}
- if (!isPeriod(c) || j <= 0) {
+ if (settingsValues.mSentenceSeparator != c || j <= 0) {
return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
}
@@ -245,7 +241,7 @@ public final class CapsModeUtils {
case WORD:
if (Character.isLetter(c)) {
state = WORD;
- } else if (isPeriod(c)) {
+ } else if (settingsValues.mSentenceSeparator == c) {
state = PERIOD;
} else {
return caps;
@@ -261,7 +257,7 @@ public final class CapsModeUtils {
case LETTER:
if (Character.isLetter(c)) {
state = LETTER;
- } else if (isPeriod(c)) {
+ } else if (settingsValues.mSentenceSeparator == c) {
state = PERIOD;
} else {
return noCaps;
diff --git a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
new file mode 100644
index 000000000..ee2b97b2a
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
@@ -0,0 +1,52 @@
+/*
+ * 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.utils;
+
+import com.android.inputmethod.dictionarypack.DictionarySettingsFragment;
+import com.android.inputmethod.latin.about.AboutPreferences;
+import com.android.inputmethod.latin.settings.AdditionalSubtypeSettings;
+import com.android.inputmethod.latin.settings.DebugSettings;
+import com.android.inputmethod.latin.settings.SettingsFragment;
+import com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment;
+import com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordFragment;
+import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
+import com.android.inputmethod.latin.userdictionary.UserDictionaryLocalePicker;
+import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
+import com.android.inputmethod.research.FeedbackFragment;
+
+import java.util.HashSet;
+
+public class FragmentUtils {
+ private static final HashSet<String> sLatinImeFragments = new HashSet<String>();
+ static {
+ sLatinImeFragments.add(DictionarySettingsFragment.class.getName());
+ sLatinImeFragments.add(AboutPreferences.class.getName());
+ sLatinImeFragments.add(AdditionalSubtypeSettings.class.getName());
+ sLatinImeFragments.add(DebugSettings.class.getName());
+ sLatinImeFragments.add(SettingsFragment.class.getName());
+ sLatinImeFragments.add(SpellCheckerSettingsFragment.class.getName());
+ sLatinImeFragments.add(UserDictionaryAddWordFragment.class.getName());
+ sLatinImeFragments.add(UserDictionaryList.class.getName());
+ sLatinImeFragments.add(UserDictionaryLocalePicker.class.getName());
+ sLatinImeFragments.add(UserDictionarySettings.class.getName());
+ sLatinImeFragments.add(FeedbackFragment.class.getName());
+ }
+
+ public static boolean isValidFragment(String fragmentName) {
+ return sLatinImeFragments.contains(fragmentName);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
index ea32a74ff..635afe7cc 100644
--- a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
@@ -49,7 +49,16 @@ public final class UserHistoryDictIOUtils {
private static final String LAST_UPDATED_TIME_KEY = "date";
public interface OnAddWordListener {
- public void setUnigram(final String word, final String shortcutTarget, final int frequency);
+ /**
+ * Callback to be notified when a word is added to the dictionary.
+ * @param word The added word.
+ * @param shortcutTarget A shortcut target for this word, or null if none.
+ * @param frequency The frequency for this word.
+ * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist).
+ * Unspecified if shortcutTarget is null - do not rely on its value.
+ */
+ public void setUnigram(final String word, final String shortcutTarget, final int frequency,
+ final int shortcutFreq);
public void setBigram(final String word1, final String word2, final int frequency);
}
@@ -153,7 +162,7 @@ public final class UserHistoryDictIOUtils {
for (Entry<Integer, String> entry : unigrams.entrySet()) {
final String word1 = entry.getValue();
final int unigramFrequency = frequencies.get(entry.getKey());
- to.setUnigram(word1, null, unigramFrequency);
+ to.setUnigram(word1, null /* shortcutTarget */, unigramFrequency, 0 /* shortcutFreq */);
final ArrayList<PendingAttribute> attrList = bigrams.get(entry.getKey());
if (attrList != null) {
for (final PendingAttribute attr : attrList) {