Index: content/public/android/java/src/org/chromium/content/browser/input/HandleView.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java b/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java |
deleted file mode 100644 |
index 2b50079a25361af7172df81a839228ec63f7fdb4..0000000000000000000000000000000000000000 |
--- a/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java |
+++ /dev/null |
@@ -1,438 +0,0 @@ |
-// 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.graphics.Canvas; |
-import android.graphics.Rect; |
-import android.graphics.drawable.Drawable; |
-import android.os.SystemClock; |
-import android.util.TypedValue; |
-import android.view.MotionEvent; |
-import android.view.View; |
-import android.view.ViewConfiguration; |
-import android.view.ViewParent; |
-import android.view.animation.AnimationUtils; |
-import android.widget.PopupWindow; |
- |
-import org.chromium.content.browser.PositionObserver; |
- |
-/** |
- * View that displays a selection or insertion handle for text editing. |
- * |
- * While a HandleView is logically a child of some other view, it does not exist in that View's |
- * hierarchy. |
- * |
- */ |
-public class HandleView extends View { |
- private static final float FADE_DURATION = 200.f; |
- |
- private Drawable mDrawable; |
- private final PopupWindow mContainer; |
- |
- // The position of the handle relative to the parent view. |
- private int mPositionX; |
- private int mPositionY; |
- |
- // The position of the parent relative to the application's root view. |
- private int mParentPositionX; |
- private int mParentPositionY; |
- |
- // The offset from this handles position to the "tip" of the handle. |
- private float mHotspotX; |
- private float mHotspotY; |
- |
- private final CursorController mController; |
- private boolean mIsDragging; |
- private float mTouchToWindowOffsetX; |
- private float mTouchToWindowOffsetY; |
- |
- private final int mLineOffsetY; |
- private float mDownPositionX, mDownPositionY; |
- private long mTouchTimer; |
- private boolean mIsInsertionHandle = false; |
- private float mAlpha; |
- private long mFadeStartTime; |
- |
- private final View mParent; |
- private InsertionHandleController.PastePopupMenu mPastePopupWindow; |
- |
- private final Rect mTempRect = new Rect(); |
- |
- static final int LEFT = 0; |
- static final int CENTER = 1; |
- static final int RIGHT = 2; |
- private int mOrientation = -1; |
- |
- /** Defer re-orientation while dragging to prevent confusing handle re-positioning. */ |
- private int mDeferredOrientation = -1; |
- |
- private final PositionObserver mParentPositionObserver; |
- private final PositionObserver.Listener mParentPositionListener; |
- |
- // Number of dips to subtract from the handle's y position to give a suitable |
- // y coordinate for the corresponding text position. This is to compensate for the fact |
- // that the handle position is at the base of the line of text. |
- private static final float LINE_OFFSET_Y_DIP = 5.0f; |
- |
- private static final int[] TEXT_VIEW_HANDLE_ATTRS = { |
- android.R.attr.textSelectHandleLeft, |
- android.R.attr.textSelectHandle, |
- android.R.attr.textSelectHandleRight, |
- }; |
- |
- HandleView(CursorController controller, int orientation, View parent, |
- PositionObserver parentPositionObserver) { |
- super(parent.getContext()); |
- mParent = parent; |
- Context context = mParent.getContext(); |
- mController = controller; |
- mContainer = new PopupWindow(context, null, android.R.attr.textSelectHandleWindowStyle); |
- mContainer.setSplitTouchEnabled(true); |
- mContainer.setClippingEnabled(false); |
- mContainer.setAnimationStyle(0); |
- |
- setOrientation(orientation); |
- |
- // Convert line offset dips to pixels. |
- mLineOffsetY = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, |
- LINE_OFFSET_Y_DIP, context.getResources().getDisplayMetrics()); |
- |
- mAlpha = 1.f; |
- |
- mParentPositionListener = new PositionObserver.Listener() { |
- @Override |
- public void onPositionChanged(int x, int y) { |
- updateParentPosition(x, y); |
- } |
- }; |
- mParentPositionObserver = parentPositionObserver; |
- } |
- |
- void setOrientation(int orientation) { |
- assert orientation >= LEFT && orientation <= RIGHT; |
- |
- if (mIsDragging) { |
- mDeferredOrientation = orientation; |
- return; |
- } |
- |
- if (mOrientation == orientation) return; |
- |
- final boolean hadValidOrientation = mOrientation != -1; |
- mOrientation = orientation; |
- mDeferredOrientation = -1; |
- |
- Context context = mParent.getContext(); |
- TypedArray a = context.getTheme().obtainStyledAttributes(TEXT_VIEW_HANDLE_ATTRS); |
- mDrawable = a.getDrawable(orientation); |
- a.recycle(); |
- |
- mIsInsertionHandle = (orientation == CENTER); |
- |
- final int oldAdjustedPositionX = getAdjustedPositionX(); |
- final int oldAdjustedPositionY = getAdjustedPositionY(); |
- |
- int handleWidth = mDrawable.getIntrinsicWidth(); |
- switch (orientation) { |
- case LEFT: { |
- mHotspotX = (handleWidth * 3) / 4f; |
- break; |
- } |
- |
- case RIGHT: { |
- mHotspotX = handleWidth / 4f; |
- break; |
- } |
- |
- case CENTER: |
- default: { |
- mHotspotX = handleWidth / 2f; |
- break; |
- } |
- } |
- mHotspotY = 0; |
- |
- // Force handle repositioning to accommodate the new orientation's hotspot. |
- if (hadValidOrientation) positionAt(oldAdjustedPositionX, oldAdjustedPositionY); |
- |
- invalidate(); |
- } |
- |
- @Override |
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
- setMeasuredDimension(mDrawable.getIntrinsicWidth(), |
- mDrawable.getIntrinsicHeight()); |
- } |
- |
- private void updateParentPosition(int parentPositionX, int parentPositionY) { |
- // Hide paste popup window as soon as a scroll occurs. |
- if (mPastePopupWindow != null) mPastePopupWindow.hide(); |
- |
- mTouchToWindowOffsetX += parentPositionX - mParentPositionX; |
- mTouchToWindowOffsetY += parentPositionY - mParentPositionY; |
- mParentPositionX = parentPositionX; |
- mParentPositionY = parentPositionY; |
- onPositionChanged(); |
- } |
- |
- private int getContainerPositionX() { |
- return mParentPositionX + mPositionX; |
- } |
- |
- private int getContainerPositionY() { |
- return mParentPositionY + mPositionY; |
- } |
- |
- private void onPositionChanged() { |
- // Deferring View invalidation while the handles are hidden prevents |
- // scheduling conflicts with the compositor. |
- if (getVisibility() != VISIBLE) return; |
- mContainer.update(getContainerPositionX(), getContainerPositionY(), |
- getRight() - getLeft(), getBottom() - getTop()); |
- } |
- |
- private void showContainer() { |
- mContainer.showAtLocation(mParent, 0, getContainerPositionX(), getContainerPositionY()); |
- } |
- |
- void show() { |
- // While hidden, the parent position may have become stale. It must be updated before |
- // checking isPositionVisible(). |
- updateParentPosition(mParentPositionObserver.getPositionX(), |
- mParentPositionObserver.getPositionY()); |
- if (!isPositionVisible()) { |
- hide(); |
- return; |
- } |
- mParentPositionObserver.addListener(mParentPositionListener); |
- mContainer.setContentView(this); |
- showContainer(); |
- |
- // Hide paste view when handle is moved on screen. |
- if (mPastePopupWindow != null) { |
- mPastePopupWindow.hide(); |
- } |
- } |
- |
- void hide() { |
- mIsDragging = false; |
- mDeferredOrientation = -1; |
- mContainer.dismiss(); |
- mParentPositionObserver.removeListener(mParentPositionListener); |
- if (mPastePopupWindow != null) { |
- mPastePopupWindow.hide(); |
- } |
- } |
- |
- boolean isShowing() { |
- return mContainer.isShowing(); |
- } |
- |
- private boolean isPositionVisible() { |
- // Always show a dragging handle. |
- if (mIsDragging) { |
- return true; |
- } |
- |
- final Rect clip = mTempRect; |
- clip.left = 0; |
- clip.top = 0; |
- clip.right = mParent.getWidth(); |
- clip.bottom = mParent.getHeight(); |
- |
- final ViewParent parent = mParent.getParent(); |
- if (parent == null || !parent.getChildVisibleRect(mParent, clip, null)) { |
- return false; |
- } |
- |
- final int posX = getContainerPositionX() + (int) mHotspotX; |
- final int posY = getContainerPositionY() + (int) mHotspotY; |
- |
- return posX >= clip.left && posX <= clip.right && |
- posY >= clip.top && posY <= clip.bottom; |
- } |
- |
- // x and y are in physical pixels. |
- void moveTo(int x, int y) { |
- int previousPositionX = mPositionX; |
- int previousPositionY = mPositionY; |
- |
- mPositionX = x; |
- mPositionY = y; |
- if (isPositionVisible()) { |
- if (mContainer.isShowing()) { |
- onPositionChanged(); |
- // Hide paste popup window as soon as the handle is dragged. |
- if (mPastePopupWindow != null && |
- (previousPositionX != mPositionX || previousPositionY != mPositionY)) { |
- mPastePopupWindow.hide(); |
- } |
- } else { |
- show(); |
- } |
- |
- if (mIsDragging) { |
- // Hide paste popup window as soon as the handle is dragged. |
- if (mPastePopupWindow != null) { |
- mPastePopupWindow.hide(); |
- } |
- } |
- } else { |
- hide(); |
- } |
- } |
- |
- @Override |
- protected void onDraw(Canvas c) { |
- updateAlpha(); |
- mDrawable.setBounds(0, 0, getRight() - getLeft(), getBottom() - getTop()); |
- mDrawable.draw(c); |
- } |
- |
- @Override |
- public boolean onTouchEvent(MotionEvent ev) { |
- switch (ev.getActionMasked()) { |
- case MotionEvent.ACTION_DOWN: { |
- mDownPositionX = ev.getRawX(); |
- mDownPositionY = ev.getRawY(); |
- mTouchToWindowOffsetX = mDownPositionX - mPositionX; |
- mTouchToWindowOffsetY = mDownPositionY - mPositionY; |
- mIsDragging = true; |
- mController.beforeStartUpdatingPosition(this); |
- mTouchTimer = SystemClock.uptimeMillis(); |
- break; |
- } |
- |
- case MotionEvent.ACTION_MOVE: { |
- updatePosition(ev.getRawX(), ev.getRawY()); |
- break; |
- } |
- |
- case MotionEvent.ACTION_UP: |
- if (mIsInsertionHandle) { |
- long delay = SystemClock.uptimeMillis() - mTouchTimer; |
- if (delay < ViewConfiguration.getTapTimeout()) { |
- if (mPastePopupWindow != null && mPastePopupWindow.isShowing()) { |
- // Tapping on the handle dismisses the displayed paste view, |
- mPastePopupWindow.hide(); |
- } else { |
- showPastePopupWindow(); |
- } |
- } |
- } |
- mIsDragging = false; |
- if (mDeferredOrientation != -1) setOrientation(mDeferredOrientation); |
- break; |
- |
- case MotionEvent.ACTION_CANCEL: |
- mIsDragging = false; |
- if (mDeferredOrientation != -1) setOrientation(mDeferredOrientation); |
- break; |
- |
- default: |
- return false; |
- } |
- return true; |
- } |
- |
- boolean isDragging() { |
- return mIsDragging; |
- } |
- |
- /** |
- * @return Returns the x position of the handle |
- */ |
- int getPositionX() { |
- return mPositionX; |
- } |
- |
- /** |
- * @return Returns the y position of the handle |
- */ |
- int getPositionY() { |
- return mPositionY; |
- } |
- |
- private void updatePosition(float rawX, float rawY) { |
- final float newPosX = rawX - mTouchToWindowOffsetX + mHotspotX; |
- final float newPosY = rawY - mTouchToWindowOffsetY + mHotspotY - mLineOffsetY; |
- |
- mController.updatePosition(this, Math.round(newPosX), Math.round(newPosY)); |
- } |
- |
- // x and y are in physical pixels. |
- void positionAt(int x, int y) { |
- moveTo(x - Math.round(mHotspotX), y - Math.round(mHotspotY)); |
- } |
- |
- // Returns the x coordinate of the position that the handle appears to be pointing to relative |
- // to the handles "parent" view. |
- int getAdjustedPositionX() { |
- return mPositionX + Math.round(mHotspotX); |
- } |
- |
- // Returns the y coordinate of the position that the handle appears to be pointing to relative |
- // to the handles "parent" view. |
- int getAdjustedPositionY() { |
- return mPositionY + Math.round(mHotspotY); |
- } |
- |
- // Returns the x coordinate of the postion that the handle appears to be pointing to relative to |
- // the root view of the application. |
- int getRootViewRelativePositionX() { |
- return getContainerPositionX() + Math.round(mHotspotX); |
- } |
- |
- // Returns the y coordinate of the postion that the handle appears to be pointing to relative to |
- // the root view of the application. |
- int getRootViewRelativePositionY() { |
- return getContainerPositionY() + Math.round(mHotspotY); |
- } |
- |
- // Returns a suitable y coordinate for the text position corresponding to the handle. |
- // As the handle points to a position on the base of the line of text, this method |
- // returns a coordinate a small number of pixels higher (i.e. a slightly smaller number) |
- // than getAdjustedPositionY. |
- int getLineAdjustedPositionY() { |
- return (int) (mPositionY + mHotspotY - mLineOffsetY); |
- } |
- |
- Drawable getDrawable() { |
- return mDrawable; |
- } |
- |
- private void updateAlpha() { |
- if (mAlpha == 1.f) return; |
- mAlpha = Math.min(1.f, |
- (AnimationUtils.currentAnimationTimeMillis() - mFadeStartTime) / FADE_DURATION); |
- mDrawable.setAlpha((int) (255 * mAlpha)); |
- invalidate(); |
- } |
- |
- /** |
- * If the handle is not visible, sets its visibility to View.VISIBLE and begins fading it in. |
- */ |
- void beginFadeIn() { |
- if (getVisibility() == VISIBLE) return; |
- mAlpha = 0.f; |
- mFadeStartTime = AnimationUtils.currentAnimationTimeMillis(); |
- setVisibility(VISIBLE); |
- // Position updates may have been deferred while the handle was hidden. |
- onPositionChanged(); |
- } |
- |
- void showPastePopupWindow() { |
- InsertionHandleController ihc = (InsertionHandleController) mController; |
- if (mIsInsertionHandle && ihc.canPaste()) { |
- if (mPastePopupWindow == null) { |
- // Lazy initialization: create when actually shown only. |
- mPastePopupWindow = ihc.new PastePopupMenu(); |
- } |
- mPastePopupWindow.show(); |
- } |
- } |
-} |