| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package org.chromium.chrome.browser.autofill; | |
| 6 | |
| 7 import android.content.Context; | |
| 8 import android.graphics.Paint; | |
| 9 import android.graphics.Rect; | |
| 10 import android.text.TextUtils; | |
| 11 import android.view.LayoutInflater; | |
| 12 import android.view.View; | |
| 13 import android.view.View.OnLayoutChangeListener; | |
| 14 import android.widget.AdapterView; | |
| 15 import android.widget.ListPopupWindow; | |
| 16 import android.widget.TextView; | |
| 17 | |
| 18 import java.util.ArrayList; | |
| 19 | |
| 20 import org.chromium.chrome.R; | |
| 21 import org.chromium.ui.ViewAndroidDelegate; | |
| 22 | |
| 23 /** | |
| 24 * The Autofill suggestion popup that lists relevant suggestions. | |
| 25 */ | |
| 26 public class AutofillPopup extends ListPopupWindow implements AdapterView.OnItem
ClickListener { | |
| 27 | |
| 28 /** | |
| 29 * Constants defining types of Autofill suggestion entries. | |
| 30 * Has to be kept in sync with enum in WebAutofillClient.h | |
| 31 * | |
| 32 * Not supported: MenuItemIDWarningMessage, MenuItemIDSeparator, MenuItemIDC
learForm, and | |
| 33 * MenuItemIDAutofillOptions. | |
| 34 */ | |
| 35 private static final int ITEM_ID_AUTOCOMPLETE_ENTRY = 0; | |
| 36 private static final int ITEM_ID_PASSWORD_ENTRY = -2; | |
| 37 private static final int ITEM_ID_DATA_LIST_ENTRY = -6; | |
| 38 | |
| 39 private static final int TEXT_PADDING_DP = 30; | |
| 40 | |
| 41 private final AutofillPopupDelegate mAutofillCallback; | |
| 42 private final Context mContext; | |
| 43 private final ViewAndroidDelegate mViewAndroidDelegate; | |
| 44 private View mAnchorView; | |
| 45 private float mAnchorWidth; | |
| 46 private float mAnchorHeight; | |
| 47 private float mAnchorX; | |
| 48 private float mAnchorY; | |
| 49 private Paint mLabelViewPaint; | |
| 50 private Paint mSublabelViewPaint; | |
| 51 private OnLayoutChangeListener mLayoutChangeListener; | |
| 52 | |
| 53 /** | |
| 54 * An interface to handle the touch interaction with an AutofillPopup object
. | |
| 55 */ | |
| 56 public interface AutofillPopupDelegate { | |
| 57 /** | |
| 58 * Requests the controller to hide AutofillPopup. | |
| 59 */ | |
| 60 public void requestHide(); | |
| 61 | |
| 62 /** | |
| 63 * Handles the selection of an Autofill suggestion from an AutofillPopup
. | |
| 64 * @param listIndex The index of the selected Autofill suggestion. | |
| 65 */ | |
| 66 public void suggestionSelected(int listIndex); | |
| 67 } | |
| 68 | |
| 69 /** | |
| 70 * Creates an AutofillWindow with specified parameters. | |
| 71 * @param context Application context. | |
| 72 * @param viewAndroidDelegate View delegate used to add and remove views. | |
| 73 * @param autofillCallback A object that handles the calls to the native Aut
ofillPopupView. | |
| 74 */ | |
| 75 public AutofillPopup(Context context, ViewAndroidDelegate viewAndroidDelegat
e, | |
| 76 AutofillPopupDelegate autofillCallback) { | |
| 77 super(context, null, 0, R.style.AutofillPopupWindow); | |
| 78 mContext = context; | |
| 79 mViewAndroidDelegate = viewAndroidDelegate ; | |
| 80 mAutofillCallback = autofillCallback; | |
| 81 | |
| 82 setOnItemClickListener(this); | |
| 83 | |
| 84 mAnchorView = mViewAndroidDelegate.acquireAnchorView(); | |
| 85 mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAncho
rY, mAnchorWidth, | |
| 86 mAnchorHeight); | |
| 87 | |
| 88 mLayoutChangeListener = new OnLayoutChangeListener() { | |
| 89 @Override | |
| 90 public void onLayoutChange(View v, int left, int top, int right, int
bottom, | |
| 91 int oldLeft, int oldTop, int oldRight, int oldBottom) { | |
| 92 if (v == mAnchorView) AutofillPopup.this.show(); | |
| 93 } | |
| 94 }; | |
| 95 | |
| 96 mAnchorView.addOnLayoutChangeListener(mLayoutChangeListener); | |
| 97 setAnchorView(mAnchorView); | |
| 98 } | |
| 99 | |
| 100 @Override | |
| 101 public void show() { | |
| 102 // An ugly hack to keep the popup from expanding on top of the keyboard. | |
| 103 setInputMethodMode(INPUT_METHOD_NEEDED); | |
| 104 super.show(); | |
| 105 } | |
| 106 | |
| 107 /** | |
| 108 * Sets the location and the size of the anchor view that the AutofillPopup
will use to attach | |
| 109 * itself. | |
| 110 * @param x X coordinate of the top left corner of the anchor view. | |
| 111 * @param y Y coordinate of the top left corner of the anchor view. | |
| 112 * @param width The width of the anchor view. | |
| 113 * @param height The height of the anchor view. | |
| 114 */ | |
| 115 public void setAnchorRect(float x, float y, float width, float height) { | |
| 116 mAnchorWidth = width; | |
| 117 mAnchorHeight = height; | |
| 118 mAnchorX = x; | |
| 119 mAnchorY = y; | |
| 120 if (mAnchorView != null) { | |
| 121 mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mA
nchorY, | |
| 122 mAnchorWidth, mAnchorHeight); | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 /** | |
| 127 * Sets the Autofill suggestions to display in the popup and shows the popup
. | |
| 128 * @param suggestions Autofill suggestion data. | |
| 129 */ | |
| 130 public void show(AutofillSuggestion[] suggestions) { | |
| 131 // Remove the AutofillSuggestions with IDs that are not supported by And
roid | |
| 132 ArrayList<AutofillSuggestion> cleanedData = new ArrayList<AutofillSugges
tion>(); | |
| 133 for (int i = 0; i < suggestions.length; i++) { | |
| 134 int itemId = suggestions[i].mUniqueId; | |
| 135 if (itemId > 0 || itemId == ITEM_ID_AUTOCOMPLETE_ENTRY || | |
| 136 itemId == ITEM_ID_PASSWORD_ENTRY || itemId == ITEM_ID_DATA_L
IST_ENTRY) { | |
| 137 cleanedData.add(suggestions[i]); | |
| 138 } | |
| 139 } | |
| 140 setAdapter(new AutofillListAdapter(mContext, cleanedData)); | |
| 141 // Once the mAnchorRect is resized and placed correctly, it will show th
e Autofill popup. | |
| 142 mAnchorWidth = Math.max(getDesiredWidth(cleanedData), mAnchorWidth); | |
| 143 | |
| 144 mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAncho
rY, mAnchorWidth, | |
| 145 mAnchorHeight); | |
| 146 } | |
| 147 | |
| 148 /** | |
| 149 * Overrides the default dismiss behavior to request the controller to dismi
ss the view. | |
| 150 */ | |
| 151 @Override | |
| 152 public void dismiss() { | |
| 153 mAutofillCallback.requestHide(); | |
| 154 } | |
| 155 | |
| 156 /** | |
| 157 * Hides the popup and removes the anchor view from the ContainerView. | |
| 158 */ | |
| 159 public void hide() { | |
| 160 super.dismiss(); | |
| 161 mAnchorView.removeOnLayoutChangeListener(mLayoutChangeListener); | |
| 162 mViewAndroidDelegate.releaseAnchorView(mAnchorView); | |
| 163 } | |
| 164 | |
| 165 /** | |
| 166 * Get desired popup window width by calculating the maximum text length fro
m Autofill data. | |
| 167 * @param data Autofill suggestion data. | |
| 168 * @return The popup window width in DIP. | |
| 169 */ | |
| 170 private float getDesiredWidth(ArrayList<AutofillSuggestion> data) { | |
| 171 if (mLabelViewPaint == null || mSublabelViewPaint == null) { | |
| 172 LayoutInflater inflater = | |
| 173 (LayoutInflater) mContext.getSystemService(Context.LAYOUT_IN
FLATER_SERVICE); | |
| 174 View layout = inflater.inflate(R.layout.autofill_text, null); | |
| 175 TextView labelView = (TextView) layout.findViewById(R.id.autofill_la
bel); | |
| 176 mLabelViewPaint = labelView.getPaint(); | |
| 177 TextView sublabelView = (TextView) layout.findViewById(R.id.autofill
_sublabel); | |
| 178 mSublabelViewPaint = sublabelView.getPaint(); | |
| 179 } | |
| 180 | |
| 181 float maxTextWidth = 0; | |
| 182 Rect bounds = new Rect(); | |
| 183 for (int i = 0; i < data.size(); ++i) { | |
| 184 bounds.setEmpty(); | |
| 185 String label = data.get(i).mLabel; | |
| 186 if (!TextUtils.isEmpty(label)) { | |
| 187 mLabelViewPaint.getTextBounds(label, 0, label.length(), bounds); | |
| 188 } | |
| 189 float labelWidth = bounds.width(); | |
| 190 | |
| 191 bounds.setEmpty(); | |
| 192 String sublabel = data.get(i).mSublabel; | |
| 193 if (!TextUtils.isEmpty(sublabel)) { | |
| 194 mSublabelViewPaint.getTextBounds(sublabel, 0, sublabel.length(),
bounds); | |
| 195 } | |
| 196 | |
| 197 float localMax = Math.max(labelWidth, bounds.width()); | |
| 198 maxTextWidth = Math.max(maxTextWidth, localMax); | |
| 199 } | |
| 200 // Scale it down to make it unscaled by screen density. | |
| 201 maxTextWidth = maxTextWidth / mContext.getResources().getDisplayMetrics(
).density; | |
| 202 // Adding padding. | |
| 203 return maxTextWidth + TEXT_PADDING_DP; | |
| 204 } | |
| 205 | |
| 206 @Override | |
| 207 public void onItemClick(AdapterView<?> parent, View view, int position, long
id) { | |
| 208 mAutofillCallback.suggestionSelected(position); | |
| 209 } | |
| 210 | |
| 211 } | |
| OLD | NEW |