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