aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/compat/TextViewCompatUtils.java18
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/ActionBatch.java8
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java16
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/DictionaryService.java5
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/LogProblemReporter.java3
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java5
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/PrivateLog.java23
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java15
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/WordListPreference.java33
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java40
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java2
-rw-r--r--java/src/com/android/inputmethod/latin/setup/SetupActivity.java157
-rw-r--r--java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java108
13 files changed, 324 insertions, 109 deletions
diff --git a/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java b/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java
index d4f1ea830..f8e1902c0 100644
--- a/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java
@@ -22,23 +22,23 @@ import android.widget.TextView;
import java.lang.reflect.Method;
public final class TextViewCompatUtils {
- // Note that TextView.setCompoundDrawablesRelative(Drawable,Drawable,Drawable,Drawable) has
- // been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
- private static final Method METHOD_setCompoundDrawablesRelative = CompatUtils.getMethod(
- TextView.class, "setCompoundDrawablesRelative",
+ // Note that TextView.setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable,Drawable,
+ // Drawable,Drawable) has been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
+ private static final Method METHOD_setCompoundDrawablesRelativeWithIntrinsicBounds =
+ CompatUtils.getMethod(TextView.class, "setCompoundDrawablesRelativeWithIntrinsicBounds",
Drawable.class, Drawable.class, Drawable.class, Drawable.class);
private TextViewCompatUtils() {
// This utility class is not publicly instantiable.
}
- public static void setCompoundDrawablesRelative(final TextView textView, final Drawable start,
- final Drawable top, final Drawable end, final Drawable bottom) {
- if (METHOD_setCompoundDrawablesRelative == null) {
- textView.setCompoundDrawables(start, top, end, bottom);
+ public static void setCompoundDrawablesRelativeWithIntrinsicBounds(final TextView textView,
+ final Drawable start, final Drawable top, final Drawable end, final Drawable bottom) {
+ if (METHOD_setCompoundDrawablesRelativeWithIntrinsicBounds == null) {
+ textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
return;
}
- CompatUtils.invoke(textView, null, METHOD_setCompoundDrawablesRelative,
+ CompatUtils.invoke(textView, null, METHOD_setCompoundDrawablesRelativeWithIntrinsicBounds,
start, top, end, bottom);
}
}
diff --git a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
index df4a52f4e..faf5d3c87 100644
--- a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
+++ b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
@@ -174,7 +174,7 @@ public final class ActionBatch {
final long downloadId = UpdateHandler.registerDownloadRequest(manager, request, db,
mWordList.mId, mWordList.mVersion);
Utils.l("Starting download of", uri, "with id", downloadId);
- PrivateLog.log("Starting download of " + uri + ", id : " + downloadId, context);
+ PrivateLog.log("Starting download of " + uri + ", id : " + downloadId);
}
}
@@ -333,7 +333,7 @@ public final class ActionBatch {
mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mChecksum,
mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion);
PrivateLog.log("Insert 'available' record for " + mWordList.mDescription
- + " and locale " + mWordList.mLocale, context);
+ + " and locale " + mWordList.mLocale);
db.insert(MetadataDbHelper.METADATA_TABLE_NAME, null, values);
}
}
@@ -383,7 +383,7 @@ public final class ActionBatch {
mWordList.mChecksum, mWordList.mFileSize, mWordList.mVersion,
mWordList.mFormatVersion);
PrivateLog.log("Insert 'preinstalled' record for " + mWordList.mDescription
- + " and locale " + mWordList.mLocale, context);
+ + " and locale " + mWordList.mLocale);
db.insert(MetadataDbHelper.METADATA_TABLE_NAME, null, values);
}
}
@@ -424,7 +424,7 @@ public final class ActionBatch {
mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mChecksum,
mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion);
PrivateLog.log("Updating record for " + mWordList.mDescription
- + " and locale " + mWordList.mLocale, context);
+ + " and locale " + mWordList.mLocale);
db.update(MetadataDbHelper.METADATA_TABLE_NAME, values,
MetadataDbHelper.WORDLISTID_COLUMN + " = ? AND "
+ MetadataDbHelper.VERSION_COLUMN + " = ?",
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
index f8d1c4fc9..4fbe16233 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
@@ -189,7 +189,7 @@ public final class DictionaryProvider extends ContentProvider {
*/
@Override
public String getType(final Uri uri) {
- PrivateLog.log("Asked for type of : " + uri, this);
+ PrivateLog.log("Asked for type of : " + uri);
final int match = matchUri(uri);
switch (match) {
case NO_MATCH: return null;
@@ -220,7 +220,7 @@ public final class DictionaryProvider extends ContentProvider {
public Cursor query(final Uri uri, final String[] projection, final String selection,
final String[] selectionArgs, final String sortOrder) {
Utils.l("Uri =", uri);
- PrivateLog.log("Query : " + uri, this);
+ PrivateLog.log("Query : " + uri);
final String clientId = getClientId(uri);
final int match = matchUri(uri);
switch (match) {
@@ -228,7 +228,7 @@ public final class DictionaryProvider extends ContentProvider {
case DICTIONARY_V2_WHOLE_LIST:
final Cursor c = MetadataDbHelper.queryDictionaries(getContext(), clientId);
Utils.l("List of dictionaries with count", c.getCount());
- PrivateLog.log("Returned a list of " + c.getCount() + " items", this);
+ PrivateLog.log("Returned a list of " + c.getCount() + " items");
return c;
case DICTIONARY_V2_DICT_INFO:
// In protocol version 2, we return null if the client is unknown. Otherwise
@@ -248,10 +248,10 @@ public final class DictionaryProvider extends ContentProvider {
// TODO: pass clientId to the following function
DictionaryService.updateNowIfNotUpdatedInAVeryLongTime(getContext());
if (null != dictFiles && dictFiles.size() > 0) {
- PrivateLog.log("Returned " + dictFiles.size() + " files", this);
+ PrivateLog.log("Returned " + dictFiles.size() + " files");
return new ResourcePathCursor(dictFiles);
} else {
- PrivateLog.log("No dictionary files for this URL", this);
+ PrivateLog.log("No dictionary files for this URL");
return new ResourcePathCursor(Collections.<WordListInfo>emptyList());
}
// V2_METADATA and V2_DATAFILE are not supported for query()
@@ -488,7 +488,7 @@ public final class DictionaryProvider extends ContentProvider {
public Uri insert(final Uri uri, final ContentValues values)
throws UnsupportedOperationException {
if (null == uri || null == values) return null; // Should never happen but let's be safe
- PrivateLog.log("Insert, uri = " + uri.toString(), this);
+ PrivateLog.log("Insert, uri = " + uri.toString());
final String clientId = getClientId(uri);
switch (matchUri(uri)) {
case DICTIONARY_V2_METADATA:
@@ -517,7 +517,7 @@ public final class DictionaryProvider extends ContentProvider {
break;
case DICTIONARY_V1_WHOLE_LIST:
case DICTIONARY_V1_DICT_INFO:
- PrivateLog.log("Attempt to insert : " + uri, this);
+ PrivateLog.log("Attempt to insert : " + uri);
throw new UnsupportedOperationException(
"Insertion in the dictionary is not supported in this version");
}
@@ -532,7 +532,7 @@ public final class DictionaryProvider extends ContentProvider {
@Override
public int update(final Uri uri, final ContentValues values, final String selection,
final String[] selectionArgs) throws UnsupportedOperationException {
- PrivateLog.log("Attempt to update : " + uri, this);
+ PrivateLog.log("Attempt to update : " + uri);
throw new UnsupportedOperationException("Updating dictionary words is not supported");
}
}
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
index 5817eb498..46bb5543a 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
@@ -21,7 +21,6 @@ import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.os.IBinder;
import android.text.format.DateUtils;
import android.util.Log;
@@ -190,7 +189,7 @@ public final class DictionaryService extends Service {
// is still more recent than UPDATE_FREQUENCY, do nothing.
if (!isLastUpdateAtLeastThisOld(context, UPDATE_FREQUENCY)) return;
- PrivateLog.log("Date changed - registering alarm", context);
+ PrivateLog.log("Date changed - registering alarm");
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
// Best effort to wake between midnight and MAX_ALARM_DELAY in the morning.
@@ -215,7 +214,7 @@ public final class DictionaryService extends Service {
private static boolean isLastUpdateAtLeastThisOld(final Context context, final long time) {
final long now = System.currentTimeMillis();
final long lastUpdate = MetadataDbHelper.getOldestUpdateTime(context);
- PrivateLog.log("Last update was " + lastUpdate, context);
+ PrivateLog.log("Last update was " + lastUpdate);
return lastUpdate + time < now;
}
diff --git a/java/src/com/android/inputmethod/dictionarypack/LogProblemReporter.java b/java/src/com/android/inputmethod/dictionarypack/LogProblemReporter.java
index c127ad540..c9e128d70 100644
--- a/java/src/com/android/inputmethod/dictionarypack/LogProblemReporter.java
+++ b/java/src/com/android/inputmethod/dictionarypack/LogProblemReporter.java
@@ -28,7 +28,8 @@ final class LogProblemReporter implements ProblemReporter {
TAG = tag;
}
+ @Override
public void report(final Exception e) {
- Log.e(TAG, "Reporting problem : " + e);
+ Log.e(TAG, "Reporting problem", e);
}
}
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index 55f545aad..cb8e25e99 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -16,13 +16,11 @@
package com.android.inputmethod.dictionarypack;
-import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
-import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -309,8 +307,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
* @param uri the metadata URI we just downloaded
*/
public static void saveLastUpdateTimeOfUri(final Context context, final String uri) {
- PrivateLog.log("Save last update time of URI : " + uri + " " + System.currentTimeMillis(),
- context);
+ PrivateLog.log("Save last update time of URI : " + uri + " " + System.currentTimeMillis());
final ContentValues values = new ContentValues();
values.put(CLIENT_LAST_UPDATE_DATE_COLUMN, System.currentTimeMillis());
final SQLiteDatabase defaultDb = getDb(context, null);
diff --git a/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java b/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
index 8593c1c9b..67dd7b9b7 100644
--- a/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
+++ b/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
@@ -16,7 +16,6 @@
package com.android.inputmethod.dictionarypack;
-import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
@@ -24,6 +23,7 @@ import android.database.sqlite.SQLiteOpenHelper;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
/**
* Class to keep long-term log. This is inactive in production, and is only for debug purposes.
@@ -44,10 +44,10 @@ public class PrivateLog {
+ COLUMN_EVENT + " TEXT);";
private static final SimpleDateFormat sDateFormat =
- new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+ new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
private static PrivateLog sInstance = new PrivateLog();
- private static DebugHelper mDebugHelper = null;
+ private static DebugHelper sDebugHelper = null;
private PrivateLog() {
}
@@ -55,8 +55,8 @@ public class PrivateLog {
public static synchronized PrivateLog getInstance(final Context context) {
if (!DEBUG) return sInstance;
synchronized(PrivateLog.class) {
- if (sInstance.mDebugHelper == null) {
- sInstance.mDebugHelper = new DebugHelper(context);
+ if (sDebugHelper == null) {
+ sDebugHelper = new DebugHelper(context);
}
return sInstance;
}
@@ -94,16 +94,9 @@ public class PrivateLog {
}
- public static void log(String event, Context context) {
+ public static void log(String event) {
if (!DEBUG) return;
- final SQLiteDatabase l = getInstance(context).mDebugHelper.getWritableDatabase();
- mDebugHelper.insert(l, event);
- }
-
- public static void log(String event, ContentProvider provider) {
- if (!DEBUG) return;
- final SQLiteDatabase l =
- getInstance(provider.getContext()).mDebugHelper.getWritableDatabase();
- mDebugHelper.insert(l, event);
+ final SQLiteDatabase l = sDebugHelper.getWritableDatabase();
+ DebugHelper.insert(l, event);
}
}
diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
index e05a79b7b..a59660954 100644
--- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
@@ -181,10 +181,9 @@ public final class UpdateHandler {
if (!cursor.moveToFirst()) return;
do {
final String clientId = cursor.getString(0);
- if (TextUtils.isEmpty(clientId)) continue; // This probably can't happen
final String metadataUri =
MetadataDbHelper.getMetadataUriAsString(context, clientId);
- PrivateLog.log("Update for clientId " + Utils.s(clientId), context);
+ PrivateLog.log("Update for clientId " + Utils.s(clientId));
Utils.l("Update for clientId", clientId, " which uses URI ", metadataUri);
uris.add(metadataUri);
} while (cursor.moveToNext());
@@ -212,7 +211,7 @@ public final class UpdateHandler {
*/
private static void updateClientsWithMetadataUri(final Context context,
final boolean updateNow, final String metadataUri) {
- PrivateLog.log("Update for metadata URI " + Utils.s(metadataUri), context);
+ PrivateLog.log("Update for metadata URI " + Utils.s(metadataUri));
final Request metadataRequest = new Request(Uri.parse(metadataUri));
Utils.l("Request =", metadataRequest);
@@ -258,7 +257,7 @@ public final class UpdateHandler {
// method will ignore it.
writeMetadataDownloadId(context, metadataUri, downloadId);
}
- PrivateLog.log("Requested download with id " + downloadId, context);
+ PrivateLog.log("Requested download with id " + downloadId);
}
/**
@@ -405,7 +404,7 @@ public final class UpdateHandler {
/* package */ static void downloadFinished(final Context context, final Intent intent) {
// Get and check the ID of the file that was downloaded
final long fileId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, NOT_AN_ID);
- PrivateLog.log("Download finished with id " + fileId, context);
+ PrivateLog.log("Download finished with id " + fileId);
Utils.l("DownloadFinished with id", fileId);
if (NOT_AN_ID == fileId) return; // Spurious wake-up: ignore
@@ -492,7 +491,7 @@ public final class UpdateHandler {
private static void publishUpdateCycleCompletedEvent(final Context context) {
// Even if this is not successful, we have to publish the new state.
- PrivateLog.log("Publishing update cycle completed event", context);
+ PrivateLog.log("Publishing update cycle completed event");
Utils.l("Publishing update cycle completed event");
for (UpdateEventListener listener : linkedCopyOfList(sUpdateEventListeners)) {
listener.updateCycleCompleted();
@@ -583,7 +582,7 @@ public final class UpdateHandler {
}
Utils.l("Downloaded metadata :", newMetadata);
- PrivateLog.log("Downloaded metadata\n" + newMetadata, context);
+ PrivateLog.log("Downloaded metadata\n" + newMetadata);
final ActionBatch actions = computeUpgradeTo(context, clientId, newMetadata);
// TODO: Check with UX how we should report to the user
@@ -611,7 +610,7 @@ public final class UpdateHandler {
MetadataDbHelper.DESCRIPTION_COLUMN), "for", downloadRecord.mClientId);
PrivateLog.log("Downloaded a new word list with description : "
+ downloadRecord.mAttributes.getAsString(MetadataDbHelper.DESCRIPTION_COLUMN)
- + " for " + downloadRecord.mClientId, context);
+ + " for " + downloadRecord.mClientId);
final String locale =
downloadRecord.mAttributes.getAsString(MetadataDbHelper.LOCALE_COLUMN);
diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
index 0d923ae01..93f12d53e 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
@@ -23,7 +23,9 @@ import android.preference.DialogPreference;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.widget.Button;
+import android.widget.ListView;
import com.android.inputmethod.latin.R;
@@ -42,6 +44,7 @@ public final class WordListPreference extends DialogPreference {
// What to display in the "status" field when we receive unknown data as a status from
// the content provider. Empty string sounds sensible.
static final private String NO_STATUS_MESSAGE = "";
+ static final private int NOT_AN_INDEX = -1;
/// Actions
static final private int ACTION_UNKNOWN = 0;
@@ -64,7 +67,8 @@ public final class WordListPreference extends DialogPreference {
static final private int ANIMATION_IN = 1;
static final private int ANIMATION_OUT = 2;
- private static Button sLastClickedActionButton = null;
+ private static int sLastClickedIndex = NOT_AN_INDEX;
+ private static String sLastClickedWordlistId = null;
private final OnWordListPreferenceClick mPreferenceClickHandler =
new OnWordListPreferenceClick();
private final OnActionButtonClick mActionButtonClickHandler =
@@ -196,7 +200,8 @@ public final class WordListPreference extends DialogPreference {
((ViewGroup)view).setLayoutTransition(null);
final Button button = (Button)view.findViewById(R.id.wordlist_button);
button.setText(getButtonLabel(mStatus));
- button.setVisibility(View.INVISIBLE);
+ // String identity match. This is an ==, not an .equals, on purpose.
+ button.setVisibility(mWordlistId == sLastClickedWordlistId ? View.VISIBLE : View.INVISIBLE);
button.setOnClickListener(mActionButtonClickHandler);
view.setOnClickListener(mPreferenceClickHandler);
}
@@ -205,15 +210,31 @@ public final class WordListPreference extends DialogPreference {
@Override
public void onClick(final View v) {
final Button button = (Button)v.findViewById(R.id.wordlist_button);
- if (null != sLastClickedActionButton) {
- animateButton(sLastClickedActionButton, ANIMATION_OUT);
- }
animateButton(button, ANIMATION_IN);
- sLastClickedActionButton = button;
+ final ViewParent parent = v.getParent();
+ // Just in case something changed in the framework, test for the concrete class
+ if (!(parent instanceof ListView)) return;
+ final ListView listView = (ListView)parent;
+ final int myIndex = listView.indexOfChild(v) + listView.getFirstVisiblePosition();
+ if (NOT_AN_INDEX != sLastClickedIndex) {
+ animateButton(getButtonForIndex(listView, sLastClickedIndex), ANIMATION_OUT);
+ }
+ sLastClickedIndex = myIndex;
+ sLastClickedWordlistId = mWordlistId;
+ }
+ }
+
+ private Button getButtonForIndex(final ListView listView, final int index) {
+ final int indexInChildren = index - listView.getFirstVisiblePosition();
+ if (indexInChildren < 0 || index > listView.getLastVisiblePosition()) {
+ // The view is offscreen.
+ return null;
}
+ return (Button)listView.getChildAt(indexInChildren).findViewById(R.id.wordlist_button);
}
private void animateButton(final Button button, final int direction) {
+ if (null == button) return;
final float outerX = ((View)button.getParent()).getWidth();
final float innerX = button.getX() - button.getTranslationX();
if (View.INVISIBLE == button.getVisibility()) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 0e1c4dc31..16eab4bc4 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -439,6 +439,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mHandler.onCreate();
DEBUG = LatinImeLogger.sDBG;
+ // TODO: Resolve mutual dependencies of {@link #loadSettings()} and {@link #initSuggest()}.
loadSettings();
initSuggest();
@@ -476,6 +477,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
final InputAttributes inputAttributes =
new InputAttributes(getCurrentInputEditorInfo(), isFullscreenMode());
mSettings.loadSettings(locale, inputAttributes);
+ // May need to reset the contacts dictionary depending on the user settings.
resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
}
@@ -745,6 +747,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mRecapitalizeStatus.deactivate();
mCurrentlyPressedHardwareKeys.clear();
+ // Note: the following does a round-trip IPC on the main thread: be careful
+ final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+ if (null != mSuggest && null != currentLocale && !currentLocale.equals(mSuggest.mLocale)) {
+ initSuggest();
+ }
if (mSuggestionStripView != null) {
// This will set the punctuation suggestions if next word suggestion is off;
// otherwise it will clear the suggestion strip.
@@ -797,8 +804,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// to the user dictionary.
if (null != mPositionalInfoForUserDictPendingAddition
&& mPositionalInfoForUserDictPendingAddition.tryReplaceWithActualWord(
- mConnection, editorInfo, mLastSelectionEnd,
- mSubtypeSwitcher.getCurrentSubtypeLocale())) {
+ mConnection, editorInfo, mLastSelectionEnd, currentLocale)) {
mPositionalInfoForUserDictPendingAddition = null;
}
// If tryReplaceWithActualWord returns false, we don't know what word was
@@ -1678,7 +1684,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
private SuggestedWords getSuggestedWordsGestureLocked(final InputPointers batchPointers) {
mLatinIme.mWordComposer.setBatchInputPointers(batchPointers);
final SuggestedWords suggestedWords =
- mLatinIme.getSuggestedWords(Suggest.SESSION_GESTURE);
+ mLatinIme.getSuggestedWordsOrOlderSuggestions(Suggest.SESSION_GESTURE);
final int suggestionCount = suggestedWords.size();
if (suggestionCount <= 1) {
final String mostProbableSuggestion = (suggestionCount == 0) ? null
@@ -1970,9 +1976,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// If we have a recapitalize in progress, use it; otherwise, create a new one.
if (!mRecapitalizeStatus.isActive()
|| !mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) {
+ final CharSequence selectedText =
+ mConnection.getSelectedText(0 /* flags, 0 for no styles */);
+ if (TextUtils.isEmpty(selectedText)) return; // Race condition with the input connection
mRecapitalizeStatus.initialize(mLastSelectionStart, mLastSelectionEnd,
- mConnection.getSelectedText(0 /* flags, 0 for no styles */).toString(),
- mSettings.getCurrentLocale(), mSettings.getWordSeparators());
+ selectedText.toString(), mSettings.getCurrentLocale(),
+ mSettings.getWordSeparators());
// We trim leading and trailing whitespace.
mRecapitalizeStatus.trim();
// Trimming the object may have changed the length of the string, and we need to
@@ -2152,7 +2161,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
return;
}
- final SuggestedWords suggestedWords = getSuggestedWords(Suggest.SESSION_TYPING);
+ final SuggestedWords suggestedWords =
+ getSuggestedWordsOrOlderSuggestions(Suggest.SESSION_TYPING);
final String typedWord = mWordComposer.getTypedWord();
showSuggestionStrip(suggestedWords, typedWord);
}
@@ -2162,7 +2172,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
if (keyboard == null || mSuggest == null) {
return SuggestedWords.EMPTY;
}
- final String typedWord = mWordComposer.getTypedWord();
// Get the word on which we should search the bigrams. If we are composing a word, it's
// whatever is *before* the half-committed word in the buffer, hence 2; if we aren't, we
// should just skip whitespace if any, so 1.
@@ -2170,10 +2179,13 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
final String prevWord =
mConnection.getNthPreviousWord(mSettings.getCurrent().mWordSeparators,
mWordComposer.isComposingWord() ? 2 : 1);
- final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
- prevWord, keyboard.getProximityInfo(), mSettings.getCurrent().mCorrectionEnabled,
- sessionId);
- return maybeRetrieveOlderSuggestions(typedWord, suggestedWords);
+ return mSuggest.getSuggestedWords(mWordComposer, prevWord, keyboard.getProximityInfo(),
+ mSettings.getCurrent().mCorrectionEnabled, sessionId);
+ }
+
+ private SuggestedWords getSuggestedWordsOrOlderSuggestions(final int sessionId) {
+ return maybeRetrieveOlderSuggestions(mWordComposer.getTypedWord(),
+ getSuggestedWords(sessionId));
}
private SuggestedWords maybeRetrieveOlderSuggestions(final String typedWord,
@@ -2186,7 +2198,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// old suggestions. Also, if we are showing the "add to dictionary" hint, we need to
// revert to suggestions - although it is unclear how we can come here if it's displayed.
if (suggestedWords.size() > 1 || typedWord.length() <= 1
- || suggestedWords.mTypedWordValid
+ || suggestedWords.mTypedWordValid || null == mSuggestionStripView
|| mSuggestionStripView.isShowingAddToDictionaryHint()) {
return suggestedWords;
} else {
@@ -2577,8 +2589,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// Outside LatinIME, only used by the {@link InputTestsBase} test suite.
@UsedForTesting
void loadKeyboard() {
- // When the device locale is changed in SetupWizard etc., this method may get called via
- // onConfigurationChanged before SoftInputWindow is shown.
+ // TODO: Why are we calling {@link #loadSettings()} and {@link #initSuggest()} in a
+ // different order than in {@link #onStartInputView}?
initSuggest();
loadSettings();
if (mKeyboardSwitcher.getMainKeyboardView() != null) {
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 671d7146b..59d0207f6 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -68,7 +68,7 @@ public final class Suggest {
private float mAutoCorrectionThreshold;
// Locale used for upper- and title-casing words
- private final Locale mLocale;
+ public final Locale mLocale;
public Suggest(final Context context, final Locale locale,
final SuggestInitializationListener listener) {
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
index 099169aa9..a7a41719e 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
@@ -17,10 +17,12 @@
package com.android.inputmethod.latin.setup;
import android.app.Activity;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
+import android.media.MediaPlayer;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Message;
import android.provider.Settings;
@@ -28,6 +30,7 @@ import android.view.View;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
+import android.widget.VideoView;
import com.android.inputmethod.compat.TextViewCompatUtils;
import com.android.inputmethod.compat.ViewCompatUtils;
@@ -39,14 +42,23 @@ import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
import java.util.HashMap;
-public final class SetupActivity extends Activity {
+// TODO: Use Fragment to implement welcome screen and setup steps.
+public final class SetupActivity extends Activity implements View.OnClickListener {
+ private View mWelcomeScreen;
+ private View mSetupScreen;
private SetupStepIndicatorView mStepIndicatorView;
- private final SetupStepGroup mSetupSteps = new SetupStepGroup();
+ private Uri mWelcomeVideoUri;
+ private VideoView mWelcomeVideoView;
+ private View mActionStart;
+ private TextView mActionFinish;
+ private final SetupStepGroup mSetupStepGroup = new SetupStepGroup();
private static final String STATE_STEP = "step";
private int mStepNumber;
+ private static final int STEP_0 = 0;
private static final int STEP_1 = 1;
private static final int STEP_2 = 2;
private static final int STEP_3 = 3;
+ private boolean mWasLanguageAndInputSettingsInvoked;
private final SettingsPoolingHandler mHandler = new SettingsPoolingHandler(this);
@@ -108,16 +120,20 @@ public final class SetupActivity extends Activity {
return;
}
- // TODO: Use sans-serif-thin font family depending on the system locale white list and
- // the SDK version.
- final TextView titleView = (TextView)findViewById(R.id.setup_title);
- final int appName = getApplicationInfo().labelRes;
- titleView.setText(getString(R.string.setup_steps_title, getString(appName)));
+ final String applicationName = getResources().getString(getApplicationInfo().labelRes);
+ mWelcomeScreen = findViewById(R.id.setup_welcome_screen);
+ final TextView welcomeTitle = (TextView)findViewById(R.id.setup_welcome_title);
+ welcomeTitle.setText(getString(R.string.setup_welcome_title, applicationName));
+
+ mSetupScreen = findViewById(R.id.setup_steps_screen);
+ final TextView stepsTitle = (TextView)findViewById(R.id.setup_title);
+ stepsTitle.setText(getString(R.string.setup_steps_title, applicationName));
mStepIndicatorView = (SetupStepIndicatorView)findViewById(R.id.setup_step_indicator);
- final SetupStep step1 = new SetupStep(findViewById(R.id.setup_step1),
- appName, R.string.setup_step1_title, R.string.setup_step1_instruction,
+ final SetupStep step1 = new SetupStep(applicationName,
+ (TextView)findViewById(R.id.setup_step1_bullet), findViewById(R.id.setup_step1),
+ R.string.setup_step1_title, R.string.setup_step1_instruction,
R.drawable.ic_setup_step1, R.string.setup_step1_action);
step1.setAction(new Runnable() {
@Override
@@ -126,10 +142,11 @@ public final class SetupActivity extends Activity {
mHandler.startPollingImeSettings();
}
});
- mSetupSteps.addStep(STEP_1, step1);
+ mSetupStepGroup.addStep(STEP_1, step1);
- final SetupStep step2 = new SetupStep(findViewById(R.id.setup_step2),
- appName, R.string.setup_step2_title, R.string.setup_step2_instruction,
+ final SetupStep step2 = new SetupStep(applicationName,
+ (TextView)findViewById(R.id.setup_step2_bullet), findViewById(R.id.setup_step2),
+ R.string.setup_step2_title, R.string.setup_step2_instruction,
R.drawable.ic_setup_step2, R.string.setup_step2_action);
step2.setAction(new Runnable() {
@Override
@@ -139,10 +156,11 @@ public final class SetupActivity extends Activity {
.showInputMethodPicker();
}
});
- mSetupSteps.addStep(STEP_2, step2);
+ mSetupStepGroup.addStep(STEP_2, step2);
- final SetupStep step3 = new SetupStep(findViewById(R.id.setup_step3),
- appName, R.string.setup_step3_title, R.string.setup_step3_instruction,
+ final SetupStep step3 = new SetupStep(applicationName,
+ (TextView)findViewById(R.id.setup_step3_bullet), findViewById(R.id.setup_step3),
+ R.string.setup_step3_title, R.string.setup_step3_instruction,
R.drawable.ic_setup_step3, R.string.setup_step3_action);
step3.setAction(new Runnable() {
@Override
@@ -150,7 +168,40 @@ public final class SetupActivity extends Activity {
invokeSubtypeEnablerOfThisIme();
}
});
- mSetupSteps.addStep(STEP_3, step3);
+ mSetupStepGroup.addStep(STEP_3, step3);
+
+ mWelcomeVideoUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+ .authority(getPackageName())
+ .path(Integer.toString(R.raw.setup_welcome_video))
+ .build();
+ mWelcomeVideoView = (VideoView)findViewById(R.id.setup_welcome_video);
+ mWelcomeVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(final MediaPlayer mp) {
+ mp.start();
+ }
+ });
+
+ mActionStart = findViewById(R.id.setup_start_label);
+ mActionStart.setOnClickListener(this);
+ mActionFinish = (TextView)findViewById(R.id.setup_finish);
+ TextViewCompatUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(mActionFinish,
+ getResources().getDrawable(R.drawable.ic_setup_finish), null, null, null);
+ mActionFinish.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(final View v) {
+ if (v == mActionStart) {
+ mStepNumber = STEP_1;
+ updateSetupStepView();
+ return;
+ }
+ if (v == mActionFinish) {
+ finish();
+ return;
+ }
}
private void invokeSetupWizardOfThisIme() {
@@ -165,7 +216,8 @@ public final class SetupActivity extends Activity {
final Intent intent = new Intent();
intent.setClass(this, SettingsActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
- | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP
+ | Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
}
@@ -174,6 +226,7 @@ public final class SetupActivity extends Activity {
intent.setAction(Settings.ACTION_INPUT_METHOD_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivity(intent);
+ mWasLanguageAndInputSettingsInvoked = true;
}
private void invokeSubtypeEnablerOfThisIme() {
@@ -224,7 +277,7 @@ public final class SetupActivity extends Activity {
private int determineSetupStepNumber() {
mHandler.cancelPollingImeSettings();
if (!isThisImeEnabled(this)) {
- return STEP_1;
+ return mWasLanguageAndInputSettingsInvoked ? STEP_1 : STEP_0;
}
if (!isThisImeCurrent(this)) {
return STEP_2;
@@ -263,6 +316,22 @@ public final class SetupActivity extends Activity {
}
@Override
+ public void onBackPressed() {
+ if (mStepNumber == STEP_1) {
+ mStepNumber = STEP_0;
+ updateSetupStepView();
+ return;
+ }
+ super.onBackPressed();
+ }
+
+ @Override
+ protected void onPause() {
+ mWelcomeVideoView.stopPlayback();
+ super.onPause();
+ }
+
+ @Override
public void onWindowFocusChanged(final boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (!hasFocus) {
@@ -273,10 +342,20 @@ public final class SetupActivity extends Activity {
}
private void updateSetupStepView() {
+ final boolean welcomeScreen = (mStepNumber == STEP_0);
+ mWelcomeScreen.setVisibility(welcomeScreen ? View.VISIBLE : View.GONE);
+ mSetupScreen.setVisibility(welcomeScreen ? View.GONE: View.VISIBLE);
+ if (welcomeScreen) {
+ mWelcomeVideoView.setVideoURI(mWelcomeVideoUri);
+ mWelcomeVideoView.start();
+ return;
+ }
+ mWelcomeVideoView.stopPlayback();
final int layoutDirection = ViewCompatUtils.getLayoutDirection(mStepIndicatorView);
mStepIndicatorView.setIndicatorPosition(
- getIndicatorPosition(mStepNumber, mSetupSteps.getTotalStep(), layoutDirection));
- mSetupSteps.enableStep(mStepNumber);
+ getIndicatorPosition(mStepNumber, mSetupStepGroup.getTotalStep(), layoutDirection));
+ mSetupStepGroup.enableStep(mStepNumber);
+ mActionFinish.setVisibility((mStepNumber == STEP_3) ? View.VISIBLE : View.GONE);
}
private static float getIndicatorPosition(final int step, final int totalStep,
@@ -286,20 +365,26 @@ public final class SetupActivity extends Activity {
}
static final class SetupStep implements View.OnClickListener {
- private final View mRootView;
+ private final View mStepView;
+ private final TextView mBulletView;
+ private final int mActivatedColor;
+ private final int mDeactivatedColor;
private final TextView mActionLabel;
private Runnable mAction;
- public SetupStep(final View rootView, final int appName, final int title,
- final int instruction, final int actionIcon, final int actionLabel) {
- mRootView = rootView;
- final Resources res = rootView.getResources();
- final String applicationName = res.getString(appName);
+ public SetupStep(final String applicationName, final TextView bulletView,
+ final View stepView, final int title, final int instruction, final int actionIcon,
+ final int actionLabel) {
+ mStepView = stepView;
+ mBulletView = bulletView;
+ final Resources res = stepView.getResources();
+ mActivatedColor = res.getColor(R.color.setup_text_action);
+ mDeactivatedColor = res.getColor(R.color.setup_text_dark);
- final TextView titleView = (TextView)rootView.findViewById(R.id.setup_step_title);
+ final TextView titleView = (TextView)mStepView.findViewById(R.id.setup_step_title);
titleView.setText(res.getString(title, applicationName));
- final TextView instructionView = (TextView)rootView.findViewById(
+ final TextView instructionView = (TextView)mStepView.findViewById(
R.id.setup_step_instruction);
if (instruction == 0) {
instructionView.setVisibility(View.GONE);
@@ -307,21 +392,20 @@ public final class SetupActivity extends Activity {
instructionView.setText(res.getString(instruction, applicationName));
}
- mActionLabel = (TextView)rootView.findViewById(R.id.setup_step_action_label);
+ mActionLabel = (TextView)mStepView.findViewById(R.id.setup_step_action_label);
mActionLabel.setText(res.getString(actionLabel));
if (actionIcon == 0) {
final int paddingEnd = ViewCompatUtils.getPaddingEnd(mActionLabel);
ViewCompatUtils.setPaddingRelative(mActionLabel, paddingEnd, 0, paddingEnd, 0);
} else {
- final Drawable icon = res.getDrawable(actionIcon);
- icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
- TextViewCompatUtils.setCompoundDrawablesRelative(
- mActionLabel, icon, null, null, null);
+ TextViewCompatUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(
+ mActionLabel, res.getDrawable(actionIcon), null, null, null);
}
}
public void setEnabled(final boolean enabled) {
- mRootView.setVisibility(enabled ? View.VISIBLE : View.GONE);
+ mStepView.setVisibility(enabled ? View.VISIBLE : View.GONE);
+ mBulletView.setTextColor(enabled ? mActivatedColor : mDeactivatedColor);
}
public void setAction(final Runnable action) {
@@ -331,8 +415,9 @@ public final class SetupActivity extends Activity {
@Override
public void onClick(final View v) {
- if (mAction != null) {
+ if (v == mActionLabel && mAction != null) {
mAction.run();
+ return;
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java b/java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java
new file mode 100644
index 000000000..ca974f6b8
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java
@@ -0,0 +1,108 @@
+/*
+ * 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.setup;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.inputmethod.compat.ViewCompatUtils;
+import com.android.inputmethod.latin.R;
+
+public final class SetupStartIndicatorView extends LinearLayout {
+ public SetupStartIndicatorView(final Context context, final AttributeSet attrs) {
+ super(context, attrs);
+ setOrientation(HORIZONTAL);
+ LayoutInflater.from(context).inflate(R.layout.setup_start_indicator_label, this);
+
+ final LabelView labelView = (LabelView)findViewById(R.id.setup_start_label);
+ labelView.setIndicatorView(findViewById(R.id.setup_start_indicator));
+ }
+
+ public static final class LabelView extends TextView {
+ private View mIndicatorView;
+
+ public LabelView(final Context context, final AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void setIndicatorView(final View indicatorView) {
+ mIndicatorView = indicatorView;
+ }
+
+ @Override
+ public void setPressed(final boolean pressed) {
+ super.setPressed(pressed);
+ if (mIndicatorView != null) {
+ mIndicatorView.setPressed(pressed);
+ }
+ }
+ }
+
+ public static final class IndicatorView extends View {
+ private final Path mIndicatorPath = new Path();
+ private final Paint mIndicatorPaint = new Paint();
+ private final ColorStateList mIndicatorColor;
+
+ public IndicatorView(final Context context, final AttributeSet attrs) {
+ super(context, attrs);
+ mIndicatorColor = getResources().getColorStateList(
+ R.color.setup_step_action_background);
+ mIndicatorPaint.setStyle(Paint.Style.FILL);
+ }
+
+ @Override
+ public void setPressed(final boolean pressed) {
+ super.setPressed(pressed);
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(final Canvas canvas) {
+ super.onDraw(canvas);
+ final int layoutDirection = ViewCompatUtils.getLayoutDirection(this);
+ final int width = getWidth();
+ final int height = getHeight();
+ final float halfHeight = height / 2.0f;
+ final Path path = mIndicatorPath;
+ path.rewind();
+ if (layoutDirection == ViewCompatUtils.LAYOUT_DIRECTION_RTL) {
+ // Left arrow
+ path.moveTo(width, 0.0f);
+ path.lineTo(0.0f, halfHeight);
+ path.lineTo(width, height);
+ } else { // LAYOUT_DIRECTION_LTR
+ // Right arrow
+ path.moveTo(0.0f, 0.0f);
+ path.lineTo(width, halfHeight);
+ path.lineTo(0.0f, height);
+ }
+ path.close();
+ final int[] stateSet = getDrawableState();
+ final int color = mIndicatorColor.getColorForState(stateSet, 0);
+ mIndicatorPaint.setColor(color);
+ canvas.drawPath(path, mIndicatorPaint);
+ }
+ }
+}