Display suggested word info in debug mode

Bug: 4686782
Change-Id: I0e5bef33aa39c3d6f75edda7818524965aa40b79
diff --git a/java/res/layout/candidate_info.xml b/java/res/layout/candidate_info.xml
new file mode 100644
index 0000000..f355728
--- /dev/null
+++ b/java/res/layout/candidate_info.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, 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.
+*/
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:textSize="6sp"
+    android:textColor="@android:color/white"
+    android:visibility="gone"
+    style="?attr/suggestionBackgroundStyle" />
diff --git a/java/res/layout/candidate.xml b/java/res/layout/candidate_word.xml
similarity index 100%
rename from java/res/layout/candidate.xml
rename to java/res/layout/candidate_word.xml
diff --git a/java/res/layout/candidates_strip.xml b/java/res/layout/candidates_strip.xml
index 88f4c38..c23c29c 100644
--- a/java/res/layout/candidates_strip.xml
+++ b/java/res/layout/candidates_strip.xml
@@ -22,14 +22,34 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <include
-        android:id="@+id/candidate_left"
-        layout="@layout/candidate" />
+    <RelativeLayout
+        android:layout_weight="1.0"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:gravity="center"
+    >
+        <include
+            android:id="@+id/word_left"
+            layout="@layout/candidate_word" />
+        <include
+            android:id="@+id/info_left"
+            layout="@layout/candidate_info" />
+    </RelativeLayout>
     <include
         layout="@layout/candidate_divider" />
-    <include
-        android:id="@+id/candidate_center"
-        layout="@layout/candidate" />
+    <RelativeLayout
+        android:layout_weight="1.0"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:gravity="center"
+    >
+        <include
+            android:id="@+id/word_center"
+            layout="@layout/candidate_word" />
+        <include
+            android:id="@+id/info_center"
+            layout="@layout/candidate_info" />
+    </RelativeLayout>
     <include
         layout="@layout/candidate_divider" />
     <LinearLayout
@@ -39,9 +59,19 @@
         android:layout_height="wrap_content"
         android:gravity="center_vertical"
     >
-        <include
-            android:id="@+id/candidate_right"
-            layout="@layout/candidate" />
+        <RelativeLayout
+            android:layout_weight="1.0"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:gravity="center"
+        >
+            <include
+                android:id="@+id/word_right"
+                layout="@layout/candidate_word" />
+            <include
+                android:id="@+id/info_right"
+                layout="@layout/candidate_info" />
+        </RelativeLayout>
         <!-- Image drawables are set in CandidateView constructor -->
         <ImageButton
             android:id="@+id/expand_candidates_pane"
diff --git a/java/src/com/android/inputmethod/compat/FrameLayoutCompatUtils.java b/java/src/com/android/inputmethod/compat/FrameLayoutCompatUtils.java
index 46499f1..523bf7d 100644
--- a/java/src/com/android/inputmethod/compat/FrameLayoutCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/FrameLayoutCompatUtils.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.compat;
 
+import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup.MarginLayoutParams;
 import android.widget.FrameLayout;
@@ -49,4 +50,14 @@
                     + placer.getClass().getName());
         }
     }
+
+    public static void placeViewAt(View view, int x, int y, int w, int h) {
+        final ViewGroup.LayoutParams lp = view.getLayoutParams();
+        if (lp instanceof MarginLayoutParams) {
+            final MarginLayoutParams marginLayoutParams = (MarginLayoutParams)lp;
+            marginLayoutParams.width = w;
+            marginLayoutParams.height = h;
+            marginLayoutParams.setMargins(x, y, 0, 0);
+        }
+    }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 3d62303..8d4bfd7 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -41,7 +41,6 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
-import android.view.ViewGroup.MarginLayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.PopupWindow;
 import android.widget.TextView;
@@ -998,10 +997,8 @@
 
         // Place the key preview.
         // TODO: Adjust position of key previews which touch screen edges
-        final MarginLayoutParams lp = (MarginLayoutParams)previewText.getLayoutParams();
-        lp.width = previewWidth;
-        lp.height = previewHeight;
-        lp.setMargins(previewX, previewY, 0, 0);
+        FrameLayoutCompatUtils.placeViewAt(
+                previewText, previewX, previewY, previewWidth, previewHeight);
         previewText.setVisibility(VISIBLE);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index 09b356d..09fd3b4 100644
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -74,6 +74,7 @@
     private ViewGroup mCandidatesPaneContainer;
     private View mKeyboardView;
     private final ArrayList<TextView> mWords = new ArrayList<TextView>();
+    private final ArrayList<TextView> mInfos = new ArrayList<TextView>();
     private final ArrayList<View> mDividers = new ArrayList<View>();
     private final int mCandidatePadding;
     private final int mCandidateStripHeight;
@@ -177,29 +178,32 @@
         mCandidatePadding = res.getDimensionPixelOffset(R.dimen.candidate_padding);
         mCandidateStripHeight = res.getDimensionPixelOffset(R.dimen.candidate_strip_height);
         for (int i = 0; i < MAX_SUGGESTIONS; i++) {
-            final TextView tv;
+            final TextView word, info;
             switch (i) {
             case 0:
-                tv = (TextView)findViewById(R.id.candidate_left);
-                tv.setPadding(mCandidatePadding, 0, 0, 0);
+                word = (TextView)findViewById(R.id.word_left);
+                word.setPadding(mCandidatePadding, 0, 0, 0);
+                info = (TextView)findViewById(R.id.info_left);
                 break;
             case 1:
-                tv = (TextView)findViewById(R.id.candidate_center);
+                word = (TextView)findViewById(R.id.word_center);
+                info = (TextView)findViewById(R.id.info_center);
                 break;
             case 2:
-                tv = (TextView)findViewById(R.id.candidate_right);
+                word = (TextView)findViewById(R.id.word_right);
+                info = (TextView)findViewById(R.id.info_right);
                 break;
             default:
-                tv = (TextView)inflater.inflate(R.layout.candidate, null);
+                word = (TextView)inflater.inflate(R.layout.candidate_word, null);
+                info = (TextView)inflater.inflate(R.layout.candidate_info, null);
                 break;
             }
-            if (i < NUM_CANDIDATES_IN_STRIP)
-                setLayoutWeight(tv, 1.0f);
-            tv.setTag(i);
-            tv.setOnClickListener(this);
+            word.setTag(i);
+            word.setOnClickListener(this);
             if (i == 0)
-                tv.setOnLongClickListener(this);
-            mWords.add(tv);
+                word.setOnLongClickListener(this);
+            mWords.add(word);
+            mInfos.add(info);
             if (i > 0) {
                 final View divider = inflater.inflate(R.layout.candidate_divider, null);
                 divider.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC);
@@ -263,15 +267,6 @@
         }
     }
 
-    private static void setLayoutWeight(View v, float weight) {
-        ViewGroup.LayoutParams lp = v.getLayoutParams();
-        if (lp instanceof LinearLayout.LayoutParams) {
-            LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp;
-            llp.width = 0;
-            llp.weight = weight;
-        }
-    }
-
     private CharSequence getStyledCandidateWord(CharSequence word, boolean isAutoCorrect) {
         if (!isAutoCorrect)
             return word;
@@ -308,6 +303,7 @@
         clear();
         final int paneWidth = getWidth();
         final int dividerWidth = mDividers.get(0).getMeasuredWidth();
+        final int dividerHeight = mDividers.get(0).getMeasuredHeight();
         int x = 0;
         int y = 0;
         int fromIndex = NUM_CANDIDATES_IN_STRIP;
@@ -315,10 +311,10 @@
         closeCandidatesPane();
         mExpandCandidatesPane.setEnabled(count >= NUM_CANDIDATES_IN_STRIP);
         for (int i = 0; i < count; i++) {
-            final CharSequence word = suggestions.getWord(i);
-            if (word == null) continue;
+            final CharSequence suggestion = suggestions.getWord(i);
+            if (suggestion == null) continue;
 
-            final SuggestedWordInfo info = (suggestedWordInfoList != null)
+            final SuggestedWordInfo suggestionInfo = (suggestedWordInfoList != null)
                     ? suggestedWordInfoList.get(i) : null;
             final boolean isAutoCorrect = suggestions.mHasMinimalSuggestion
                     && ((i == 1 && !suggestions.mTypedWordValid)
@@ -327,18 +323,37 @@
             // and there are multiple suggestions, such as the default punctuation list.
             // TODO: Need to revisit this logic with bigram suggestions
             final boolean isSuggestedCandidate = (i != 0);
-            final boolean isPunctuationSuggestions = (word.length() == 1 && count > 1);
+            final boolean isPunctuationSuggestions = (suggestion.length() == 1 && count > 1);
 
-            final TextView tv = mWords.get(i);
+            final TextView word = mWords.get(i);
             // TODO: Reorder candidates in strip as appropriate. The center candidate should hold
             // the word when space is typed (valid typed word or auto corrected word).
-            tv.setTextColor(getCandidateTextColor(isAutoCorrect,
-                    isSuggestedCandidate || isPunctuationSuggestions, info));
-            tv.setText(getStyledCandidateWord(word, isAutoCorrect));
+            word.setTextColor(getCandidateTextColor(isAutoCorrect,
+                    isSuggestedCandidate || isPunctuationSuggestions, suggestionInfo));
+            word.setText(getStyledCandidateWord(suggestion, isAutoCorrect));
             // TODO: call TextView.setTextScaleX() to fit the candidate in single line.
-            if (i >= NUM_CANDIDATES_IN_STRIP) {
-                tv.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC);
-                final int width = tv.getMeasuredWidth();
+            word.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC);
+            final int width = word.getMeasuredWidth();
+            final int height = word.getMeasuredHeight();
+
+            final TextView info;
+            if (DBG && suggestionInfo != null
+                    && !TextUtils.isEmpty(suggestionInfo.getDebugString())) {
+                info = mInfos.get(i);
+                info.setText(suggestionInfo.getDebugString());
+                info.setVisibility(View.VISIBLE);
+                info.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC);
+            } else {
+                info = null;
+            }
+
+            if (i < NUM_CANDIDATES_IN_STRIP) {
+                if (info != null) {
+                    final int infoWidth = info.getMeasuredWidth();
+                    FrameLayoutCompatUtils.placeViewAt(
+                            info, x + width - infoWidth, y, infoWidth, info.getMeasuredHeight());
+                }
+            } else {
                 // TODO: Handle overflow case.
                 if (dividerWidth + x + width >= paneWidth) {
                     centeringCandidates(fromIndex, i - 1, x, paneWidth);
@@ -348,23 +363,23 @@
                 }
                 if (x != 0) {
                     final View divider = mDividers.get(i - NUM_CANDIDATES_IN_STRIP);
-                    addCandidateAt(divider, x, y);
+                    mCandidatesPane.addView(divider);
+                    FrameLayoutCompatUtils.placeViewAt(
+                            divider, x, y + (mCandidateStripHeight - dividerHeight) / 2,
+                            dividerWidth, dividerHeight);
                     x += dividerWidth;
                 }
-                addCandidateAt(tv, x, y);
+                mCandidatesPane.addView(word);
+                FrameLayoutCompatUtils.placeViewAt(
+                        word, x, y + (mCandidateStripHeight - height) / 2, width, height);
+                if (info != null) {
+                    mCandidatesPane.addView(info);
+                    final int infoWidth = info.getMeasuredWidth();
+                    FrameLayoutCompatUtils.placeViewAt(
+                            info, x + width - infoWidth, y, infoWidth, info.getMeasuredHeight());
+                }
                 x += width;
             }
-
-            if (DBG && info != null) {
-                final TextView dv = new TextView(getContext(), null);
-                dv.setTextSize(10.0f);
-                dv.setTextColor(0xff808080);
-                dv.setText(info.getDebugString());
-                // TODO: debug view for candidate strip needed.
-//                mCandidatesPane.addView(dv);
-//                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)dv.getLayoutParams();
-//                lp.gravity = Gravity.BOTTOM;
-            }
         }
         if (x != 0) {
             // Centering last candidates row.
@@ -372,19 +387,15 @@
         }
     }
 
-    private void addCandidateAt(View v, int x, int y) {
-        final int width = v.getMeasuredWidth();
-        final int height = v.getMeasuredHeight();
-        final MarginLayoutParams marginLayoutParams = FrameLayoutCompatUtils.newLayoutParam(
-                mCandidatesPane, width, height);
-        marginLayoutParams.setMargins(x, y + (mCandidateStripHeight - height) / 2, 0, 0);
-        mCandidatesPane.addView(v, marginLayoutParams);
-    }
-
     private void centeringCandidates(int from, int to, int width, int paneWidth) {
         final ViewGroup pane = mCandidatesPane;
         final int fromIndex = pane.indexOfChild(mWords.get(from));
-        final int toIndex = pane.indexOfChild(mWords.get(to));
+        final int toIndex;
+        if (mInfos.get(to).getParent() != null) {
+            toIndex = pane.indexOfChild(mInfos.get(to));
+        } else {
+            toIndex = pane.indexOfChild(mWords.get(to));
+        }
         final int offset = (paneWidth - width) / 2;
         for (int index = fromIndex; index <= toIndex; index++) {
             offsetMargin(pane.getChildAt(index), offset, 0);
@@ -394,9 +405,9 @@
     private static void offsetMargin(View v, int dx, int dy) {
         if (v == null)
             return;
-        ViewGroup.LayoutParams lp = v.getLayoutParams();
+        final ViewGroup.LayoutParams lp = v.getLayoutParams();
         if (lp instanceof ViewGroup.MarginLayoutParams) {
-            ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp;
+            final ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp;
             mlp.setMargins(mlp.leftMargin + dx, mlp.topMargin + dy, 0, 0);
         }
     }
@@ -458,8 +469,10 @@
     public void clear() {
         mShowingAddToDictionary = false;
         mShowingAutoCorrectionInverted = false;
-        for (int i = 0; i < NUM_CANDIDATES_IN_STRIP; i++)
+        for (int i = 0; i < NUM_CANDIDATES_IN_STRIP; i++) {
             mWords.get(i).setText(null);
+            mInfos.get(i).setVisibility(View.GONE);
+        }
         mCandidatesPane.removeAllViews();
     }