[Autofill] Create new UI classes for the Autofill Dropdown on Android.

This code changes no behavior. It's simply in preparation for changing
the autofill dropdown in the next CLs.

Change-Id: I682c245d728c8bf3e8d5c57139b02e28a326111a
Reviewed-on: https://chromium-review.googlesource.com/1147428
Commit-Queue: Sebastien Seguin-Gagnon <sebsg@chromium.org>
Reviewed-by: Theresa <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#578332}
diff --git a/components/autofill/android/BUILD.gn b/components/autofill/android/BUILD.gn
index fea7272..cd72694 100644
--- a/components/autofill/android/BUILD.gn
+++ b/components/autofill/android/BUILD.gn
@@ -59,6 +59,7 @@
   resource_dirs = [ "java/res" ]
   deps = [
     ":autofill_strings_grd",
+    "//ui/android:ui_java_resources",
   ]
 }
 
@@ -78,6 +79,7 @@
   ]
   java_files = [
     "java/src/org/chromium/components/autofill/AutofillDelegate.java",
+    "java/src/org/chromium/components/autofill/AutofillDropdownAdapter.java",
     "java/src/org/chromium/components/autofill/AutofillPopup.java",
     "java/src/org/chromium/components/autofill/AutofillSuggestion.java",
   ]
diff --git a/components/autofill/android/java/res/layout/autofill_dropdown_item.xml b/components/autofill/android/java/res/layout/autofill_dropdown_item.xml
new file mode 100644
index 0000000..93512e2
--- /dev/null
+++ b/components/autofill/android/java/res/layout/autofill_dropdown_item.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 The Chromium Authors. All rights reserved.
+
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_vertical"
+    android:orientation="horizontal" >
+
+    <!-- These layout params are overwritten in DropdownAdapter.java -->
+    <ImageView
+        android:id="@+id/start_dropdown_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_margin="@dimen/autofill_dropdown_icon_margin"
+        tools:ignore="ContentDescription" />
+
+    <LinearLayout
+        android:id="@+id/dropdown_label_wrapper"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:gravity="center_vertical"
+        android:orientation="vertical" >
+
+        <TextView
+            android:id="@+id/dropdown_label"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="@dimen/autofill_dropdown_item_label_margin"
+            android:layout_marginStart="@dimen/autofill_dropdown_item_label_margin"
+            android:ellipsize="end"
+            android:includeFontPadding="false"
+            android:singleLine="true"
+            android:textAlignment="viewStart"
+            android:textAppearance="@style/BlackTitle1" />
+
+        <TextView
+            android:id="@+id/dropdown_sublabel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="@dimen/autofill_dropdown_item_label_margin"
+            android:layout_marginStart="@dimen/autofill_dropdown_item_label_margin"
+            android:ellipsize="end"
+            android:includeFontPadding="false"
+            android:singleLine="true"
+            android:textAlignment="viewStart"
+            android:textAppearance="@style/BlackCaption" />
+    </LinearLayout>
+
+    <ImageView
+        android:id="@+id/end_dropdown_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_margin="8dp"
+        tools:ignore="ContentDescription" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/components/autofill/android/java/res/values/dimens.xml b/components/autofill/android/java/res/values/dimens.xml
index 1327d16e..a7224ad 100644
--- a/components/autofill/android/java/res/values/dimens.xml
+++ b/components/autofill/android/java/res/values/dimens.xml
@@ -5,4 +5,8 @@
      found in the LICENSE file.
 -->
 <resources>
+    <dimen name="autofill_dropdown_item_height">50dp</dimen>
+    <dimen name="autofill_dropdown_item_divider_height">1px</dimen>
+    <dimen name="autofill_dropdown_item_label_margin">10dp</dimen>
+    <dimen name="autofill_dropdown_icon_margin">8dp</dimen>
 </resources>
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillDropdownAdapter.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillDropdownAdapter.java
new file mode 100644
index 0000000..42fc54c
--- /dev/null
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillDropdownAdapter.java
@@ -0,0 +1,190 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.autofill;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.support.v4.view.MarginLayoutParamsCompat;
+import android.support.v4.view.ViewCompat;
+import android.support.v7.content.res.AppCompatResources;
+import android.text.TextUtils;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView.LayoutParams;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.ui.DropdownDividerDrawable;
+import org.chromium.ui.DropdownItem;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Dropdown item adapter for the AutofillPopup.
+ */
+public class AutofillDropdownAdapter extends ArrayAdapter<DropdownItem> {
+    private final Context mContext;
+    private final Set<Integer> mSeparators;
+    private final boolean mAreAllItemsEnabled;
+    private final int mLabelMargin;
+
+    /**
+     * Creates an {@code ArrayAdapter} with specified parameters.
+     * @param context Application context.
+     * @param items List of labels and icons to display.
+     * @param separators Set of positions that separate {@code items}.
+     */
+    public AutofillDropdownAdapter(
+            Context context, List<? extends DropdownItem> items, Set<Integer> separators) {
+        super(context, R.layout.autofill_dropdown_item);
+        mContext = context;
+        addAll(items);
+        mSeparators = separators;
+        mAreAllItemsEnabled = checkAreAllItemsEnabled();
+        mLabelMargin = context.getResources().getDimensionPixelSize(
+                R.dimen.autofill_dropdown_item_label_margin);
+    }
+
+    private boolean checkAreAllItemsEnabled() {
+        for (int i = 0; i < getCount(); i++) {
+            DropdownItem item = getItem(i);
+            if (item.isEnabled() && !item.isGroupHeader()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        View layout = convertView;
+        if (convertView == null) {
+            LayoutInflater inflater = LayoutInflater.from(mContext);
+            layout = inflater.inflate(R.layout.autofill_dropdown_item, null);
+            layout.setBackground(new DropdownDividerDrawable(/*backgroundColor=*/null));
+        }
+        DropdownDividerDrawable divider = (DropdownDividerDrawable) layout.getBackground();
+        int height = mContext.getResources().getDimensionPixelSize(
+                R.dimen.autofill_dropdown_item_height);
+
+        if (position == 0) {
+            divider.setDividerColor(Color.TRANSPARENT);
+        } else {
+            int dividerHeight = mContext.getResources().getDimensionPixelSize(
+                    R.dimen.autofill_dropdown_item_divider_height);
+            height += dividerHeight;
+            divider.setHeight(dividerHeight);
+            int dividerColor;
+            if (mSeparators != null && mSeparators.contains(position)) {
+                dividerColor = ApiCompatibilityUtils.getColor(
+                        mContext.getResources(), R.color.dropdown_dark_divider_color);
+            } else {
+                dividerColor = ApiCompatibilityUtils.getColor(
+                        mContext.getResources(), R.color.dropdown_divider_color);
+            }
+            divider.setDividerColor(dividerColor);
+        }
+
+        DropdownItem item = getItem(position);
+
+        // Note: trying to set the height of the root LinearLayout breaks accessibility,
+        // so we have to adjust the height of this LinearLayout that wraps the TextViews instead.
+        // If you need to modify this layout, don't forget to test it with TalkBack and make sure
+        // it doesn't regress.
+        // http://crbug.com/429364
+        LinearLayout wrapper = (LinearLayout) layout.findViewById(R.id.dropdown_label_wrapper);
+        if (item.isMultilineLabel()) height = LayoutParams.WRAP_CONTENT;
+        wrapper.setOrientation(LinearLayout.VERTICAL);
+        wrapper.setLayoutParams(new LinearLayout.LayoutParams(0, height, 1));
+
+        // Layout of the main label view.
+        TextView labelView = (TextView) layout.findViewById(R.id.dropdown_label);
+        labelView.setText(item.getLabel());
+        labelView.setSingleLine(!item.isMultilineLabel());
+        if (item.isMultilineLabel()) {
+            // If there is a multiline label, we add extra padding at the top and bottom because
+            // WRAP_CONTENT, defined above for multiline labels, leaves none.
+            int existingStart = ViewCompat.getPaddingStart(labelView);
+            int existingEnd = ViewCompat.getPaddingEnd(labelView);
+            ViewCompat.setPaddingRelative(
+                    labelView, existingStart, mLabelMargin, existingEnd, mLabelMargin);
+        }
+
+        labelView.setEnabled(item.isEnabled());
+        if (item.isGroupHeader() || item.isBoldLabel()) {
+            labelView.setTypeface(null, Typeface.BOLD);
+        } else {
+            labelView.setTypeface(null, Typeface.NORMAL);
+        }
+
+        labelView.setTextColor(ApiCompatibilityUtils.getColor(
+                mContext.getResources(), item.getLabelFontColorResId()));
+        labelView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                mContext.getResources().getDimension(R.dimen.text_size_large));
+
+        // Layout of the sublabel view, which has a smaller font and usually sits below the main
+        // label.
+        TextView sublabelView = (TextView) layout.findViewById(R.id.dropdown_sublabel);
+        CharSequence sublabel = item.getSublabel();
+        if (TextUtils.isEmpty(sublabel)) {
+            sublabelView.setVisibility(View.GONE);
+        } else {
+            sublabelView.setText(sublabel);
+            sublabelView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                    mContext.getResources().getDimension(item.getSublabelFontSizeResId()));
+            sublabelView.setVisibility(View.VISIBLE);
+        }
+
+        ImageView iconViewStart = (ImageView) layout.findViewById(R.id.start_dropdown_icon);
+        ImageView iconViewEnd = (ImageView) layout.findViewById(R.id.end_dropdown_icon);
+        if (item.isIconAtStart()) {
+            iconViewEnd.setVisibility(View.GONE);
+        } else {
+            iconViewStart.setVisibility(View.GONE);
+        }
+
+        ImageView iconView = item.isIconAtStart() ? iconViewStart : iconViewEnd;
+        if (item.getIconId() == DropdownItem.NO_ICON) {
+            iconView.setVisibility(View.GONE);
+        } else {
+            int iconSizeResId = item.getIconSizeResId();
+            int iconSize = iconSizeResId == 0
+                    ? LayoutParams.WRAP_CONTENT
+                    : mContext.getResources().getDimensionPixelSize(iconSizeResId);
+            ViewGroup.MarginLayoutParams iconLayoutParams =
+                    (ViewGroup.MarginLayoutParams) iconView.getLayoutParams();
+            iconLayoutParams.width = iconSize;
+            iconLayoutParams.height = iconSize;
+            int iconMargin =
+                    mContext.getResources().getDimensionPixelSize(item.getIconMarginResId());
+            MarginLayoutParamsCompat.setMarginStart(iconLayoutParams, iconMargin);
+            MarginLayoutParamsCompat.setMarginEnd(iconLayoutParams, iconMargin);
+            iconView.setLayoutParams(iconLayoutParams);
+            iconView.setImageDrawable(AppCompatResources.getDrawable(mContext, item.getIconId()));
+            iconView.setVisibility(View.VISIBLE);
+        }
+
+        return layout;
+    }
+
+    @Override
+    public boolean areAllItemsEnabled() {
+        return mAreAllItemsEnabled;
+    }
+
+    @Override
+    public boolean isEnabled(int position) {
+        if (position < 0 || position >= getCount()) return false;
+        DropdownItem item = getItem(position);
+        return item.isEnabled() && !item.isGroupHeader();
+    }
+}
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillPopup.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillPopup.java
index 914e6fb5..891731c 100644
--- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillPopup.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillPopup.java
@@ -13,7 +13,6 @@
 import android.widget.AdapterView;
 import android.widget.PopupWindow;
 
-import org.chromium.ui.DropdownAdapter;
 import org.chromium.ui.DropdownItem;
 import org.chromium.ui.DropdownPopupWindow;
 
@@ -86,7 +85,7 @@
             }
         }
 
-        setAdapter(new DropdownAdapter(mContext, cleanedData, separators));
+        setAdapter(new AutofillDropdownAdapter(mContext, cleanedData, separators));
         setRtl(isRtl);
         show();
         getListView().setOnItemLongClickListener(this);
@@ -107,7 +106,7 @@
 
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        DropdownAdapter adapter = (DropdownAdapter) parent.getAdapter();
+        AutofillDropdownAdapter adapter = (AutofillDropdownAdapter) parent.getAdapter();
         int listIndex = mSuggestions.indexOf(adapter.getItem(position));
         assert listIndex > -1;
         mAutofillDelegate.suggestionSelected(listIndex);
@@ -115,7 +114,7 @@
 
     @Override
     public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
-        DropdownAdapter adapter = (DropdownAdapter) parent.getAdapter();
+        AutofillDropdownAdapter adapter = (AutofillDropdownAdapter) parent.getAdapter();
         AutofillSuggestion suggestion = (AutofillSuggestion) adapter.getItem(position);
         if (!suggestion.isDeletable()) return false;
 
diff --git a/ui/android/java/src/org/chromium/ui/DropdownDividerDrawable.java b/ui/android/java/src/org/chromium/ui/DropdownDividerDrawable.java
index 1b45064f..8a6f4782 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownDividerDrawable.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownDividerDrawable.java
@@ -11,8 +11,10 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 
-class DropdownDividerDrawable extends Drawable {
-
+/**
+ * A drawable divider to be used by dropdown adapters.
+ */
+public class DropdownDividerDrawable extends Drawable {
     private final Paint mPaint;
     private final Rect mDividerRect;
     private final Integer mBackgroundColor;