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

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

Issue 335943002: [Android] Composited selection handle rendering (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@input_native_handles_final
Patch Set: Clean up paste popup interaction Created 6 years, 5 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/PastePopupMenu.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/PastePopupMenu.java b/content/public/android/java/src/org/chromium/content/browser/input/PastePopupMenu.java
new file mode 100644
index 0000000000000000000000000000000000000000..4aedac90da0947ff4510b7c33cce2821279088f4
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/input/PastePopupMenu.java
@@ -0,0 +1,205 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser.input;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.PopupWindow;
+
+/**
+ * Paste popup implementation based on TextView.PastePopupMenu.
+ */
+public class PastePopupMenu implements OnClickListener {
+ private final View mParent;
+ private final PastePopupMenuDelegate mDelegate;
+ private final Context mContext;
+ private final PopupWindow mContainer;
+ private int mRawPositionX;
+ private int mRawPositionY;
+ private int mPositionX;
+ private int mPositionY;
+ private final View[] mPasteViews;
+ private final int[] mPasteViewLayouts;
+ private final int mLineOffsetY;
+ private final int mWidthOffsetX;
+ private boolean mAllowAutomaticShowing;
+
+ /**
+ * Provider of paste functionality for the given popup.
+ */
+ public interface PastePopupMenuDelegate {
+ /**
+ * Called to initiate a paste after the popup has been tapped.
+ */
+ void paste();
+
+ /**
+ * @return true iff content can be pasted to a focused editable region.
+ */
+ boolean canPaste();
+ }
+
+ public PastePopupMenu(View parent, PastePopupMenuDelegate delegate) {
+ mParent = parent;
+ mDelegate = delegate;
+ mContext = parent.getContext();
+ mContainer = new PopupWindow(mContext, null,
+ android.R.attr.textSelectHandleWindowStyle);
+ mContainer.setSplitTouchEnabled(true);
+ mContainer.setClippingEnabled(false);
+ mContainer.setAnimationStyle(0);
+
+ mContainer.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
+ mContainer.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ final int[] POPUP_LAYOUT_ATTRS = {
+ android.R.attr.textEditPasteWindowLayout,
+ android.R.attr.textEditNoPasteWindowLayout,
+ android.R.attr.textEditSidePasteWindowLayout,
+ android.R.attr.textEditSideNoPasteWindowLayout,
+ };
+
+ mPasteViews = new View[POPUP_LAYOUT_ATTRS.length];
+ mPasteViewLayouts = new int[POPUP_LAYOUT_ATTRS.length];
+
+ TypedArray attrs = mContext.getTheme().obtainStyledAttributes(POPUP_LAYOUT_ATTRS);
+ for (int i = 0; i < attrs.length(); ++i) {
+ mPasteViewLayouts[i] = attrs.getResourceId(attrs.getIndex(i), 0);
+ }
+ attrs.recycle();
+
+ // Convert line offset dips to pixels.
+ mLineOffsetY = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ 5.0f, mContext.getResources().getDisplayMetrics());
+ mWidthOffsetX = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ 30.0f, mContext.getResources().getDisplayMetrics());
+ }
+
+ /**
+ * Shows the paste popup at an appropriate location relative to the specified position.
+ */
+ public void showAt(int x, int y) {
+ if (!canPaste()) return;
+ updateContent(true);
+ positionAt(x, y);
+ }
+
+ /**
+ * Hides the paste popup.
+ */
+ public void hide() {
+ mContainer.dismiss();
+ }
+
+ /**
+ * @return Whether the popup is active and showing.
+ */
+ public boolean isShowing() {
+ return mContainer.isShowing();
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (canPaste()) {
+ paste();
+ }
+ hide();
+ }
+
+ private void positionAt(int x, int y) {
+ if (mRawPositionX == x && mRawPositionY == y && isShowing()) return;
+ mRawPositionX = x;
+ mRawPositionY = y;
+
+ View contentView = mContainer.getContentView();
+ int width = contentView.getMeasuredWidth();
+ int height = contentView.getMeasuredHeight();
+
+ mPositionX = (int) (x - width / 2.0f);
+ mPositionY = y - height - mLineOffsetY;
+
+ final int[] coords = new int[2];
+ mParent.getLocationInWindow(coords);
+ coords[0] += mPositionX;
+ coords[1] += mPositionY;
+
+ final int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
+ if (coords[1] < 0) {
+ updateContent(false);
+ // Update dimensions from new view
+ contentView = mContainer.getContentView();
+ width = contentView.getMeasuredWidth();
+ height = contentView.getMeasuredHeight();
+
+ // Vertical clipping, move under edited line and to the side of insertion cursor
+ // TODO bottom clipping in case there is no system bar
+ coords[1] += height;
+ coords[1] += mLineOffsetY;
+
+ // Move to right hand side of insertion cursor by default. TODO RTL text.
+ final int handleHalfWidth = mWidthOffsetX / 2;
+
+ if (x + width < screenWidth) {
+ coords[0] += handleHalfWidth + width / 2;
+ } else {
+ coords[0] -= handleHalfWidth + width / 2;
+ }
+ } else {
+ // Horizontal clipping
+ coords[0] = Math.max(0, coords[0]);
+ coords[0] = Math.min(screenWidth - width, coords[0]);
+ }
+
+ mContainer.showAtLocation(mParent, Gravity.NO_GRAVITY, coords[0], coords[1]);
+ }
+
+ private int viewIndex(boolean onTop) {
+ return (onTop ? 0 : 1 << 1) + (canPaste() ? 0 : 1 << 0);
+ }
+
+ private void updateContent(boolean onTop) {
+ final int viewIndex = viewIndex(onTop);
+ View view = mPasteViews[viewIndex];
+
+ if (view == null) {
+ final int layout = mPasteViewLayouts[viewIndex];
+ LayoutInflater inflater = (LayoutInflater) mContext.
+ getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ if (inflater != null) {
+ view = inflater.inflate(layout, null);
+ }
+
+ if (view == null) {
+ throw new IllegalArgumentException("Unable to inflate TextEdit paste window");
+ }
+
+ final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+ view.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ view.measure(size, size);
+
+ view.setOnClickListener(this);
+
+ mPasteViews[viewIndex] = view;
+ }
+
+ mContainer.setContentView(view);
+ }
+
+ private boolean canPaste() {
+ return mDelegate.canPaste();
+ }
+
+ private void paste() {
+ mDelegate.paste();
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698