aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java1
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java3
-rw-r--r--java/src/com/android/inputmethod/latin/DebugSettings.java14
-rw-r--r--java/src/com/android/inputmethod/latin/FeedbackUtils.java9
-rw-r--r--java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java12
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputMethodManager.java127
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java2
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsFragment.java28
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java10
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java15
-rw-r--r--java/src/com/android/inputmethod/latin/setup/SetupActivity.java166
-rw-r--r--java/src/com/android/inputmethod/latin/setup/SetupStartIndicatorView.java108
12 files changed, 420 insertions, 75 deletions
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 18e712212..dbc2b9082 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -141,7 +141,6 @@ public final class BinaryDictionary extends Dictionary {
mOutputTypes);
final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList();
for (int j = 0; j < count; ++j) {
- if (composerSize > 0 && mOutputScores[j] < 1) break;
final int start = j * MAX_WORD_LENGTH;
int len = 0;
while (len < MAX_WORD_LENGTH && mOutputCodePoints[start + len] != 0) {
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index 42f713697..4a2c3bb80 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -81,6 +81,7 @@ public final class BinaryDictionaryFileDumper {
private static final String QUERY_PATH_METADATA = "metadata";
private static final String INSERT_METADATA_CLIENT_ID_COLUMN = "clientid";
private static final String INSERT_METADATA_METADATA_URI_COLUMN = "uri";
+ private static final String INSERT_METADATA_METADATA_ADDITIONAL_ID_COLUMN = "additionalid";
// Prevents this class to be accidentally instantiated.
private BinaryDictionaryFileDumper() {
@@ -423,6 +424,7 @@ public final class BinaryDictionaryFileDumper {
private static void reinitializeClientRecordInDictionaryContentProvider(final Context context,
final ContentProviderClient client, final String clientId) throws RemoteException {
final String metadataFileUri = MetadataFileUriGetter.getMetadataUri(context);
+ final String metadataAdditionalId = MetadataFileUriGetter.getMetadataAdditionalId(context);
if (TextUtils.isEmpty(metadataFileUri)) return;
// Tell the content provider to reset all information about this client id
final Uri metadataContentUri = getProviderUriBuilder(clientId)
@@ -434,6 +436,7 @@ public final class BinaryDictionaryFileDumper {
final ContentValues metadataValues = new ContentValues();
metadataValues.put(INSERT_METADATA_CLIENT_ID_COLUMN, clientId);
metadataValues.put(INSERT_METADATA_METADATA_URI_COLUMN, metadataFileUri);
+ metadataValues.put(INSERT_METADATA_METADATA_ADDITIONAL_ID_COLUMN, metadataAdditionalId);
client.insert(metadataContentUri, metadataValues);
// Update the dictionary list.
diff --git a/java/src/com/android/inputmethod/latin/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java
index c2aade64d..9d4794121 100644
--- a/java/src/com/android/inputmethod/latin/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/DebugSettings.java
@@ -121,18 +121,8 @@ public final class DebugSettings extends PreferenceFragment
return;
}
boolean isDebugMode = mDebugMode.isChecked();
- String version = "";
- try {
- final Context context = getActivity();
- if (context == null) {
- return;
- }
- final String packageName = context.getPackageName();
- PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
- version = "Version " + info.versionName;
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Could not find version info.");
- }
+ final String version = getResources().getString(
+ R.string.version_text, Utils.getSdkVersion(getActivity()));
if (!isDebugMode) {
mDebugMode.setTitle(version);
mDebugMode.setSummary("");
diff --git a/java/src/com/android/inputmethod/latin/FeedbackUtils.java b/java/src/com/android/inputmethod/latin/FeedbackUtils.java
index 1e5260e34..0582763fe 100644
--- a/java/src/com/android/inputmethod/latin/FeedbackUtils.java
+++ b/java/src/com/android/inputmethod/latin/FeedbackUtils.java
@@ -17,6 +17,7 @@
package com.android.inputmethod.latin;
import android.content.Context;
+import android.content.Intent;
public class FeedbackUtils {
public static boolean isFeedbackFormSupported() {
@@ -25,4 +26,12 @@ public class FeedbackUtils {
public static void showFeedbackForm(Context context) {
}
+
+ public static int getAboutKeyboardTitleResId() {
+ return 0;
+ }
+
+ public static Intent getAboutKeyboardIntent(Context context) {
+ return null;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java b/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java
index e6dc6db8f..a98ecc7b6 100644
--- a/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java
+++ b/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java
@@ -19,10 +19,18 @@ package com.android.inputmethod.latin;
import android.content.Context;
/**
- * Helper class to get the metadata URI.
+ * Helper class to get the metadata URI and the additional ID.
*/
public class MetadataFileUriGetter {
- public static String getMetadataUri(Context context) {
+ private MetadataFileUriGetter() {
+ // This helper class is not instantiable.
+ }
+
+ public static String getMetadataUri(final Context context) {
return context.getString(R.string.dictionary_pack_metadata_uri);
}
+
+ public static String getMetadataAdditionalId(final Context context) {
+ return "";
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index e39aae958..3f7be99e5 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.preference.PreferenceManager;
+import android.util.Log;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
@@ -46,6 +47,8 @@ public final class RichInputMethodManager {
private InputMethodManagerCompatWrapper mImmWrapper;
private InputMethodInfo mInputMethodInfoOfThisIme;
+ private static final int INDEX_NOT_FOUND = -1;
+
public static RichInputMethodManager getInstance() {
sInstance.checkInitialized();
return sInstance;
@@ -98,11 +101,100 @@ public final class RichInputMethodManager {
}
public boolean switchToNextInputMethod(final IBinder token, final boolean onlyCurrentIme) {
- final boolean result = mImmWrapper.switchToNextInputMethod(token, onlyCurrentIme);
- if (!result) {
- mImmWrapper.mImm.switchToLastInputMethod(token);
+ if (mImmWrapper.switchToNextInputMethod(token, onlyCurrentIme)) {
+ return true;
+ }
+ // Was not able to call {@link InputMethodManager#switchToNextInputMethodIBinder,boolean)}
+ // because the current device is running ICS or previous and lacks the API.
+ if (switchToNextInputSubtypeInThisIme(token, onlyCurrentIme)) {
+ return true;
+ }
+ return switchToNextInputMethodAndSubtype(token);
+ }
+
+ private boolean switchToNextInputSubtypeInThisIme(final IBinder token,
+ final boolean onlyCurrentIme) {
+ final InputMethodManager imm = mImmWrapper.mImm;
+ final InputMethodSubtype currentSubtype = imm.getCurrentInputMethodSubtype();
+ final List<InputMethodSubtype> enabledSubtypes = imm.getEnabledInputMethodSubtypeList(
+ mInputMethodInfoOfThisIme, true /* allowsImplicitlySelectedSubtypes */);
+ final int currentIndex = getSubtypeIndexInList(currentSubtype, enabledSubtypes);
+ if (currentIndex == INDEX_NOT_FOUND) {
+ Log.w(TAG, "Can't find current subtype in enabled subtypes: subtype="
+ + SubtypeLocale.getSubtypeDisplayName(currentSubtype));
+ return false;
+ }
+ final int nextIndex = (currentIndex + 1) % enabledSubtypes.size();
+ if (nextIndex <= currentIndex && !onlyCurrentIme) {
+ // The current subtype is the last or only enabled one and it needs to switch to
+ // next IME.
return false;
}
+ final InputMethodSubtype nextSubtype = enabledSubtypes.get(nextIndex);
+ setInputMethodAndSubtype(token, nextSubtype);
+ return true;
+ }
+
+ private boolean switchToNextInputMethodAndSubtype(final IBinder token) {
+ final InputMethodManager imm = mImmWrapper.mImm;
+ final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
+ final int currentIndex = getImiIndexInList(mInputMethodInfoOfThisIme, enabledImis);
+ if (currentIndex == INDEX_NOT_FOUND) {
+ Log.w(TAG, "Can't find current IME in enabled IMEs: IME package="
+ + mInputMethodInfoOfThisIme.getPackageName());
+ return false;
+ }
+ final InputMethodInfo nextImi = getNextNonAuxiliaryIme(currentIndex, enabledImis);
+ final List<InputMethodSubtype> enabledSubtypes = imm.getEnabledInputMethodSubtypeList(
+ nextImi, true /* allowsImplicitlySelectedSubtypes */);
+ if (enabledSubtypes.isEmpty()) {
+ // The next IME has no subtype.
+ imm.setInputMethod(token, nextImi.getId());
+ return true;
+ }
+ final InputMethodSubtype firstSubtype = enabledSubtypes.get(0);
+ imm.setInputMethodAndSubtype(token, nextImi.getId(), firstSubtype);
+ return true;
+ }
+
+ private static int getImiIndexInList(final InputMethodInfo inputMethodInfo,
+ final List<InputMethodInfo> imiList) {
+ final int count = imiList.size();
+ for (int index = 0; index < count; index++) {
+ final InputMethodInfo imi = imiList.get(index);
+ if (imi.equals(inputMethodInfo)) {
+ return index;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ // This method mimics {@link InputMethodManager#switchToNextInputMethod(IBinder,boolean)}.
+ private static InputMethodInfo getNextNonAuxiliaryIme(final int currentIndex,
+ final List<InputMethodInfo> imiList) {
+ final int count = imiList.size();
+ for (int i = 1; i < count; i++) {
+ final int nextIndex = (currentIndex + i) % count;
+ final InputMethodInfo nextImi = imiList.get(nextIndex);
+ if (!isAuxiliaryIme(nextImi)) {
+ return nextImi;
+ }
+ }
+ return imiList.get(currentIndex);
+ }
+
+ // Copied from {@link InputMethodInfo}. See how auxiliary of IME is determined.
+ private static boolean isAuxiliaryIme(final InputMethodInfo imi) {
+ final int count = imi.getSubtypeCount();
+ if (count == 0) {
+ return false;
+ }
+ for (int index = 0; index < count; index++) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(index);
+ if (!subtype.isAuxiliary()) {
+ return false;
+ }
+ }
return true;
}
@@ -136,24 +228,35 @@ public final class RichInputMethodManager {
private static boolean checkIfSubtypeBelongsToList(final InputMethodSubtype subtype,
final List<InputMethodSubtype> subtypes) {
- for (final InputMethodSubtype ims : subtypes) {
+ return getSubtypeIndexInList(subtype, subtypes) != INDEX_NOT_FOUND;
+ }
+
+ private static int getSubtypeIndexInList(final InputMethodSubtype subtype,
+ final List<InputMethodSubtype> subtypes) {
+ final int count = subtypes.size();
+ for (int index = 0; index < count; index++) {
+ final InputMethodSubtype ims = subtypes.get(index);
if (ims.equals(subtype)) {
- return true;
+ return index;
}
}
- return false;
+ return INDEX_NOT_FOUND;
}
public boolean checkIfSubtypeBelongsToThisIme(final InputMethodSubtype subtype) {
- final InputMethodInfo myImi = mInputMethodInfoOfThisIme;
- final int count = myImi.getSubtypeCount();
- for (int i = 0; i < count; i++) {
- final InputMethodSubtype ims = myImi.getSubtypeAt(i);
+ return getSubtypeIndexInIme(subtype, mInputMethodInfoOfThisIme) != INDEX_NOT_FOUND;
+ }
+
+ private static int getSubtypeIndexInIme(final InputMethodSubtype subtype,
+ final InputMethodInfo imi) {
+ final int count = imi.getSubtypeCount();
+ for (int index = 0; index < count; index++) {
+ final InputMethodSubtype ims = imi.getSubtypeAt(index);
if (ims.equals(subtype)) {
- return true;
+ return index;
}
}
- return false;
+ return INDEX_NOT_FOUND;
}
public InputMethodSubtype getCurrentInputMethodSubtype(
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 72e08700a..22ec01558 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -36,6 +36,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_POPUP_ON = "popup_on";
public static final String PREF_VOICE_MODE = "voice_mode";
public static final String PREF_CORRECTION_SETTINGS = "correction_settings";
+ public static final String PREF_EDIT_PERSONAL_DICTIONARY = "edit_personal_dictionary";
public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key";
public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold";
public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
@@ -78,6 +79,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
"pref_suppress_language_switch_key";
public static final String PREF_SEND_FEEDBACK = "send_feedback";
+ public static final String PREF_ABOUT_KEYBOARD = "about_keyboard";
private Resources mRes;
private SharedPreferences mPrefs;
diff --git a/java/src/com/android/inputmethod/latin/SettingsFragment.java b/java/src/com/android/inputmethod/latin/SettingsFragment.java
index a96c997c8..88a27144c 100644
--- a/java/src/com/android/inputmethod/latin/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/SettingsFragment.java
@@ -20,6 +20,8 @@ import android.app.backup.BackupManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Bundle;
@@ -29,6 +31,7 @@ import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
+import android.util.Log;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.dictionarypack.DictionarySettingsActivity;
@@ -38,6 +41,8 @@ import com.android.inputmethodcommon.InputMethodSettingsFragment;
public final class SettingsFragment extends InputMethodSettingsFragment
implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = SettingsFragment.class.getSimpleName();
+
private ListPreference mVoicePreference;
private ListPreference mShowCorrectionSuggestionsPreference;
private ListPreference mAutoCorrectionThresholdPreference;
@@ -77,10 +82,13 @@ public final class SettingsFragment extends InputMethodSettingsFragment
final Resources res = getResources();
final Context context = getActivity();
- // When we are called from the Settings application but we are not already running, the
- // {@link SubtypeLocale} class may not have been initialized. It is safe to call
- // {@link SubtypeLocale#init(Context)} multiple times.
+ // When we are called from the Settings application but we are not already running, some
+ // singleton and utility classes may not have been initialized. We have to call
+ // initialization method of these classes here. See {@link LatinIME#onCreate()}.
+ SubtypeSwitcher.init(context);
SubtypeLocale.init(context);
+ AudioAndHapticFeedbackManager.init(context);
+
mVoicePreference = (ListPreference) findPreference(Settings.PREF_VOICE_MODE);
mShowCorrectionSuggestionsPreference =
(ListPreference) findPreference(Settings.PREF_SHOW_SUGGESTIONS_SETTING);
@@ -110,6 +118,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment
}
final Preference feedbackSettings = findPreference(Settings.PREF_SEND_FEEDBACK);
+ final Preference aboutSettings = findPreference(Settings.PREF_ABOUT_KEYBOARD);
if (feedbackSettings != null) {
if (FeedbackUtils.isFeedbackFormSupported()) {
feedbackSettings.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@@ -119,8 +128,11 @@ public final class SettingsFragment extends InputMethodSettingsFragment
return true;
}
});
+ aboutSettings.setTitle(FeedbackUtils.getAboutKeyboardTitleResId());
+ aboutSettings.setIntent(FeedbackUtils.getAboutKeyboardIntent(getActivity()));
} else {
miscSettings.removePreference(feedbackSettings);
+ miscSettings.removePreference(aboutSettings);
}
}
@@ -180,6 +192,16 @@ public final class SettingsFragment extends InputMethodSettingsFragment
textCorrectionGroup.removePreference(dictionaryLink);
}
+ final Preference editPersonalDictionary =
+ findPreference(Settings.PREF_EDIT_PERSONAL_DICTIONARY);
+ final Intent editPersonalDictionaryIntent = editPersonalDictionary.getIntent();
+ final ResolveInfo ri = context.getPackageManager().resolveActivity(
+ editPersonalDictionaryIntent, PackageManager.MATCH_DEFAULT_ONLY);
+ if (ri == null) {
+ // TODO: Set a intent that invokes our own edit personal dictionary activity.
+ Log.w(TAG, "No activity that responds to " + editPersonalDictionaryIntent.getAction());
+ }
+
if (!Settings.readFromBuildConfigIfGestureInputEnabled(res)) {
removePreference(Settings.PREF_GESTURE_SETTINGS, getPreferenceScreen());
}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 2f9e34ff1..bef8a3cf1 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -80,6 +80,7 @@ public final class SubtypeSwitcher {
public static void init(final Context context) {
SubtypeLocale.init(context);
+ RichInputMethodManager.init(context);
sInstance.initialize(context);
}
@@ -87,10 +88,13 @@ public final class SubtypeSwitcher {
// Intentional empty constructor for singleton.
}
- private void initialize(final Context service) {
- mResources = service.getResources();
+ private void initialize(final Context context) {
+ if (mResources != null) {
+ return;
+ }
+ mResources = context.getResources();
mRichImm = RichInputMethodManager.getInstance();
- mConnectivityManager = (ConnectivityManager) service.getSystemService(
+ mConnectivityManager = (ConnectivityManager) context.getSystemService(
Context.CONNECTIVITY_SERVICE);
mNoLanguageSubtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
SubtypeLocale.NO_LANGUAGE, SubtypeLocale.QWERTY);
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index aff5d17d7..fc32bd45e 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -21,6 +21,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.inputmethodservice.InputMethodService;
@@ -473,4 +474,18 @@ public final class Utils {
}
return 0;
}
+
+ public static String getSdkVersion(Context context) {
+ try {
+ if (context == null) {
+ return "";
+ }
+ final String packageName = context.getPackageName();
+ PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
+ return info.versionName;
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not find version info.", e);
+ }
+ return "";
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
index 15d0bac37..a7a41719e 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
@@ -17,11 +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.PorterDuff;
-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;
@@ -29,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;
@@ -40,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);
@@ -109,17 +120,21 @@ 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_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,
- R.drawable.ic_settings_language, R.string.language_settings);
+ 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
public void run() {
@@ -127,11 +142,12 @@ 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,
- 0 /* actionIcon */, R.string.select_input_method);
+ 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
public void run() {
@@ -140,18 +156,52 @@ 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, 0 /* instruction */,
- R.drawable.sym_keyboard_language_switch, 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
public void run() {
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() {
@@ -166,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);
}
@@ -175,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() {
@@ -225,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;
@@ -264,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) {
@@ -274,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,
@@ -287,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);
@@ -308,23 +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 int overrideColor = res.getColor(R.color.setup_text_action);
- final Drawable icon = res.getDrawable(actionIcon);
- icon.setColorFilter(overrideColor, PorterDuff.Mode.MULTIPLY);
- 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) {
@@ -334,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);
+ }
+ }
+}