Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ui / android / java / src / org / chromium / ui / autofill / AutofillPopup.java
1 // Copyright 2013 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.ui.autofill;
6
7 import android.annotation.SuppressLint;
8 import android.content.Context;
9 import android.util.Log;
10 import android.view.View;
11 import android.widget.AdapterView;
12 import android.widget.ListPopupWindow;
13 import android.widget.PopupWindow;
14
15 import org.chromium.base.ApiCompatibilityUtils;
16 import org.chromium.ui.DropdownAdapter;
17 import org.chromium.ui.DropdownItem;
18 import org.chromium.ui.DropdownPopupWindow;
19 import org.chromium.ui.base.ViewAndroidDelegate;
20
21 import java.lang.reflect.Method;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.HashSet;
25 import java.util.List;
26
27 /**
28  * The Autofill suggestion popup that lists relevant suggestions.
29  */
30 public class AutofillPopup extends DropdownPopupWindow implements AdapterView.OnItemClickListener,
31         PopupWindow.OnDismissListener {
32
33     /**
34      * The constant used to specify a separator in a list of Autofill suggestions.
35      * Has to be kept in sync with enum in WebAutofillClient.h
36      */
37     private static final int ITEM_ID_SEPARATOR_ENTRY = -3;
38
39     private final Context mContext;
40     private final AutofillPopupDelegate mAutofillCallback;
41     private List<AutofillSuggestion> mSuggestions;
42
43
44     /**
45      * An interface to handle the touch interaction with an AutofillPopup object.
46      */
47     public interface AutofillPopupDelegate {
48         /**
49          * Informs the controller the AutofillPopup was hidden.
50          */
51         public void dismissed();
52
53         /**
54          * Handles the selection of an Autofill suggestion from an AutofillPopup.
55          * @param listIndex The index of the selected Autofill suggestion.
56          */
57         public void suggestionSelected(int listIndex);
58     }
59
60     /**
61      * Creates an AutofillWindow with specified parameters.
62      * @param context Application context.
63      * @param viewAndroidDelegate View delegate used to add and remove views.
64      * @param autofillCallback A object that handles the calls to the native AutofillPopupView.
65      */
66     public AutofillPopup(Context context, ViewAndroidDelegate viewAndroidDelegate,
67             AutofillPopupDelegate autofillCallback) {
68         super(context, viewAndroidDelegate);
69         mContext = context;
70         mAutofillCallback = autofillCallback;
71
72         setOnItemClickListener(this);
73         setOnDismissListener(this);
74     }
75
76     /**
77      * Filters the Autofill suggestions to the ones that we support and shows the popup.
78      * @param suggestions Autofill suggestion data.
79      */
80     @SuppressLint("InlinedApi")
81     public void filterAndShow(AutofillSuggestion[] suggestions, boolean isRtl) {
82         mSuggestions = new ArrayList<AutofillSuggestion>(Arrays.asList(suggestions));
83         // Remove the AutofillSuggestions with IDs that are not supported by Android
84         ArrayList<DropdownItem> cleanedData = new ArrayList<DropdownItem>();
85         HashSet<Integer> separators = new HashSet<Integer>();
86         for (int i = 0; i < suggestions.length; i++) {
87             int itemId = suggestions[i].getSuggestionId();
88             if (itemId == ITEM_ID_SEPARATOR_ENTRY) {
89                 separators.add(cleanedData.size());
90             } else {
91                 cleanedData.add(suggestions[i]);
92             }
93         }
94
95         setAdapter(new DropdownAdapter(mContext, cleanedData, separators));
96         show();
97         ApiCompatibilityUtils.setLayoutDirection(getListView(),
98                 isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
99
100         // HACK: The ListPopupWindow's mPopup automatically dismisses on an outside tap. There's
101         // no way to override it or prevent it, except reaching into ListPopupWindow's hidden
102         // API. This allows the C++ controller to completely control showing/hiding the popup.
103         // See http://crbug.com/400601
104         try {
105             Method setForceIgnoreOutsideTouch = ListPopupWindow.class.getMethod(
106                     "setForceIgnoreOutsideTouch", new Class[] { boolean.class });
107             setForceIgnoreOutsideTouch.invoke(this, new Object[] { true });
108         } catch (Exception e) {
109             Log.e("AutofillPopup",
110                     "ListPopupWindow.setForceIgnoreOutsideTouch not found",
111                     e);
112         }
113     }
114
115     /**
116      * Hides the popup.
117      */
118     public void hide() {
119         dismiss();
120     }
121
122     @Override
123     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
124         DropdownAdapter adapter = (DropdownAdapter) parent.getAdapter();
125         int listIndex = mSuggestions.indexOf(adapter.getItem(position));
126         assert listIndex > -1;
127         mAutofillCallback.suggestionSelected(listIndex);
128     }
129
130     @Override
131     public void onDismiss() {
132         mAutofillCallback.dismissed();
133     }
134 }