SelectPopupDialog.java revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1// Copyright 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
5package org.chromium.content.browser.input;
6
7import android.app.AlertDialog;
8import android.content.Context;
9import android.content.DialogInterface;
10import android.content.res.TypedArray;
11import android.util.SparseBooleanArray;
12import android.view.View;
13import android.widget.AdapterView;
14import android.widget.AdapterView.OnItemClickListener;
15import android.widget.ListView;
16
17import org.chromium.content.R;
18import org.chromium.content.browser.ContentViewCore;
19
20import java.util.List;
21
22/**
23 * Handles the popup dialog for the <select> HTML tag support.
24 */
25public class SelectPopupDialog {
26    private static final int[] SELECT_DIALOG_ATTRS = {
27        R.attr.select_dialog_multichoice,
28        R.attr.select_dialog_singlechoice
29    };
30
31    // The dialog hosting the popup list view.
32    private AlertDialog mListBoxPopup = null;
33
34    private final ContentViewCore mContentViewCore;
35    private final Context mContext;
36
37    private SelectPopupDialog(ContentViewCore contentViewCore, List<SelectPopupItem> items,
38            boolean multiple, int[] selected) {
39        mContentViewCore = contentViewCore;
40        mContext = mContentViewCore.getContext();
41
42        final ListView listView = new ListView(mContext);
43        listView.setCacheColorHint(0);
44        AlertDialog.Builder b = new AlertDialog.Builder(mContext)
45                .setView(listView)
46                .setCancelable(true)
47                .setInverseBackgroundForced(true);
48
49        if (multiple) {
50            b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
51                @Override
52                public void onClick(DialogInterface dialog, int which) {
53                    mContentViewCore.selectPopupMenuItems(getSelectedIndices(listView));
54                }
55            });
56            b.setNegativeButton(android.R.string.cancel,
57                    new DialogInterface.OnClickListener() {
58                        @Override
59                        public void onClick(DialogInterface dialog, int which) {
60                            mContentViewCore.selectPopupMenuItems(null);
61                        }
62                    });
63        }
64        mListBoxPopup = b.create();
65        final SelectPopupAdapter adapter = new SelectPopupAdapter(
66                mContext, getSelectDialogLayout(multiple), items);
67        listView.setAdapter(adapter);
68        listView.setFocusableInTouchMode(true);
69
70        if (multiple) {
71            listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
72            for (int i = 0; i < selected.length; ++i) {
73                listView.setItemChecked(selected[i], true);
74            }
75        } else {
76            listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
77            listView.setOnItemClickListener(new OnItemClickListener() {
78                @Override
79                public void onItemClick(AdapterView<?> parent, View v,
80                        int position, long id) {
81                    mContentViewCore.selectPopupMenuItems(getSelectedIndices(listView));
82                    mListBoxPopup.dismiss();
83                }
84            });
85            if (selected.length > 0) {
86                listView.setSelection(selected[0]);
87                listView.setItemChecked(selected[0], true);
88            }
89        }
90        mListBoxPopup.setOnCancelListener(new DialogInterface.OnCancelListener() {
91            @Override
92            public void onCancel(DialogInterface dialog) {
93                mContentViewCore.selectPopupMenuItems(null);
94            }
95        });
96    }
97
98    private int getSelectDialogLayout(boolean isMultiChoice) {
99        int resourceId;
100        TypedArray styledAttributes = mContext.obtainStyledAttributes(
101                R.style.SelectPopupDialog, SELECT_DIALOG_ATTRS);
102        resourceId = styledAttributes.getResourceId(isMultiChoice ? 0 : 1, 0);
103        styledAttributes.recycle();
104        return resourceId;
105    }
106
107    private int[] getSelectedIndices(ListView listView) {
108        SparseBooleanArray sparseArray = listView.getCheckedItemPositions();
109        int selectedCount = 0;
110        for (int i = 0; i < sparseArray.size(); ++i) {
111            if (sparseArray.valueAt(i)) {
112                selectedCount++;
113            }
114        }
115        int[] indices = new int[selectedCount];
116        for (int i = 0, j = 0; i < sparseArray.size(); ++i) {
117            if (sparseArray.valueAt(i)) {
118                indices[j++] = sparseArray.keyAt(i);
119            }
120        }
121        return indices;
122    }
123
124    /**
125     * Hides the select dialog.
126     */
127    public void hide() {
128        mListBoxPopup.cancel();
129    }
130
131    /**
132     * Shows the popup menu triggered by the passed ContentView.
133     * Hides any currently shown popup.
134     * @param items           Items to show.
135     * @param multiple        Whether the popup menu should support multi-select.
136     * @param selectedIndices Indices of selected items.
137     * @return                The select dialog created.
138     */
139    public static SelectPopupDialog show(
140            ContentViewCore contentViewCore, List<SelectPopupItem> items,
141            boolean multiple, int[] selectedIndices) {
142        SelectPopupDialog dialog = new SelectPopupDialog(
143                contentViewCore, items, multiple, selectedIndices);
144        dialog.mListBoxPopup.show();
145        return dialog;
146    }
147}
148