Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java

Issue 231953003: Show Ash like <select> popup on Android tablets (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@newpopupx
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java
index 3313d8836f52aeab377845cde168aa4d226c6fa7..458d4ba4272f800f3bdb958fa3426a00f8a3b934 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupDialog.java
@@ -5,100 +5,164 @@
package org.chromium.content.browser.input;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
+import android.graphics.Rect;
import android.util.SparseBooleanArray;
+import android.view.Display;
+import android.view.Gravity;
import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.Window;
+import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
import android.widget.ListView;
import org.chromium.content.R;
import org.chromium.content.browser.ContentViewCore;
+import org.chromium.content.browser.DeviceUtils;
+import org.chromium.content.browser.RenderCoordinates;
import java.util.List;
/**
- * Handles the popup dialog for the <select> HTML tag support.
+ * Handles the popup for the <select> HTML tag support.
*/
-public class SelectPopupDialog {
+public class SelectPopupDialog implements OnItemClickListener,
Ted C 2014/04/12 01:10:27 With the amount of tablet specific checks, I think
+ DialogInterface.OnCancelListener,
Ted C 2014/04/12 01:10:27 same about indenting, needs to be 8 from the start
+ DialogInterface.OnDismissListener {
+
private static final int[] SELECT_DIALOG_ATTRS = {
- R.attr.select_dialog_multichoice,
- R.attr.select_dialog_singlechoice
+ R.attr.select_popup_multichoice,
+ R.attr.select_popup_singlechoice
};
+ // Keep in sync with optionRowHeightForTouch in blink::PopupListBox.
+ private static final int TABLET_POPUP_ROW_HEIGHT = 28;
+ // Keep in sync with WebCore::styledMenuListInternalPadding.
+ private static final int TABLET_POPUP_ROW_PADDING = 4;
+
// The dialog hosting the popup list view.
- private AlertDialog mListBoxPopup = null;
+ private Dialog mListBoxPopup = null;
+ private ListView mListView = null;
+ private Rect mOriginRect = null;
private final ContentViewCore mContentViewCore;
private final Context mContext;
- private SelectPopupDialog(ContentViewCore contentViewCore, List<SelectPopupItem> items,
- boolean multiple, int[] selected) {
+ private SelectPopupDialog(ContentViewCore contentViewCore,
+ List<SelectPopupItem> items, double itemFontSize, boolean multiple, int[] selected) {
mContentViewCore = contentViewCore;
mContext = mContentViewCore.getContext();
- final ListView listView = new ListView(mContext);
- listView.setCacheColorHint(0);
- AlertDialog.Builder b = new AlertDialog.Builder(mContext)
- .setView(listView)
- .setCancelable(true)
- .setInverseBackgroundForced(true);
+ if (DeviceUtils.isTablet(mContext)) {
+ mListBoxPopup = new Dialog(mContext, android.R.style.Theme_Translucent_NoTitleBar);
Ted C 2014/04/12 01:10:27 Instead of using a regular Dialog, we should be us
keishi 2014/04/15 14:41:07 Done.
+ mListBoxPopup.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ mListBoxPopup.setContentView(R.layout.select_popup_dialog);
+ mListBoxPopup.setCancelable(true);
+ mListBoxPopup.setCanceledOnTouchOutside(true);
- if (multiple) {
- b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- mContentViewCore.selectPopupMenuItems(getSelectedIndices(listView));
+ mListBoxPopup.findViewById(R.id.select_popup_shadow)
+ .setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
Ted C 2014/04/12 01:10:27 needs @Override
+ mListBoxPopup.cancel();
}
});
- b.setNegativeButton(android.R.string.cancel,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- mContentViewCore.selectPopupMenuItems(null);
- }
- });
+
+ mListView = (ListView) mListBoxPopup.findViewById(R.id.listView);
+ } else {
+ mListView = new ListView(mContext);
+ mListView.setCacheColorHint(0);
+ AlertDialog.Builder b = new AlertDialog.Builder(mContext)
+ .setView(mListView)
+ .setCancelable(true)
+ .setInverseBackgroundForced(true);
+
+ if (multiple) {
+ b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mContentViewCore.selectPopupMenuItems(getSelectedIndices(mListView));
+ }
+ });
+ b.setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mContentViewCore.selectPopupMenuItems(null);
+ }
+ });
+ }
+ mListBoxPopup = b.create();
}
- mListBoxPopup = b.create();
- final SelectPopupAdapter adapter = new SelectPopupAdapter(
- mContext, getSelectDialogLayout(multiple), items);
- listView.setAdapter(adapter);
- listView.setFocusableInTouchMode(true);
+ setupListView(items, itemFontSize, multiple, selected);
+ mListBoxPopup.setOnCancelListener(this);
+ mListBoxPopup.setOnDismissListener(this);
+ }
+
+ private void setupListView(List<SelectPopupItem> items, double itemFontSize, boolean multiple,
+ int[] selected) {
Ted C 2014/04/12 01:10:27 indenting
+ int layout = R.layout.select_popup_item;
+ if (!DeviceUtils.isTablet(mContext))
Ted C 2014/04/12 01:10:27 needs braces
+ layout = getSelectDialogLayout(multiple);
+ final SelectPopupAdapter adapter = new SelectPopupAdapter(mContext, layout, items);
+ if (DeviceUtils.isTablet(mContext)) {
+ RenderCoordinates renderCoordinates = mContentViewCore.renderCoordinates();
+ adapter.setTextSize(
+ renderCoordinates.fromLocalCssToPix((float)itemFontSize));
Ted C 2014/04/12 01:10:27 I'm not sure we want to scale these based on page
+ adapter.setMinHeight(
+ (int)renderCoordinates.fromLocalCssToPix(TABLET_POPUP_ROW_HEIGHT));
+ adapter.setPadding(
+ (int)renderCoordinates.fromLocalCssToPix(TABLET_POPUP_ROW_PADDING));
+ }
+ mListView.setAdapter(adapter);
+ mListView.setFocusableInTouchMode(true);
if (multiple) {
- listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+ mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
for (int i = 0; i < selected.length; ++i) {
- listView.setItemChecked(selected[i], true);
+ mListView.setItemChecked(selected[i], true);
}
} else {
- listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
- listView.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View v,
- int position, long id) {
- mContentViewCore.selectPopupMenuItems(getSelectedIndices(listView));
- mListBoxPopup.dismiss();
- }
- });
+ mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ mListView.setOnItemClickListener(this);
if (selected.length > 0) {
- listView.setSelection(selected[0]);
- listView.setItemChecked(selected[0], true);
+ mListView.setSelection(selected[0]);
+ mListView.setItemChecked(selected[0], true);
}
}
- mListBoxPopup.setOnCancelListener(new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- mContentViewCore.selectPopupMenuItems(null);
- }
- });
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View v,
+ int position, long id) {
+ mContentViewCore.selectPopupMenuItems(getSelectedIndices(mListView));
+ mListBoxPopup.dismiss();
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ if (DeviceUtils.isTablet(mContext)) {
+ mContentViewCore.selectPopupMenuItems(getSelectedIndices(mListView));
+ } else {
+ mContentViewCore.selectPopupMenuItems(null);
+ }
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ mListBoxPopup = null;
}
private int getSelectDialogLayout(boolean isMultiChoice) {
int resourceId;
TypedArray styledAttributes = mContext.obtainStyledAttributes(
- R.style.SelectPopupDialog, SELECT_DIALOG_ATTRS);
+ R.style.SelectPopup, SELECT_DIALOG_ATTRS);
resourceId = styledAttributes.getResourceId(isMultiChoice ? 0 : 1, 0);
styledAttributes.recycle();
return resourceId;
@@ -121,27 +185,126 @@ public class SelectPopupDialog {
return indices;
}
+ private int getListViewPreferredWidth() {
+ SelectPopupAdapter adapter = (SelectPopupAdapter) mListView.getAdapter();
+ int maxWidth = 0;
+ View view = null;
+ FrameLayout fakeParent = new FrameLayout(mContext);
+ for (int i = 0; i < adapter.getCount(); i++) {
+ view = adapter.getView(i, view, fakeParent);
Ted C 2014/04/12 01:10:27 Hmm..I think you might be able to pass null as the
keishi 2014/04/15 14:41:07 Done.
+ LinearLayout.LayoutParams params =
+ new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT);
Ted C 2014/04/12 01:10:27 java indenting
keishi 2014/04/15 14:41:07 Done.
+ view.setLayoutParams(params);
+ view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+ int width = view.getMeasuredWidth();
Ted C 2014/04/12 01:10:27 this could just be maxWidth = Math.max(maxWidth,
keishi 2014/04/15 14:41:07 Done.
+ if (width > maxWidth) {
+ maxWidth = width;
+ }
+ }
+ return maxWidth;
+ }
+
+ private int getListViewTotalHeight(int width) {
+ SelectPopupAdapter adapter = (SelectPopupAdapter) mListView.getAdapter();
+ int totalHeight = 0;
+ View view = null;
+ for (int i = 0; i < adapter.getCount(); i++) {
+ view = adapter.getView(i, view, mListView);
+ view.measure(
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
Ted C 2014/04/12 01:10:27 these lines should be +4 indented
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ totalHeight += view.getMeasuredHeight();
+ }
+ return totalHeight + (mListView.getDividerHeight() * (adapter.getCount() - 1));
+ }
+
+ public void show(Rect originRect) {
+ update(originRect);
+ mListBoxPopup.show();
+ }
+
+ public void hide() {
+ mListBoxPopup.dismiss();
+ }
+
/**
- * Hides the select dialog.
+ * Updates the popup position.
+ * @param originRect The rect of the origin select element. If null the last originRect will be
+ * reused.
Ted C 2014/04/12 01:10:27 align this with "The rect" above
*/
- public void hide() {
- mListBoxPopup.cancel();
+ public void update(Rect originRect) {
+ if (!DeviceUtils.isTablet(mContext)) {
Ted C 2014/04/12 01:10:27 I would make this a one liner since it is compact
+ return;
+ }
+ if (originRect != null) {
+ mOriginRect = originRect;
+ }
+ Rect screenRect = new Rect();
+ Display d = mListBoxPopup.getWindow().getWindowManager().getDefaultDisplay();
+ d.getRectSize(screenRect);
+ int horizontalMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.select_popup_horizontal_margin);
+ int bottomMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.select_popup_bottom_margin);
+ int borderWidth = mContext.getResources().getDimensionPixelSize(
+ R.dimen.select_popup_border_width);
+
+ Rect contentViewFrame = new Rect();
+ mContentViewCore.getContainerView().getWindowVisibleDisplayFrame(contentViewFrame);
+
+ RenderCoordinates renderCoordinates = mContentViewCore.renderCoordinates();
+ Rect originRectOnScreen = new Rect(
+ (int) renderCoordinates.fromLocalCssToPix(mOriginRect.left),
+ ((int) (renderCoordinates.fromLocalCssToPix(mOriginRect.top)
+ + renderCoordinates.getContentOffsetYPix())) + contentViewFrame.top,
+ (int) renderCoordinates.fromLocalCssToPix(mOriginRect.right),
+ ((int) (renderCoordinates.fromLocalCssToPix(mOriginRect.bottom)
+ + renderCoordinates.getContentOffsetYPix())) + contentViewFrame.top);
+
+ int availableSpaceAbove = originRectOnScreen.top;
+ int availableSpaceBelow = screenRect.height() - originRectOnScreen.bottom;
+ int availableSpace = Math.max(availableSpaceAbove, availableSpaceBelow);
+
+ int dialogWidth = Math.max(
+ getListViewPreferredWidth() + (horizontalMargin + borderWidth) * 2,
+ originRectOnScreen.width() + horizontalMargin * 2);
+ dialogWidth = Math.min(dialogWidth, screenRect.width());
+ int dialogHeight = Math.min(
+ getListViewTotalHeight(dialogWidth - (horizontalMargin + borderWidth) * 2) +
+ borderWidth * 2 + bottomMargin,
+ availableSpace);
+
+ WindowManager.LayoutParams wmlp = mListBoxPopup.getWindow().getAttributes();
+ wmlp.gravity = Gravity.TOP | Gravity.LEFT;
+ wmlp.x = originRectOnScreen.left - horizontalMargin;
+ wmlp.y = originRectOnScreen.bottom;
+ wmlp.width = dialogWidth;
+ wmlp.height = dialogHeight;
+ if (availableSpaceBelow < dialogHeight && availableSpaceAbove > availableSpaceBelow) {
+ wmlp.y = originRectOnScreen.top - dialogHeight + bottomMargin;
+ }
+ if (wmlp.x < 0) {
+ wmlp.x = 0;
+ }
+ if (wmlp.x > screenRect.width() - dialogWidth) {
+ wmlp.x = screenRect.right - dialogWidth;
+ }
+ mListBoxPopup.getWindow().setAttributes(wmlp);
}
/**
* Shows the popup menu triggered by the passed ContentView.
- * Hides any currently shown popup.
* @param items Items to show.
* @param multiple Whether the popup menu should support multi-select.
* @param selectedIndices Indices of selected items.
- * @return The select dialog created.
*/
- public static SelectPopupDialog show(
- ContentViewCore contentViewCore, List<SelectPopupItem> items,
- boolean multiple, int[] selectedIndices) {
- SelectPopupDialog dialog = new SelectPopupDialog(
- contentViewCore, items, multiple, selectedIndices);
- dialog.mListBoxPopup.show();
- return dialog;
+ public static SelectPopupDialog show(ContentViewCore contentViewCore, Rect originRect,
+ List<SelectPopupItem> items, double itemFontSize, boolean multiple,
+ int[] selectedIndices) {
+ SelectPopupDialog popup = new SelectPopupDialog(contentViewCore, items, itemFontSize,
+ multiple, selectedIndices);
+ popup.show(originRect);
+ return popup;
}
}

Powered by Google App Engine
This is Rietveld 408576698