OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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.contextmenu; |
| 6 |
| 7 import android.app.Dialog; |
| 8 import android.content.Context; |
| 9 import android.content.DialogInterface; |
| 10 import android.support.design.widget.TabLayout; |
| 11 import android.support.v4.view.ViewPager; |
| 12 import android.support.v7.app.AlertDialog; |
| 13 import android.text.TextUtils; |
| 14 import android.util.Pair; |
| 15 import android.view.LayoutInflater; |
| 16 import android.view.View; |
| 17 import android.view.ViewGroup; |
| 18 import android.widget.AdapterView; |
| 19 import android.widget.BaseAdapter; |
| 20 import android.widget.ListView; |
| 21 import android.widget.TextView; |
| 22 |
| 23 import org.chromium.base.ApiCompatibilityUtils; |
| 24 import org.chromium.base.Callback; |
| 25 import org.chromium.base.VisibleForTesting; |
| 26 import org.chromium.chrome.R; |
| 27 |
| 28 import java.util.ArrayList; |
| 29 import java.util.List; |
| 30 |
| 31 /** |
| 32 * A custom dialog that separates each group into separate tabs. It uses a dialo
g instead. |
| 33 */ |
| 34 public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl
ickListener { |
| 35 private Dialog mDialog; |
| 36 private Callback<Integer> mCallback; |
| 37 private int mMenuItemHeight; |
| 38 |
| 39 @Override |
| 40 public void displayMenu(Context context, ContextMenuParams params, |
| 41 List<Pair<Integer, List<ContextMenuItem>>> items, Callback<Integer>
onItemClicked, |
| 42 final Runnable onMenuShown, final Runnable onMenuClosed) { |
| 43 mCallback = onItemClicked; |
| 44 mDialog = createDialog(context, params, items); |
| 45 mDialog.getWindow().setBackgroundDrawable(ApiCompatibilityUtils.getDrawa
ble( |
| 46 context.getResources(), R.drawable.bg_find_toolbar_popup)); |
| 47 |
| 48 mDialog.setOnShowListener(new DialogInterface.OnShowListener() { |
| 49 @Override |
| 50 public void onShow(DialogInterface dialogInterface) { |
| 51 onMenuShown.run(); |
| 52 } |
| 53 }); |
| 54 |
| 55 mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { |
| 56 @Override |
| 57 public void onDismiss(DialogInterface dialogInterface) { |
| 58 onMenuClosed.run(); |
| 59 } |
| 60 }); |
| 61 |
| 62 mDialog.show(); |
| 63 } |
| 64 |
| 65 /** |
| 66 * Returns the fully complete dialog based off the params and the itemGroups
. |
| 67 * @param context Used to inflate the dialog. |
| 68 * @param params Used to get the header title. |
| 69 * @param itemGroups If there is more than one group it will create a paged
view. |
| 70 * @return Returns a final dialog that does not have a background can be dis
played using |
| 71 * {@link AlertDialog#show()}. |
| 72 */ |
| 73 private Dialog createDialog(Context context, ContextMenuParams params, |
| 74 List<Pair<Integer, List<ContextMenuItem>>> itemGroups) { |
| 75 Dialog dialog = new Dialog(context); |
| 76 dialog.setContentView(createPagerView(context, params, itemGroups)); |
| 77 return dialog; |
| 78 } |
| 79 |
| 80 /** |
| 81 * Creates the view of a context menu. Based off the Context Type, it'll adj
ust the list of |
| 82 * items and display only the ones that'll be on that specific group. |
| 83 * @param context Used to get the resources of an item. |
| 84 * @param params used to create the header text. |
| 85 * @param items A set of Items to display in a context menu. Filtered based
off the type. |
| 86 * @return Returns a filled LinearLayout with all the context menu items |
| 87 */ |
| 88 @VisibleForTesting |
| 89 ViewGroup createContextMenuPageUi( |
| 90 Context context, ContextMenuParams params, List<ContextMenuItem> ite
ms, int maxCount) { |
| 91 ViewGroup baseLayout = (ViewGroup) LayoutInflater.from(context).inflate( |
| 92 R.layout.tabular_context_menu_page, null); |
| 93 ListView listView = (ListView) baseLayout.findViewById(R.id.selectable_i
tems); |
| 94 displayHeaderIfVisibleItems(params, baseLayout); |
| 95 |
| 96 // Set the list adapter and get the height to display it appropriately i
n a dialog. |
| 97 TabularContextMenuListAdapter listAdapter = |
| 98 new TabularContextMenuListAdapter(items, context); |
| 99 ViewGroup.LayoutParams layoutParams = listView.getLayoutParams(); |
| 100 layoutParams.height = measureApproximateListViewHeight(listView, listAda
pter, maxCount); |
| 101 listView.setLayoutParams(layoutParams); |
| 102 listView.setAdapter(listAdapter); |
| 103 listView.setOnItemClickListener(this); |
| 104 |
| 105 return baseLayout; |
| 106 } |
| 107 |
| 108 private void displayHeaderIfVisibleItems(ContextMenuParams params, ViewGroup
baseLayout) { |
| 109 String headerText = ChromeContextMenuPopulator.createHeaderText(params); |
| 110 TextView headerTextView = (TextView) baseLayout.findViewById(R.id.contex
t_header_text); |
| 111 if (TextUtils.isEmpty(headerText)) { |
| 112 headerTextView.setVisibility(View.GONE); |
| 113 baseLayout.findViewById(R.id.context_divider).setVisibility(View.GON
E); |
| 114 return; |
| 115 } |
| 116 headerTextView.setVisibility(View.VISIBLE); |
| 117 headerTextView.setText(headerText); |
| 118 } |
| 119 |
| 120 /** |
| 121 * To save time measuring the height, this method gets an item if the height
has not been |
| 122 * previous measured and multiplies it by count of the total amount of items
. It is fine if the |
| 123 * height too small as the ListView will scroll through the other values. |
| 124 * @param listView The ListView to measure the surrounding padding. |
| 125 * @param listAdapter The adapter which contains the items within the list. |
| 126 * @return Returns the combined height of the padding of the ListView and th
e approximate height |
| 127 * of the ListView based off the an item. |
| 128 */ |
| 129 private int measureApproximateListViewHeight( |
| 130 ListView listView, BaseAdapter listAdapter, int maxCount) { |
| 131 int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom()
; |
| 132 if (mMenuItemHeight == 0 && !listAdapter.isEmpty()) { |
| 133 View view = listAdapter.getView(0, null, listView); |
| 134 view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UN
SPECIFIED), |
| 135 View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECI
FIED)); |
| 136 mMenuItemHeight = view.getMeasuredHeight(); |
| 137 } |
| 138 return totalHeight + mMenuItemHeight * maxCount; |
| 139 } |
| 140 |
| 141 /** |
| 142 * Creates a ViewPageAdapter based off the given list of views. |
| 143 * @param context Used to inflate the new ViewPager |
| 144 * @param params Used to get the header text. |
| 145 * @param itemGroups The list of views to put into the ViewPager. The string
is the title of the |
| 146 * tab |
| 147 * @return Returns a complete tabular context menu view. |
| 148 */ |
| 149 @VisibleForTesting |
| 150 View createPagerView(Context context, ContextMenuParams params, |
| 151 List<Pair<Integer, List<ContextMenuItem>>> itemGroups) { |
| 152 View view = LayoutInflater.from(context).inflate(R.layout.tabular_contex
t_menu, null); |
| 153 |
| 154 List<Pair<String, ViewGroup>> viewGroups = new ArrayList<>(); |
| 155 int maxCount = 0; |
| 156 for (int i = 0; i < itemGroups.size(); i++) { |
| 157 Pair<Integer, List<ContextMenuItem>> itemGroup = itemGroups.get(i); |
| 158 maxCount = Math.max(maxCount, itemGroup.second.size()); |
| 159 } |
| 160 for (int i = 0; i < itemGroups.size(); i++) { |
| 161 Pair<Integer, List<ContextMenuItem>> itemGroup = itemGroups.get(i); |
| 162 viewGroups.add(new Pair<>(context.getString(itemGroup.first), |
| 163 createContextMenuPageUi(context, params, itemGroup.second, m
axCount))); |
| 164 } |
| 165 TabularContextMenuViewPager pager = |
| 166 (TabularContextMenuViewPager) view.findViewById(R.id.custom_page
r); |
| 167 pager.setAdapter(new TabularContextMenuPagerAdapter(viewGroups)); |
| 168 |
| 169 TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout); |
| 170 if (itemGroups.size() <= 1) { |
| 171 tabLayout.setVisibility(View.GONE); |
| 172 } |
| 173 tabLayout.setupWithViewPager((ViewPager) view.findViewById(R.id.custom_p
ager)); |
| 174 |
| 175 return view; |
| 176 } |
| 177 |
| 178 @Override |
| 179 public void onItemClick(AdapterView<?> adapterView, View view, int position,
long id) { |
| 180 mDialog.dismiss(); |
| 181 mCallback.onResult((int) id); |
| 182 } |
| 183 } |
OLD | NEW |