Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 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.contextmenu; | 5 package org.chromium.chrome.browser.contextmenu; |
| 6 | 6 |
| 7 import android.app.Dialog; | 7 import android.app.Dialog; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.DialogInterface; | 9 import android.content.DialogInterface; |
| 10 import android.content.res.Resources; | |
| 11 import android.graphics.Bitmap; | |
| 12 import android.graphics.Canvas; | |
| 13 import android.graphics.Shader; | |
| 14 import android.graphics.drawable.BitmapDrawable; | |
| 15 import android.graphics.drawable.Drawable; | |
| 10 import android.support.design.widget.TabLayout; | 16 import android.support.design.widget.TabLayout; |
| 11 import android.support.v4.view.ViewPager; | 17 import android.support.v4.view.ViewPager; |
| 12 import android.support.v7.app.AlertDialog; | 18 import android.support.v7.app.AlertDialog; |
| 13 import android.text.TextUtils; | 19 import android.text.TextUtils; |
| 14 import android.util.Pair; | 20 import android.util.Pair; |
| 15 import android.view.LayoutInflater; | 21 import android.view.LayoutInflater; |
| 16 import android.view.View; | 22 import android.view.View; |
| 17 import android.view.ViewGroup; | 23 import android.view.ViewGroup; |
| 18 import android.widget.AdapterView; | 24 import android.widget.AdapterView; |
| 19 import android.widget.BaseAdapter; | 25 import android.widget.BaseAdapter; |
| 26 import android.widget.ImageView; | |
| 20 import android.widget.ListView; | 27 import android.widget.ListView; |
| 21 import android.widget.TextView; | 28 import android.widget.TextView; |
| 22 | 29 |
| 23 import org.chromium.base.ApiCompatibilityUtils; | 30 import org.chromium.base.ApiCompatibilityUtils; |
| 24 import org.chromium.base.Callback; | 31 import org.chromium.base.Callback; |
| 25 import org.chromium.base.VisibleForTesting; | 32 import org.chromium.base.VisibleForTesting; |
| 26 import org.chromium.chrome.R; | 33 import org.chromium.chrome.R; |
| 27 | 34 |
| 28 import java.util.ArrayList; | 35 import java.util.ArrayList; |
| 29 import java.util.List; | 36 import java.util.List; |
| 30 | 37 |
| 31 /** | 38 /** |
| 32 * A custom dialog that separates each group into separate tabs. It uses a dialo g instead. | 39 * A custom dialog that separates each group into separate tabs. It uses a dialo g instead. |
| 33 */ | 40 */ |
| 34 public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl ickListener { | 41 public class TabularContextMenuUi implements ContextMenuUi, AdapterView.OnItemCl ickListener { |
| 35 private Dialog mDialog; | 42 private Dialog mDialog; |
| 36 private Callback<Integer> mCallback; | 43 private Callback<Integer> mCallback; |
| 37 private int mMenuItemHeight; | 44 private int mMenuItemHeight; |
| 45 private ImageView mHeaderImageView; | |
| 38 | 46 |
| 39 @Override | 47 @Override |
| 40 public void displayMenu(Context context, ContextMenuParams params, | 48 public void displayMenu(Context context, ContextMenuParams params, |
| 41 List<Pair<Integer, List<ContextMenuItem>>> items, Callback<Integer> onItemClicked, | 49 List<Pair<Integer, List<ContextMenuItem>>> items, Callback<Integer> onItemClicked, |
| 42 final Runnable onMenuShown, final Runnable onMenuClosed) { | 50 final Runnable onMenuShown, final Runnable onMenuClosed) { |
| 43 mCallback = onItemClicked; | 51 mCallback = onItemClicked; |
| 44 mDialog = createDialog(context, params, items); | 52 mDialog = createDialog(context, params, items); |
| 45 mDialog.getWindow().setBackgroundDrawable(ApiCompatibilityUtils.getDrawa ble( | 53 mDialog.getWindow().setBackgroundDrawable(ApiCompatibilityUtils.getDrawa ble( |
| 46 context.getResources(), R.drawable.bg_find_toolbar_popup)); | 54 context.getResources(), R.drawable.bg_find_toolbar_popup)); |
| 47 | 55 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 76 dialog.setContentView(createPagerView(context, params, itemGroups)); | 84 dialog.setContentView(createPagerView(context, params, itemGroups)); |
| 77 return dialog; | 85 return dialog; |
| 78 } | 86 } |
| 79 | 87 |
| 80 /** | 88 /** |
| 81 * Creates the view of a context menu. Based off the Context Type, it'll adj ust the list of | 89 * 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. | 90 * items and display only the ones that'll be on that specific group. |
| 83 * @param context Used to get the resources of an item. | 91 * @param context Used to get the resources of an item. |
| 84 * @param params used to create the header text. | 92 * @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. | 93 * @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 | 94 * @param isImage Whether or not the view should have an image layout or not . |
| 95 * @param maxCount The maximum amount of {@link ContextMenuItem}s that could exist in this view | |
| 96 * or any other views calculated in the context menu. Used t o estimate the size | |
| 97 * of the list. | |
| 98 * @return Returns a filled LinearLayout with all the context menu items. | |
| 87 */ | 99 */ |
| 88 @VisibleForTesting | 100 @VisibleForTesting |
| 89 ViewGroup createContextMenuPageUi( | 101 ViewGroup createContextMenuPageUi(Context context, ContextMenuParams params, |
| 90 Context context, ContextMenuParams params, List<ContextMenuItem> ite ms, int maxCount) { | 102 List<ContextMenuItem> items, boolean isImage, int maxCount) { |
| 91 ViewGroup baseLayout = (ViewGroup) LayoutInflater.from(context).inflate( | 103 ViewGroup baseLayout = (ViewGroup) LayoutInflater.from(context).inflate( |
| 92 R.layout.tabular_context_menu_page, null); | 104 R.layout.tabular_context_menu_page, null); |
| 93 ListView listView = (ListView) baseLayout.findViewById(R.id.selectable_i tems); | 105 ListView listView = (ListView) baseLayout.findViewById(R.id.selectable_i tems); |
| 94 displayHeaderIfVisibleItems(params, baseLayout); | 106 |
| 107 if (isImage) { | |
| 108 displayImageHeader(baseLayout, params, context.getResources()); | |
| 109 } else { | |
| 110 displayHeaderIfVisibleItems(params, baseLayout); | |
| 111 } | |
| 95 | 112 |
| 96 // Set the list adapter and get the height to display it appropriately i n a dialog. | 113 // Set the list adapter and get the height to display it appropriately i n a dialog. |
| 97 TabularContextMenuListAdapter listAdapter = | 114 TabularContextMenuListAdapter listAdapter = |
| 98 new TabularContextMenuListAdapter(items, context); | 115 new TabularContextMenuListAdapter(items, context); |
| 99 ViewGroup.LayoutParams layoutParams = listView.getLayoutParams(); | 116 ViewGroup.LayoutParams layoutParams = listView.getLayoutParams(); |
| 100 layoutParams.height = measureApproximateListViewHeight(listView, listAda pter, maxCount); | 117 layoutParams.height = measureApproximateListViewHeight(listView, listAda pter, maxCount); |
| 101 listView.setLayoutParams(layoutParams); | 118 listView.setLayoutParams(layoutParams); |
| 102 listView.setAdapter(listAdapter); | 119 listView.setAdapter(listAdapter); |
| 103 listView.setOnItemClickListener(this); | 120 listView.setOnItemClickListener(this); |
| 104 | 121 |
| 105 return baseLayout; | 122 return baseLayout; |
| 106 } | 123 } |
| 107 | 124 |
| 108 private void displayHeaderIfVisibleItems(ContextMenuParams params, ViewGroup baseLayout) { | 125 private void displayHeaderIfVisibleItems(ContextMenuParams params, ViewGroup baseLayout) { |
| 109 String headerText = ChromeContextMenuPopulator.createHeaderText(params); | 126 String headerText = ChromeContextMenuPopulator.createHeaderText(params); |
| 110 final TextView headerTextView = | 127 final TextView headerTextView = |
| 111 (TextView) baseLayout.findViewById(R.id.context_header_text); | 128 (TextView) baseLayout.findViewById(R.id.context_header_text); |
| 112 if (TextUtils.isEmpty(headerText)) { | 129 if (TextUtils.isEmpty(headerText)) { |
| 130 baseLayout.findViewById(R.id.context_header_layout).setVisibility(Vi ew.GONE); | |
| 113 headerTextView.setVisibility(View.GONE); | 131 headerTextView.setVisibility(View.GONE); |
| 114 baseLayout.findViewById(R.id.context_divider).setVisibility(View.GON E); | 132 baseLayout.findViewById(R.id.context_divider).setVisibility(View.GON E); |
| 115 return; | 133 return; |
| 116 } | 134 } |
| 117 headerTextView.setVisibility(View.VISIBLE); | 135 headerTextView.setVisibility(View.VISIBLE); |
| 118 headerTextView.setText(headerText); | 136 headerTextView.setText(headerText); |
| 119 headerTextView.setOnClickListener(new View.OnClickListener() { | 137 headerTextView.setOnClickListener(new View.OnClickListener() { |
| 120 @Override | 138 @Override |
| 121 public void onClick(View view) { | 139 public void onClick(View view) { |
| 122 if (headerTextView.getMaxLines() == Integer.MAX_VALUE) { | 140 if (headerTextView.getMaxLines() == Integer.MAX_VALUE) { |
| 123 headerTextView.setMaxLines(1); | 141 headerTextView.setMaxLines(1); |
| 124 headerTextView.setEllipsize(TextUtils.TruncateAt.END); | 142 headerTextView.setEllipsize(TextUtils.TruncateAt.END); |
| 125 } else { | 143 } else { |
| 126 headerTextView.setMaxLines(Integer.MAX_VALUE); | 144 headerTextView.setMaxLines(Integer.MAX_VALUE); |
| 127 headerTextView.setEllipsize(null); | 145 headerTextView.setEllipsize(null); |
| 128 } | 146 } |
| 129 } | 147 } |
| 130 }); | 148 }); |
| 131 } | 149 } |
| 132 | 150 |
| 151 private void displayImageHeader( | |
| 152 ViewGroup baseLayout, ContextMenuParams params, Resources resources) { | |
| 153 displayHeaderIfVisibleItems(params, baseLayout); | |
| 154 // #displayHeaderIfVisibleItems() sets these two views to GONE if the he ader text is | |
| 155 // empty but they should still be visible because we have an image to di splay. | |
| 156 baseLayout.findViewById(R.id.context_header_layout).setVisibility(View.V ISIBLE); | |
| 157 baseLayout.findViewById(R.id.context_divider).setVisibility(View.VISIBLE ); | |
| 158 | |
| 159 mHeaderImageView = (ImageView) baseLayout.findViewById(R.id.context_head er_image); | |
| 160 TextView headerTextView = (TextView) baseLayout.findViewById(R.id.contex t_header_text); | |
| 161 // We'd prefer the header text is the title text instead of the link tex t for images. | |
| 162 String headerText = params.getTitleText(); | |
| 163 if (!TextUtils.isEmpty(headerText)) { | |
| 164 headerTextView.setText(headerText); | |
| 165 } | |
| 166 setBackgroundForImageView(mHeaderImageView, resources); | |
| 167 } | |
| 168 | |
| 169 /** | |
| 170 * This creates a checkerboard style background displayed before the image i s shown. | |
| 171 */ | |
| 172 private void setBackgroundForImageView(ImageView imageView, Resources resour ces) { | |
| 173 Drawable drawable = | |
| 174 ApiCompatibilityUtils.getDrawable(resources, R.drawable.checkerb oard_background); | |
| 175 Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), | |
| 176 drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); | |
| 177 Canvas canvas = new Canvas(bitmap); | |
| 178 drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); | |
| 179 drawable.draw(canvas); | |
| 180 BitmapDrawable bm = new BitmapDrawable(resources, bitmap); | |
| 181 bm.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); | |
| 182 imageView.setVisibility(View.VISIBLE); | |
| 183 imageView.setBackground(bm); | |
| 184 } | |
| 185 | |
| 133 /** | 186 /** |
| 134 * To save time measuring the height, this method gets an item if the height has not been | 187 * To save time measuring the height, this method gets an item if the height has not been |
| 135 * previous measured and multiplies it by count of the total amount of items . It is fine if the | 188 * previous measured and multiplies it by count of the total amount of items . It is fine if the |
| 136 * height too small as the ListView will scroll through the other values. | 189 * height too small as the ListView will scroll through the other values. |
| 137 * @param listView The ListView to measure the surrounding padding. | 190 * @param listView The ListView to measure the surrounding padding. |
| 138 * @param listAdapter The adapter which contains the items within the list. | 191 * @param listAdapter The adapter which contains the items within the list. |
| 139 * @return Returns the combined height of the padding of the ListView and th e approximate height | 192 * @return Returns the combined height of the padding of the ListView and th e approximate height |
| 140 * of the ListView based off the an item. | 193 * of the ListView based off the an item. |
| 141 */ | 194 */ |
| 142 private int measureApproximateListViewHeight( | 195 private int measureApproximateListViewHeight( |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 165 View view = LayoutInflater.from(context).inflate(R.layout.tabular_contex t_menu, null); | 218 View view = LayoutInflater.from(context).inflate(R.layout.tabular_contex t_menu, null); |
| 166 | 219 |
| 167 List<Pair<String, ViewGroup>> viewGroups = new ArrayList<>(); | 220 List<Pair<String, ViewGroup>> viewGroups = new ArrayList<>(); |
| 168 int maxCount = 0; | 221 int maxCount = 0; |
| 169 for (int i = 0; i < itemGroups.size(); i++) { | 222 for (int i = 0; i < itemGroups.size(); i++) { |
| 170 Pair<Integer, List<ContextMenuItem>> itemGroup = itemGroups.get(i); | 223 Pair<Integer, List<ContextMenuItem>> itemGroup = itemGroups.get(i); |
| 171 maxCount = Math.max(maxCount, itemGroup.second.size()); | 224 maxCount = Math.max(maxCount, itemGroup.second.size()); |
| 172 } | 225 } |
| 173 for (int i = 0; i < itemGroups.size(); i++) { | 226 for (int i = 0; i < itemGroups.size(); i++) { |
| 174 Pair<Integer, List<ContextMenuItem>> itemGroup = itemGroups.get(i); | 227 Pair<Integer, List<ContextMenuItem>> itemGroup = itemGroups.get(i); |
| 228 // TODO(tedchoc): Pass the ContextMenuGroup identifier to determine if it's an image. | |
| 229 boolean isImageTab = itemGroup.first == R.string.contextmenu_image_t itle; | |
| 175 viewGroups.add(new Pair<>(context.getString(itemGroup.first), | 230 viewGroups.add(new Pair<>(context.getString(itemGroup.first), |
| 176 createContextMenuPageUi(context, params, itemGroup.second, m axCount))); | 231 createContextMenuPageUi( |
| 232 context, params, itemGroup.second, isImageTab, maxCo unt))); | |
| 177 } | 233 } |
| 178 TabularContextMenuViewPager pager = | 234 TabularContextMenuViewPager pager = |
| 179 (TabularContextMenuViewPager) view.findViewById(R.id.custom_page r); | 235 (TabularContextMenuViewPager) view.findViewById(R.id.custom_page r); |
| 180 pager.setAdapter(new TabularContextMenuPagerAdapter(viewGroups)); | 236 pager.setAdapter(new TabularContextMenuPagerAdapter(viewGroups)); |
| 181 | 237 |
| 182 TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout); | 238 TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout); |
| 183 if (itemGroups.size() <= 1) { | 239 if (itemGroups.size() <= 1) { |
| 184 tabLayout.setVisibility(View.GONE); | 240 tabLayout.setVisibility(View.GONE); |
| 185 } | 241 } |
| 186 tabLayout.setupWithViewPager((ViewPager) view.findViewById(R.id.custom_p ager)); | 242 tabLayout.setupWithViewPager((ViewPager) view.findViewById(R.id.custom_p ager)); |
| 187 | 243 |
| 188 return view; | 244 return view; |
| 189 } | 245 } |
| 190 | 246 |
| 247 public void onImageThumbnailRetrieved(Bitmap bitmap) { | |
|
Ted C
2017/03/31 18:48:32
add javadoc
JJ
2017/03/31 19:01:20
Done.
| |
| 248 if (mHeaderImageView != null) { | |
| 249 mHeaderImageView.setImageBitmap(bitmap); | |
| 250 } | |
| 251 } | |
| 252 | |
| 191 @Override | 253 @Override |
| 192 public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { | 254 public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { |
| 193 mDialog.dismiss(); | 255 mDialog.dismiss(); |
| 194 mCallback.onResult((int) id); | 256 mCallback.onResult((int) id); |
| 195 } | 257 } |
| 196 } | 258 } |
| OLD | NEW |