Automated import from //branches/donutburger/...@142787,142787
diff --git a/res/drawable/dialog_bubble_step02.9.png b/res/drawable/dialog_bubble_step02.9.png
index 62386f2..d77f85f 100755
--- a/res/drawable/dialog_bubble_step02.9.png
+++ b/res/drawable/dialog_bubble_step02.9.png
Binary files differ
diff --git a/res/drawable/dialog_bubble_step03.9.png b/res/drawable/dialog_bubble_step03.9.png
deleted file mode 100755
index 16b4d02..0000000
--- a/res/drawable/dialog_bubble_step03.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/dialog_bubble_step04.9.png b/res/drawable/dialog_bubble_step04.9.png
deleted file mode 100755
index a24012d..0000000
--- a/res/drawable/dialog_bubble_step04.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/dialog_bubble_step07.9.png b/res/drawable/dialog_bubble_step07.9.png
new file mode 100755
index 0000000..80f4a0e
--- /dev/null
+++ b/res/drawable/dialog_bubble_step07.9.png
Binary files differ
diff --git a/res/layout/bubble_text.xml b/res/layout/bubble_text.xml
index eae3ab6..c3957b6 100644
--- a/res/layout/bubble_text.xml
+++ b/res/layout/bubble_text.xml
@@ -25,4 +25,6 @@
     android:textColor="?android:attr/textColorPrimary"
     android:minWidth="32dip"
     android:gravity="center"
+    android:shadowRadius="2.75"
+    android:shadowColor="#BB000000"
     />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 41809c1..25d990e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -70,6 +70,21 @@
     <!-- Description for auto punctuate -->
     <string name="auto_punctuate_summary"></string>
     
+    <!-- Option to enable quick fixes -->
+    <string name="quick_fixes">Quick fixes</string>
+    <!-- Description for quick fixes -->
+    <string name="quick_fixes_summary">Corrects commonly typed mistakes</string>
+    
+    <!-- Option to enable showing suggestions -->
+    <string name="show_suggestions">Show suggestions</string>
+    <!-- Description for show suggestions -->
+    <string name="show_suggestions_summary">Display suggested words while typing</string>
+    
+    <!-- Option to enable auto completion -->
+    <string name="auto_complete">Auto-complete</string>
+    <!-- Description for auto completion -->
+    <string name="auto_complete_summary">Spacebar and punctuation automatically insert highlighted word</string>
+    
     <!-- Array of prediction modes -->
     <string-array name="prediction_modes">
         <item>None</item>
@@ -122,7 +137,33 @@
     <!-- Tip to long press on typed word to add to dictionary -->
     <string name="tip_add_to_dictionary">Press and hold the left-most word to add it to the dictionary
         </string>
-
+        
+    <!-- Instruction to touch the bubble to continue -->
+    <string name="touch_to_continue">Touch this hint to continue »</string>
+    
+    <!-- Instruction to touch the bubble to start typing -->
+    <string name="touch_to_finish">Touch here to close this hint and start typing!</string>
+    
+    <!-- Tutorial tip 1 - The keyboard opens any time you touch a text field -->
+    <string name="tip_to_open_keyboard"><b>The keyboard opens any time you touch a text field</b></string>
+    
+    <!-- Tutorial tip 2 - Touch and hold a key to view accents (examples) -->
+    <string name="tip_to_view_accents"><b>Touch &amp; hold a key to view accents\n(ø, ö, ô, ó, and so on)</b>
+    </string>
+    
+    <!-- Tutorial tip 3 - How to switch to number/symbol keyboard -->
+    <string name="tip_to_open_symbols"><b>Switch to numbers and symbols by touching this key</b></string>
+    
+    <!-- Tutorial tip 4 - How to switch back to alphabet keyboard -->
+    <string name="tip_to_close_symbols"><b>Go back to letters by touching this key again</b></string>
+    
+    <!-- Tutorial tip 5 - How to launch keyboard settings -->
+    <string name="tip_to_launch_settings"><b>Touch &amp; hold this key to change keyboard settings, like auto complete</b></string>
+    
+    <!-- Tutorial tip 6 - Done with the tutorial -->
+    <string name="tip_to_start_typing"><b>Try it!</b></string>
+    
+    
     <!-- Label for soft enter key when it performs GO action.  Must be short to fit on key! -->
     <string name="label_go_key">Go</string>
     <!-- Label for soft enter key when it performs NEXT action.  Must be short to fit on key! -->
diff --git a/res/xml/prefs.xml b/res/xml/prefs.xml
index 037d5ff..8652699 100644
--- a/res/xml/prefs.xml
+++ b/res/xml/prefs.xml
@@ -37,44 +37,34 @@
             android:defaultValue="true"
             />
 
-    <!--CheckBoxPreference
-            android:key="auto_punctuate"
-            android:title="@string/auto_punctuate"
-            android:persistent="true"
-            android:defaultValue="true"
-            android:visible="false"
-            /-->
-
-    <ListPreference
-            android:key="prediction_mode"
-            android:title="@string/prediction"
-            android:dialogTitle="@string/auto_complete_dialog_title"
-            android:summary="@string/prediction_summary"
-            android:persistent="true" 
-            android:entries="@array/prediction_modes"
-            android:entryValues="@array/prediction_modes_values"
-            android:defaultValue="@string/prediction_basic"
-            />
-
     <PreferenceCategory
             android:title="@string/prediction_category"
             android:key="prediction_settings">
-            
+
         <CheckBoxPreference
-            android:key="hit_correction"
-            android:title="@string/hit_correction"
-            android:summary="@string/hit_correction_summary"
-            android:persistent="true" 
+            android:key="quick_fixes"
+            android:title="@string/quick_fixes"
+            android:summary="@string/quick_fixes_summary"
+            android:persistent="true"
             android:defaultValue="true"
             />
 
         <CheckBoxPreference
-            android:key="prediction_landscape"
-            android:title="@string/prediction_landscape"
-            android:summary="@string/prediction_landscape_summary"
+            android:key="show_suggestions"
+            android:title="@string/show_suggestions"
+            android:summary="@string/show_suggestions_summary"
+            android:persistent="true"
+            android:defaultValue="true"
+            />
+
+        <CheckBoxPreference
+            android:key="auto_complete"
+            android:title="@string/auto_complete"
+            android:summary="@string/auto_complete_summary"
             android:persistent="true" 
-            android:defaultValue="false"
+            android:defaultValue="true"
+            android:dependency="show_suggestions"
             />
             
     </PreferenceCategory>            
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/src/com/android/inputmethod/latin/LatinIME.java b/src/com/android/inputmethod/latin/LatinIME.java
index e5ad75b..a36ff57 100644
--- a/src/com/android/inputmethod/latin/LatinIME.java
+++ b/src/com/android/inputmethod/latin/LatinIME.java
@@ -23,7 +23,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
 import android.content.res.Configuration;
 import android.inputmethodservice.InputMethodService;
 import android.inputmethodservice.Keyboard;
@@ -35,6 +34,7 @@
 import android.os.SystemClock;
 import android.os.Vibrator;
 import android.preference.PreferenceManager;
+import android.text.AutoText;
 import android.text.ClipboardManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -64,14 +64,13 @@
     
     private static final String PREF_VIBRATE_ON = "vibrate_on";
     private static final String PREF_SOUND_ON = "sound_on";
-    private static final String PREF_PROXIMITY_CORRECTION = "hit_correction";
-    private static final String PREF_PREDICTION = "prediction_mode";
-    private static final String PREF_PREDICTION_LANDSCAPE = "prediction_landscape";
     private static final String PREF_AUTO_CAP = "auto_cap";
-    static final String PREF_TUTORIAL_RUN = "tutorial_run";
+    private static final String PREF_QUICK_FIXES = "quick_fixes";
+    private static final String PREF_SHOW_SUGGESTIONS = "show_suggestions";
+    private static final String PREF_AUTO_COMPLETE = "auto_complete";
 
     private static final int MSG_UPDATE_SUGGESTIONS = 0;
-    private static final int MSG_CHECK_TUTORIAL = 1;
+    private static final int MSG_START_TUTORIAL = 1;
     
     // How many continuous deletes at which to start deleting at a higher speed.
     private static final int DELETE_ACCELERATE_AT = 20;
@@ -93,7 +92,7 @@
     
     private AlertDialog mOptionsDialog;
     
-    private KeyboardSwitcher mKeyboardSwitcher;
+    KeyboardSwitcher mKeyboardSwitcher;
     
     private UserDictionary mUserDictionary;
     
@@ -106,20 +105,17 @@
     private CharSequence mBestWord;
     private boolean mPredictionOn;
     private boolean mCompletionOn;
-    private boolean mPasswordMode;
     private boolean mAutoSpace;
     private boolean mAutoCorrectOn;
     private boolean mCapsLock;
-    private long    mLastShiftTime;
     private boolean mVibrateOn;
     private boolean mSoundOn;
-    private boolean mProximityCorrection;
-    private int     mCorrectionMode;
     private boolean mAutoCap;
-    private boolean mAutoPunctuate;
-    private boolean mTutorialShownBefore;
+    private boolean mQuickFixes;
+    private boolean mShowSuggestions;
+    private boolean mAutoComplete;
+    private int     mCorrectionMode;
     // Indicates whether the suggestion strip is to be on in landscape
-    private boolean mShowSuggestInLand;
     private boolean mJustAccepted;
     private CharSequence mJustRevertedSeparator;
     private int mDeleteCount;
@@ -144,10 +140,15 @@
                 case MSG_UPDATE_SUGGESTIONS:
                     updateSuggestions();
                     break;
-                case MSG_CHECK_TUTORIAL:
-                    if (!mTutorialShownBefore) {
-                        mTutorial = new Tutorial(mInputView);
-                        mTutorial.start();
+                case MSG_START_TUTORIAL:
+                    if (mTutorial == null) {
+                        if (mInputView.isShown()) {
+                            mTutorial = new Tutorial(LatinIME.this, mInputView);
+                            mTutorial.start();
+                        } else {
+                            // Try again soon if the view is not yet showing
+                            sendMessageDelayed(obtainMessage(MSG_START_TUTORIAL), 100);
+                        }
                     }
                     break;
             }
@@ -188,10 +189,6 @@
         if (!TextUtils.equals(conf.locale.toString(), mLocale)) {
             initSuggest(conf.locale.toString());
         }
-        if (!mTutorialShownBefore && mTutorial != null) {
-            mTutorial.close(false);
-            mTutorial = null;
-        }
         super.onConfigurationChanged(conf);
     }
     
@@ -253,10 +250,7 @@
                 int variation = attribute.inputType &  EditorInfo.TYPE_MASK_VARIATION;
                 if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD ||
                         variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD ) {
-                    mPasswordMode = true;
                     mPredictionOn = false;
-                } else {
-                    mPasswordMode = false;
                 }
                 if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
                         || variation == EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME) {
@@ -296,39 +290,22 @@
         setCandidatesViewShown(false);
         if (mCandidateView != null) mCandidateView.setSuggestions(null, false, false, false);
         loadSettings();
-        mInputView.setProximityCorrectionEnabled(mProximityCorrection);
+        mInputView.setProximityCorrectionEnabled(true);
         if (mSuggest != null) {
             mSuggest.setCorrectionMode(mCorrectionMode);
         }
         mPredictionOn = mPredictionOn && mCorrectionMode > 0;
-        if (!mTutorialShownBefore && mTutorial == null) {
-            mHandler.sendEmptyMessageDelayed(MSG_CHECK_TUTORIAL, 
-                    mInputView.isShown() ? 100 : 3000);
-        }
+        checkTutorial(attribute.privateImeOptions);
         if (TRACE) Debug.startMethodTracing("latinime");
     }
 
     @Override
-    public void onWindowShown() {
-        super.onWindowShown();
-        // Bring the tutorial up faster, if window just shown
-        if (!mTutorialShownBefore && mTutorial == null) {
-            mHandler.removeMessages(MSG_CHECK_TUTORIAL);
-            mHandler.sendEmptyMessageDelayed(MSG_CHECK_TUTORIAL, 1000);
-        }
-    }
-    
-    @Override
     public void onFinishInput() {
         super.onFinishInput();
 
         if (mInputView != null) {
             mInputView.closing();
         }
-//        if (!mTutorialShownBefore && mTutorial != null) {
-//            mTutorial.close(false);
-//            mTutorial = null;
-//        }        
     }
 
     @Override
@@ -359,8 +336,12 @@
     @Override
     public void hideWindow() {
         if (TRACE) Debug.stopMethodTracing();
-        if (!mTutorialShownBefore && mTutorial != null) {
-            mTutorial.close(false);
+        if (mOptionsDialog != null && mOptionsDialog.isShowing()) {
+            mOptionsDialog.dismiss();
+            mOptionsDialog = null;
+        }
+        if (mTutorial != null) {
+            mTutorial.close();
             mTutorial = null;
         }
         super.hideWindow();
@@ -417,11 +398,21 @@
                 if (event.getRepeatCount() == 0 && mInputView != null) {
                     if (mInputView.handleBack()) {
                         return true;
-                    } else if (!mTutorialShownBefore && mTutorial != null) {
-                        mTutorial.close(true);
+                    } else if (mTutorial != null) {
+                        mTutorial.close();
+                        mTutorial = null;
                     }
                 }
                 break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_UP:
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                // If tutorial is visible, don't allow dpad to work
+                if (mTutorial != null) {
+                    return true;
+                }
+                break;
         }
         return super.onKeyDown(keyCode, event);
     }
@@ -433,6 +424,10 @@
             case KeyEvent.KEYCODE_DPAD_UP:
             case KeyEvent.KEYCODE_DPAD_LEFT:
             case KeyEvent.KEYCODE_DPAD_RIGHT:
+                // If tutorial is visible, don't allow dpad to work
+                if (mTutorial != null) {
+                    return true;
+                }
                 // Enable shift key and DPAD to do selections
                 if (mInputView != null && mInputView.isShown() && mInputView.isShifted()) {
                     event = new KeyEvent(event.getDownTime(), event.getEventTime(), 
@@ -596,9 +591,7 @@
                 ic.deleteSurroundingText(1, 0);
             }
         } else {
-            //getCurrentInputConnection().deleteSurroundingText(1, 0);
             deleteChar = true;
-            //sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
         }
         updateShiftKeyState(getCurrentInputEditorInfo());
         TextEntryState.backspace();
@@ -697,9 +690,6 @@
     
     private void handleClose() {
         commitTyped(getCurrentInputConnection());
-        if (!mTutorialShownBefore && mTutorial != null) {
-            mTutorial.close(true);
-        }
         requestHideSelf(0);
         mInputView.closing();
         TextEntryState.endSession();
@@ -730,11 +720,7 @@
     }
     
     private boolean isCandidateStripVisible() {
-        boolean visible = isPredictionOn() &&
-                (!isFullscreenMode() ||
-                 mCorrectionMode == Suggest.CORRECTION_FULL ||
-                 mShowSuggestInLand);
-        return visible;
+        return isPredictionOn() && mShowSuggestions;
     }
 
     private void updateSuggestions() {
@@ -901,14 +887,6 @@
                 mInputView.startPlaying(text.toString());
             }
         }
-//        if (mAutoCorrectOn) {
-//            commitTyped(getCurrentInputConnection());
-//        } else if (mPredicting) {
-//            pickDefaultSuggestion();
-//        }
-//        if (mAutoSpace) {
-//            sendSpace();
-//        }
     }
     
     public void swipeLeft() {
@@ -987,6 +965,27 @@
         mVibrator.vibrate(mVibrateDuration);
     }
 
+    private void checkTutorial(String privateImeOptions) {
+        if (privateImeOptions == null) return;
+        if (privateImeOptions.equals("com.android.setupwizard:ShowTutorial")) {
+            if (mTutorial == null) startTutorial();
+        } else if (privateImeOptions.equals("com.android.setupwizard:HideTutorial")) {
+            if (mTutorial != null) {
+                if (mTutorial.close()) {
+                    mTutorial = null;
+                }
+            }
+        }
+    }
+    
+    private void startTutorial() {
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_TUTORIAL), 500);
+    }
+
+    void tutorialDone() {
+        mTutorial = null;
+    }
+    
     private void launchSettings() {
         handleClose();
         Intent intent = new Intent();
@@ -998,24 +997,17 @@
     private void loadSettings() {
         // Get the settings preferences
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
-        mProximityCorrection = sp.getBoolean(PREF_PROXIMITY_CORRECTION, true);
         mVibrateOn = sp.getBoolean(PREF_VIBRATE_ON, false);
         mSoundOn = sp.getBoolean(PREF_SOUND_ON, false);
-        String predictionBasic = getString(R.string.prediction_basic);
-        String mode = sp.getString(PREF_PREDICTION, predictionBasic);
-        if (mode.equals(getString(R.string.prediction_full))) {
-            mCorrectionMode = 2;
-        } else if (mode.equals(predictionBasic)) {
-            mCorrectionMode = 1;
-        } else {
-            mCorrectionMode = 0;
-        }
-        mAutoCorrectOn = mSuggest != null && mCorrectionMode > 0;
-        
         mAutoCap = sp.getBoolean(PREF_AUTO_CAP, true);
-        //mAutoPunctuate = sp.getBoolean(PREF_AUTO_PUNCTUATE, mCorrectionMode > 0);
-        mShowSuggestInLand = !sp.getBoolean(PREF_PREDICTION_LANDSCAPE, false);
-        mTutorialShownBefore = sp.getBoolean(PREF_TUTORIAL_RUN, false);
+        mQuickFixes = sp.getBoolean(PREF_QUICK_FIXES, true);
+        // If there is no auto text data, then quickfix is forced to "on", so that the other options
+        // will continue to work
+        if (AutoText.getSize(mInputView) < 1) mQuickFixes = true;
+        mShowSuggestions = sp.getBoolean(PREF_SHOW_SUGGESTIONS, true) & mQuickFixes;
+        mAutoComplete = sp.getBoolean(PREF_AUTO_COMPLETE, true) & mShowSuggestions;
+        mAutoCorrectOn = mSuggest != null && (mAutoComplete || mQuickFixes);
+        mCorrectionMode = mAutoComplete ? 2 : (mQuickFixes ? 1 : 0);
     }
 
     private void showOptionsMenu() {
@@ -1079,11 +1071,7 @@
         p.println("  mSoundOn=" + mSoundOn);
         p.println("  mVibrateOn=" + mVibrateOn);
     }
-    
-    
-    private static final int[] KEY_SPACE = { KEYCODE_SPACE };
-    
-    
+
     // Characters per second measurement
     
     private static final boolean PERF_DEBUG = false;
diff --git a/src/com/android/inputmethod/latin/LatinIMESettings.java b/src/com/android/inputmethod/latin/LatinIMESettings.java
index 2c23263..e87c4a5 100644
--- a/src/com/android/inputmethod/latin/LatinIMESettings.java
+++ b/src/com/android/inputmethod/latin/LatinIMESettings.java
@@ -16,60 +16,38 @@
 
 package com.android.inputmethod.latin;
 
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.os.Bundle;
-import android.preference.ListPreference;
-import android.preference.Preference;
+import android.preference.CheckBoxPreference;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceGroup;
+import android.text.AutoText;
 
-public class LatinIMESettings extends PreferenceActivity 
-        implements OnSharedPreferenceChangeListener{
+public class LatinIMESettings extends PreferenceActivity {
     
-    private static final String CORRECTION_MODE_KEY = "prediction_mode";
+    private static final String QUICK_FIXES_KEY = "quick_fixes";
+    private static final String SHOW_SUGGESTIONS_KEY = "show_suggestions";
     private static final String PREDICTION_SETTINGS_KEY = "prediction_settings";
-    private static final String PREDICTION_LANDSCAPE_KEY = "prediction_landscape";
     
-    private ListPreference mCorrectionMode;
-    private PreferenceGroup mPredictionSettings;
-    private Preference mPredictionLandscape;
+    private CheckBoxPreference mQuickFixes;
+    private CheckBoxPreference mShowSuggestions;
     
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         addPreferencesFromResource(R.xml.prefs);
-        mCorrectionMode = (ListPreference) findPreference(CORRECTION_MODE_KEY);
-        mPredictionSettings = (PreferenceGroup) findPreference(PREDICTION_SETTINGS_KEY);
-        mPredictionLandscape = findPreference(PREDICTION_LANDSCAPE_KEY);
-        updatePredictionSettings();
-        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
-    }
-    
-    @Override
-    protected void onDestroy() {
-        getPreferenceScreen().getSharedPreferences()
-                .unregisterOnSharedPreferenceChangeListener(this);
-        super.onDestroy();
-    }
-    
-    private void updatePredictionSettings() {
-        if (mCorrectionMode != null && mPredictionSettings != null) {
-            String correctionMode = mCorrectionMode.getValue();
-            if (correctionMode.equals(getResources().getString(R.string.prediction_none))) {
-                mPredictionSettings.setEnabled(false);
-            } else {
-                mPredictionSettings.setEnabled(true);
-                boolean suggestionsInLandscape = 
-                    !correctionMode.equals(getResources().getString(R.string.prediction_full));
-                mPredictionLandscape.setEnabled(suggestionsInLandscape);
-            }
-        }
+        mQuickFixes = (CheckBoxPreference) findPreference(QUICK_FIXES_KEY);
+        mShowSuggestions = (CheckBoxPreference) findPreference(SHOW_SUGGESTIONS_KEY);
     }
 
-    public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
-        if (key.equals(CORRECTION_MODE_KEY)) {
-            updatePredictionSettings();
+    @Override
+    protected void onResume() {
+        super.onResume();
+        int autoTextSize = AutoText.getSize(getListView());
+        if (autoTextSize < 1) {
+            ((PreferenceGroup) findPreference(PREDICTION_SETTINGS_KEY))
+                .removePreference(mQuickFixes);
+        } else {
+            mShowSuggestions.setDependency(QUICK_FIXES_KEY);
         }
     }
 }
diff --git a/src/com/android/inputmethod/latin/Tutorial.java b/src/com/android/inputmethod/latin/Tutorial.java
index d944d17..750de05 100644
--- a/src/com/android/inputmethod/latin/Tutorial.java
+++ b/src/com/android/inputmethod/latin/Tutorial.java
@@ -17,38 +17,38 @@
 package com.android.inputmethod.latin;
 
 import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.opengl.Visibility;
 import android.os.Handler;
 import android.os.Message;
-import android.os.SystemClock;
-import android.preference.PreferenceManager;
 import android.text.Layout;
+import android.text.SpannableStringBuilder;
 import android.text.StaticLayout;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnTouchListener;
 import android.widget.PopupWindow;
 import android.widget.TextView;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class Tutorial {
+public class Tutorial implements OnTouchListener {
     
     private List<Bubble> mBubbles = new ArrayList<Bubble>();
     private long mStartTime;
     private static final long MINIMUM_TIME = 6000;
     private static final long MAXIMUM_TIME = 20000;
     private View mInputView;
+    private LatinIME mIme;
     private int[] mLocation = new int[2];
     private int mBubblePointerOffset;
     
     private static final int MSG_SHOW_BUBBLE = 0;
-    private static final int MSG_HIDE_ALL = 1;
+    
+    private int mBubbleIndex;
     
     Handler mHandler = new Handler() {
         @Override
@@ -58,8 +58,6 @@
                     Bubble bubba = (Bubble) msg.obj;
                     bubba.show(mLocation[0], mLocation[1]);
                     break;
-                case MSG_HIDE_ALL:
-                    close(true);
             }
         }
     };
@@ -70,7 +68,7 @@
         int y;
         int width;
         int gravity;
-        String text;
+        CharSequence text;
         boolean dismissOnTouch;
         boolean dismissOnClose;
         PopupWindow window;
@@ -78,16 +76,18 @@
         View inputView;
         
         Bubble(Context context, View inputView,
-                int backgroundResource, int bx, int by, int bw, int gravity, int textResource,
-                boolean dismissOnTouch, boolean dismissOnClose) {
+                int backgroundResource, int bx, int by, int textResource1, int textResource2) {
             bubbleBackground = context.getResources().getDrawable(backgroundResource);
-            x = bx; 
+            x = bx;
             y = by;
-            width = bw;
-            this.gravity = gravity;
-            text = context.getResources().getString(textResource);
-            this.dismissOnTouch = dismissOnTouch;
-            this.dismissOnClose = dismissOnClose;
+            width = (int) (inputView.getWidth() * 0.9);
+            this.gravity = Gravity.TOP | Gravity.LEFT;
+            text = new SpannableStringBuilder()
+                .append(context.getResources().getText(textResource1))
+                .append("\n") 
+                .append(context.getResources().getText(textResource2));
+            this.dismissOnTouch = true;
+            this.dismissOnClose = false;
             this.inputView = inputView;
             window = new PopupWindow(context);
             window.setBackgroundDrawable(null);
@@ -97,19 +97,20 @@
             textView = (TextView) inflate.inflate(R.layout.bubble_text, null);
             textView.setBackgroundDrawable(bubbleBackground);
             textView.setText(text);
+            //textView.setText(textResource1);
             window.setContentView(textView);
             window.setFocusable(false);
             window.setTouchable(true);
             window.setOutsideTouchable(false);
             textView.setOnTouchListener(new View.OnTouchListener() {
                 public boolean onTouch(View view, MotionEvent me) {
-                    Tutorial.this.touched();
+                    Tutorial.this.next();
                     return true;
                 }
             });
         }
 
-        private void chooseSize(PopupWindow pop, View parentView, CharSequence text, TextView tv) {
+        private int chooseSize(PopupWindow pop, View parentView, CharSequence text, TextView tv) {
             int wid = tv.getPaddingLeft() + tv.getPaddingRight();
             int ht = tv.getPaddingTop() + tv.getPaddingBottom();
 
@@ -131,10 +132,12 @@
              */
             pop.setWidth(width);
             pop.setHeight(ht + l.getHeight());
+            return l.getHeight();
         }
 
         void show(int offx, int offy) {
-            chooseSize(window, inputView, text, textView);
+            int textHeight = chooseSize(window, inputView, text, textView);
+            offy -= textView.getPaddingTop() + textHeight;
             if (inputView.getVisibility() == View.VISIBLE 
                     && inputView.getWindowVisibility() == View.VISIBLE) {
                 try {
@@ -155,72 +158,83 @@
         }
     }
     
-    public Tutorial(LatinKeyboardView inputView) {
+    public Tutorial(LatinIME ime, LatinKeyboardView inputView) {
         Context context = inputView.getContext();
-        int inputHeight = inputView.getHeight();
+        mIme = ime;
         int inputWidth = inputView.getWidth();
+        final int x = inputWidth / 20; // Half of 1/10th
         mBubblePointerOffset = inputView.getContext().getResources()
             .getDimensionPixelOffset(R.dimen.bubble_pointer_offset);
-        Bubble b0 = new Bubble(context, inputView, 
-                R.drawable.dialog_bubble_step02, 0, 0, 
-                inputWidth,
-                Gravity.BOTTOM | Gravity.LEFT,
-                R.string.tip_dismiss,
-                false, true);
-        mBubbles.add(b0);
-//        Bubble b1 = new Bubble(context, inputView, 
-//                R.drawable.dialog_bubble_step03, 
-//                (int) (inputWidth * 0.85) + mBubblePointerOffset, inputHeight / 5, 
-//                (int) (inputWidth * 0.45),
-//                Gravity.TOP | Gravity.RIGHT,
-//                R.string.tip_long_press,
-//                true, false);
-//        mBubbles.add(b1);
-//        Bubble b2 = new Bubble(inputView.getContext(), inputView, 
-//                R.drawable.dialog_bubble_step04, 
-//                inputWidth / 10 - mBubblePointerOffset, inputHeight - inputHeight / 5,
-//                (int) (inputWidth * 0.45),
-//                Gravity.BOTTOM | Gravity.LEFT,
-//                R.string.tip_access_symbols,
-//                true, false);
-//        mBubbles.add(b2);
+        Bubble bWelcome = new Bubble(context, inputView, 
+                R.drawable.dialog_bubble_step02, x, 0, 
+                R.string.tip_to_open_keyboard, R.string.touch_to_continue);
+        mBubbles.add(bWelcome);
+        Bubble bAccents = new Bubble(context, inputView, 
+                R.drawable.dialog_bubble_step02, x, 0, 
+                R.string.tip_to_view_accents, R.string.touch_to_continue);
+        mBubbles.add(bAccents);
+        Bubble b123 = new Bubble(context, inputView, 
+                R.drawable.dialog_bubble_step07, x, 0, 
+                R.string.tip_to_open_symbols, R.string.touch_to_continue);
+        mBubbles.add(b123);
+        Bubble bABC = new Bubble(context, inputView, 
+                R.drawable.dialog_bubble_step07, x, 0, 
+                R.string.tip_to_close_symbols, R.string.touch_to_continue);
+        mBubbles.add(bABC);
+        Bubble bSettings = new Bubble(context, inputView, 
+                R.drawable.dialog_bubble_step07, x, 0, 
+                R.string.tip_to_launch_settings, R.string.touch_to_continue);
+        mBubbles.add(bSettings);
+        Bubble bDone = new Bubble(context, inputView, 
+                R.drawable.dialog_bubble_step02, x, 0, 
+                R.string.tip_to_start_typing, R.string.touch_to_finish);
+        mBubbles.add(bDone);
         mInputView = inputView;
     }
     
     void start() {
         mInputView.getLocationInWindow(mLocation);
-        long delayMillis = 0;
-        for (int i = 0; i < mBubbles.size(); i++) {
-            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(i)), delayMillis);
-            delayMillis += 2000;
+        mBubbleIndex = -1;
+        mInputView.setOnTouchListener(this);
+        next();
+    }
+
+    boolean next() {
+        if (mBubbleIndex >= 0) {
+            mBubbles.get(mBubbleIndex).hide();
         }
-        //mHandler.sendEmptyMessageDelayed(MSG_HIDE_ALL, MAXIMUM_TIME);
-        mStartTime = SystemClock.uptimeMillis();
+        mBubbleIndex++;
+        if (mBubbleIndex >= mBubbles.size()) {
+            mInputView.setOnTouchListener(null);
+            mIme.sendDownUpKeyEvents(-1); // Inform the setupwizard that tutorial is in last bubble
+            mIme.tutorialDone();
+            return false;
+        }
+        if (mBubbleIndex == 3 || mBubbleIndex == 4) {
+            mIme.mKeyboardSwitcher.toggleSymbols();
+        }
+        mHandler.sendMessageDelayed(
+                mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(mBubbleIndex)), 200);
+        return true;
     }
     
-    void touched() {
-        if (SystemClock.uptimeMillis() - mStartTime < MINIMUM_TIME) {
-            return;
-        }
-        for (int i = 0; i < mBubbles.size(); i++) {
-            Bubble bubba = mBubbles.get(i);
-            if (bubba.dismissOnTouch) {
-                bubba.hide();
-            }
-        }
-    }
-    
-    void close(boolean completed) {
-        mHandler.removeMessages(MSG_SHOW_BUBBLE);
+    void hide() {
         for (int i = 0; i < mBubbles.size(); i++) {
             mBubbles.get(i).hide();
         }
-        if (completed) {
-            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
-                    mInputView.getContext());
-            Editor editor = sp.edit();
-            editor.putBoolean(LatinIME.PREF_TUTORIAL_RUN, true);
-            editor.commit();
+        mInputView.setOnTouchListener(null);
+    }
+
+    boolean close() {
+        mHandler.removeMessages(MSG_SHOW_BUBBLE);
+        hide();
+        return true;
+    }
+
+    public boolean onTouch(View v, MotionEvent event) {
+        if (event.getAction() == MotionEvent.ACTION_UP) {
+            next();
         }
+        return true;
     }
 }