blob: f3493c581d68e85e20a2eeec5909e21618fa63b1 [file] [log] [blame]
// Copyright 2014 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.graphics.Rect;
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 LegacyPastePopupMenu implements OnClickListener, PastePopupMenu {
private final View mParent;
private final PastePopupMenuDelegate mDelegate;
private final Context mContext;
private final PopupWindow mContainer;
private int mRawPositionX;
private int mRawPositionY;
private int mStatusBarHeight;
private View mPasteView;
private final int mPasteViewLayout;
private final int mLineOffsetY;
private final int mWidthOffsetX;
public LegacyPastePopupMenu(
Context context, View parent, final PastePopupMenuDelegate delegate) {
mParent = parent;
mDelegate = delegate;
mContext = context;
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[] popupLayoutAttrs = {
android.R.attr.textEditPasteWindowLayout,
};
TypedArray attrs = mContext.getTheme().obtainStyledAttributes(popupLayoutAttrs);
mPasteViewLayout = attrs.getResourceId(attrs.getIndex(0), 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());
final int statusBarHeightResourceId =
mContext.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (statusBarHeightResourceId > 0) {
mStatusBarHeight =
mContext.getResources().getDimensionPixelSize(statusBarHeightResourceId);
}
}
@Override
public void show(Rect selectionRect) {
hide();
updateContent();
positionAt(selectionRect.left, selectionRect.bottom);
}
@Override
public void hide() {
mContainer.dismiss();
}
@Override
public void onClick(View v) {
paste();
hide();
}
private void positionAt(int x, int y) {
if (mRawPositionX == x && mRawPositionY == y) return;
mRawPositionX = x;
mRawPositionY = y;
final View contentView = mContainer.getContentView();
final int width = contentView.getMeasuredWidth();
final int height = contentView.getMeasuredHeight();
int positionX = (int) (x - width / 2.0f);
int positionY = y - height - mLineOffsetY;
int minOffsetY = 0;
if (mParent.getSystemUiVisibility() == View.SYSTEM_UI_FLAG_VISIBLE) {
minOffsetY = mStatusBarHeight;
}
final int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
if (positionY < minOffsetY) {
// Vertical clipping, move under edited line and to the side of insertion cursor
// TODO bottom clipping in case there is no system bar
positionY += height;
positionY += mLineOffsetY;
// Move to right hand side of insertion cursor by default. TODO RTL text.
final int handleHalfWidth = mWidthOffsetX / 2;
if (x + width < screenWidth) positionX += handleHalfWidth + width / 2;
else positionX -= handleHalfWidth + width / 2;
} else {
// Horizontal clipping
positionX = Math.max(0, positionX);
positionX = Math.min(screenWidth - width, positionX);
}
// Offseting with location in window.
final int[] coords = new int[2];
mParent.getLocationInWindow(coords);
positionX += coords[0];
positionY += coords[1];
mContainer.showAtLocation(mParent, Gravity.NO_GRAVITY, positionX, positionY);
}
private void updateContent() {
if (mPasteView == null) {
final LayoutInflater inflater =
(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (inflater != null) mPasteView = inflater.inflate(mPasteViewLayout, null);
if (mPasteView == null) {
throw new IllegalArgumentException("Unable to inflate TextEdit paste window");
}
final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
mPasteView.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mPasteView.measure(size, size);
mPasteView.setOnClickListener(this);
}
mContainer.setContentView(mPasteView);
}
private void paste() {
mDelegate.paste();
}
}