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

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

Issue 141533006: [Android] Move the java content/ package to content_public/ to start the split. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Small fixes and findbugs line update Created 6 years, 11 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/PopupZoomer.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/PopupZoomer.java b/content/public/android/java/src/org/chromium/content/browser/PopupZoomer.java
deleted file mode 100644
index bdc54301f220634ee7b909287a4de79908ca697d..0000000000000000000000000000000000000000
--- a/content/public/android/java/src/org/chromium/content/browser/PopupZoomer.java
+++ /dev/null
@@ -1,555 +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;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Path.Direction;
-import android.graphics.PointF;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Region.Op;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.SystemClock;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.animation.Interpolator;
-import android.view.animation.OvershootInterpolator;
-
-import org.chromium.content.R;
-
-/**
- * PopupZoomer is used to show the on-demand link zooming popup. It handles manipulation of the
- * canvas and touch events to display the on-demand zoom magnifier.
- */
-class PopupZoomer extends View {
- private static final String LOGTAG = "PopupZoomer";
-
- // The padding between the edges of the view and the popup. Note that there is a mirror
- // constant in content/renderer/render_view_impl.cc which should be kept in sync if
- // this is changed.
- private static final int ZOOM_BOUNDS_MARGIN = 25;
- // Time it takes for the animation to finish in ms.
- private static final long ANIMATION_DURATION = 300;
-
- /**
- * Interface to be implemented to listen for touch events inside the zoomed area.
- * The MotionEvent coordinates correspond to original unzoomed view.
- */
- public static interface OnTapListener {
- public boolean onSingleTap(View v, MotionEvent event);
- public boolean onLongPress(View v, MotionEvent event);
- }
-
- private OnTapListener mOnTapListener = null;
-
- /**
- * Interface to be implemented to add and remove PopupZoomer to/from the view hierarchy.
- */
- public static interface OnVisibilityChangedListener {
- public void onPopupZoomerShown(PopupZoomer zoomer);
- public void onPopupZoomerHidden(PopupZoomer zoomer);
- }
-
- private OnVisibilityChangedListener mOnVisibilityChangedListener = null;
-
- // Cached drawable used to frame the zooming popup.
- // TODO(tonyg): This should be marked purgeable so that if the system wants to recover this
- // memory, we can just reload it from the resource ID next time it is needed.
- // See android.graphics.BitmapFactory.Options#inPurgeable
- private static Drawable sOverlayDrawable;
- // The padding used for drawing the overlay around the content, instead of directly above it.
- private static Rect sOverlayPadding;
- // The radius of the overlay bubble, used for rounding the bitmap to draw underneath it.
- private static float sOverlayCornerRadius;
-
- private final Interpolator mShowInterpolator = new OvershootInterpolator();
- private final Interpolator mHideInterpolator = new ReverseInterpolator(mShowInterpolator);
-
- private boolean mAnimating = false;
- private boolean mShowing = false;
- private long mAnimationStartTime = 0;
-
- // The time that was left for the outwards animation to finish.
- // This is used in the case that the zoomer is cancelled while it is still animating outwards,
- // to avoid having it jump to full size then animate closed.
- private long mTimeLeft = 0;
-
- // initDimensions() needs to be called in onDraw().
- private boolean mNeedsToInitDimensions;
-
- // Available view area after accounting for ZOOM_BOUNDS_MARGIN.
- private RectF mViewClipRect;
-
- // The target rect to be zoomed.
- private Rect mTargetBounds;
-
- // The bitmap to hold the zoomed view.
- private Bitmap mZoomedBitmap;
-
- // How far to shift the canvas after all zooming is done, to keep it inside the bounds of the
- // view (including margin).
- private float mShiftX = 0, mShiftY = 0;
- // The magnification factor of the popup. It is recomputed once we have mTargetBounds and
- // mZoomedBitmap.
- private float mScale = 1.0f;
- // The bounds representing the actual zoomed popup.
- private RectF mClipRect;
- // The extrusion values are how far the zoomed area (mClipRect) extends from the touch point.
- // These values to used to animate the popup.
- private float mLeftExtrusion, mTopExtrusion, mRightExtrusion, mBottomExtrusion;
- // The last touch point, where the animation will start from.
- private final PointF mTouch = new PointF();
-
- // Since we sometimes overflow the bounds of the mViewClipRect, we need to allow scrolling.
- // Current scroll position.
- private float mPopupScrollX, mPopupScrollY;
- // Scroll bounds.
- private float mMinScrollX, mMaxScrollX;
- private float mMinScrollY, mMaxScrollY;
-
- private GestureDetector mGestureDetector;
-
- private static float getOverlayCornerRadius(Context context) {
- if (sOverlayCornerRadius == 0) {
- try {
- sOverlayCornerRadius = context.getResources().getDimension(
- R.dimen.link_preview_overlay_radius);
- } catch (Resources.NotFoundException e) {
- Log.w(LOGTAG, "No corner radius resource for PopupZoomer overlay found.");
- sOverlayCornerRadius = 1.0f;
- }
- }
- return sOverlayCornerRadius;
- }
-
- /**
- * Gets the drawable that should be used to frame the zooming popup, loading
- * it from the resource bundle if not already cached.
- */
- private static Drawable getOverlayDrawable(Context context) {
- if (sOverlayDrawable == null) {
- try {
- sOverlayDrawable = context.getResources().getDrawable(
- R.drawable.ondemand_overlay);
- } catch (Resources.NotFoundException e) {
- Log.w(LOGTAG, "No drawable resource for PopupZoomer overlay found.");
- sOverlayDrawable = new ColorDrawable();
- }
- sOverlayPadding = new Rect();
- sOverlayDrawable.getPadding(sOverlayPadding);
- }
- return sOverlayDrawable;
- }
-
- private static float constrain(float amount, float low, float high) {
- return amount < low ? low : (amount > high ? high : amount);
- }
-
- private static int constrain(int amount, int low, int high) {
- return amount < low ? low : (amount > high ? high : amount);
- }
-
- /**
- * Creates Popupzoomer.
- * @param context Context to be used.
- * @param overlayRadiusDimensoinResId Resource to be used to get overlay corner radius.
- */
- public PopupZoomer(Context context) {
- super(context);
-
- setVisibility(INVISIBLE);
- setFocusable(true);
- setFocusableInTouchMode(true);
-
- GestureDetector.SimpleOnGestureListener listener =
- new GestureDetector.SimpleOnGestureListener() {
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2,
- float distanceX, float distanceY) {
- if (mAnimating) return true;
-
- if (isTouchOutsideArea(e1.getX(), e1.getY())) {
- hide(true);
- } else {
- scroll(distanceX, distanceY);
- }
- return true;
- }
-
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- return handleTapOrPress(e, false);
- }
-
- @Override
- public void onLongPress(MotionEvent e) {
- handleTapOrPress(e, true);
- }
-
- private boolean handleTapOrPress(MotionEvent e, boolean isLongPress) {
- if (mAnimating) return true;
-
- float x = e.getX();
- float y = e.getY();
- if (isTouchOutsideArea(x, y)) {
- // User clicked on area outside the popup.
- hide(true);
- } else if (mOnTapListener != null) {
- PointF converted = convertTouchPoint(x, y);
- MotionEvent event = MotionEvent.obtainNoHistory(e);
- event.setLocation(converted.x, converted.y);
- if (isLongPress) {
- mOnTapListener.onLongPress(PopupZoomer.this, event);
- } else {
- mOnTapListener.onSingleTap(PopupZoomer.this, event);
- }
- hide(true);
- }
- return true;
- }
- };
- mGestureDetector = new GestureDetector(context, listener);
- }
-
- /**
- * Sets the OnTapListener.
- */
- public void setOnTapListener(OnTapListener listener) {
- mOnTapListener = listener;
- }
-
- /**
- * Sets the OnVisibilityChangedListener.
- */
- public void setOnVisibilityChangedListener(OnVisibilityChangedListener listener) {
- mOnVisibilityChangedListener = listener;
- }
-
- /**
- * Sets the bitmap to be used for the zoomed view.
- */
- public void setBitmap(Bitmap bitmap) {
- if (mZoomedBitmap != null) {
- mZoomedBitmap.recycle();
- mZoomedBitmap = null;
- }
- mZoomedBitmap = bitmap;
-
- // Round the corners of the bitmap so it doesn't stick out around the overlay.
- Canvas canvas = new Canvas(mZoomedBitmap);
- Path path = new Path();
- RectF canvasRect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
- float overlayCornerRadius = getOverlayCornerRadius(getContext());
- path.addRoundRect(canvasRect, overlayCornerRadius, overlayCornerRadius, Direction.CCW);
- canvas.clipPath(path, Op.XOR);
- Paint clearPaint = new Paint();
- clearPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
- clearPaint.setColor(Color.TRANSPARENT);
- canvas.drawPaint(clearPaint);
- }
-
- private void scroll(float x, float y) {
- mPopupScrollX = constrain(mPopupScrollX - x, mMinScrollX, mMaxScrollX);
- mPopupScrollY = constrain(mPopupScrollY - y, mMinScrollY, mMaxScrollY);
- invalidate();
- }
-
- private void startAnimation(boolean show) {
- mAnimating = true;
- mShowing = show;
- mTimeLeft = 0;
- if (show) {
- setVisibility(VISIBLE);
- mNeedsToInitDimensions = true;
- if (mOnVisibilityChangedListener != null) {
- mOnVisibilityChangedListener.onPopupZoomerShown(this);
- }
- } else {
- long endTime = mAnimationStartTime + ANIMATION_DURATION;
- mTimeLeft = endTime - SystemClock.uptimeMillis();
- if (mTimeLeft < 0) mTimeLeft = 0;
- }
- mAnimationStartTime = SystemClock.uptimeMillis();
- invalidate();
- }
-
- private void hideImmediately() {
- mAnimating = false;
- mShowing = false;
- mTimeLeft = 0;
- if (mOnVisibilityChangedListener != null) {
- mOnVisibilityChangedListener.onPopupZoomerHidden(this);
- }
- setVisibility(INVISIBLE);
- mZoomedBitmap.recycle();
- mZoomedBitmap = null;
- }
-
- /**
- * Returns true if the view is currently being shown (or is animating).
- */
- public boolean isShowing() {
- return mShowing || mAnimating;
- }
-
- /**
- * Sets the last touch point (on the unzoomed view).
- */
- public void setLastTouch(float x, float y) {
- mTouch.x = x;
- mTouch.y = y;
- }
-
- private void setTargetBounds(Rect rect) {
- mTargetBounds = rect;
- }
-
- private void initDimensions() {
- if (mTargetBounds == null || mTouch == null) return;
-
- // Compute the final zoom scale.
- mScale = (float) mZoomedBitmap.getWidth() / mTargetBounds.width();
-
- float l = mTouch.x - mScale * (mTouch.x - mTargetBounds.left);
- float t = mTouch.y - mScale * (mTouch.y - mTargetBounds.top);
- float r = l + mZoomedBitmap.getWidth();
- float b = t + mZoomedBitmap.getHeight();
- mClipRect = new RectF(l, t, r, b);
- int width = getWidth();
- int height = getHeight();
-
- mViewClipRect = new RectF(ZOOM_BOUNDS_MARGIN,
- ZOOM_BOUNDS_MARGIN,
- width - ZOOM_BOUNDS_MARGIN,
- height - ZOOM_BOUNDS_MARGIN);
-
- // Ensure it stays inside the bounds of the view. First shift it around to see if it
- // can fully fit in the view, then clip it to the padding section of the view to
- // ensure no overflow.
- mShiftX = 0;
- mShiftY = 0;
-
- // Right now this has the happy coincidence of showing the leftmost portion
- // of a scaled up bitmap, which usually has the text in it. When we want to support
- // RTL languages, we can conditionally switch the order of this check to push it
- // to the left instead of right.
- if (mClipRect.left < ZOOM_BOUNDS_MARGIN) {
- mShiftX = ZOOM_BOUNDS_MARGIN - mClipRect.left;
- mClipRect.left += mShiftX;
- mClipRect.right += mShiftX;
- } else if (mClipRect.right > width - ZOOM_BOUNDS_MARGIN) {
- mShiftX = (width - ZOOM_BOUNDS_MARGIN - mClipRect.right);
- mClipRect.right += mShiftX;
- mClipRect.left += mShiftX;
- }
- if (mClipRect.top < ZOOM_BOUNDS_MARGIN) {
- mShiftY = ZOOM_BOUNDS_MARGIN - mClipRect.top;
- mClipRect.top += mShiftY;
- mClipRect.bottom += mShiftY;
- } else if (mClipRect.bottom > height - ZOOM_BOUNDS_MARGIN) {
- mShiftY = height - ZOOM_BOUNDS_MARGIN - mClipRect.bottom;
- mClipRect.bottom += mShiftY;
- mClipRect.top += mShiftY;
- }
-
- // Allow enough scrolling to get to the entire bitmap that may be clipped inside the
- // bounds of the view.
- mMinScrollX = mMaxScrollX = mMinScrollY = mMaxScrollY = 0;
- if (mViewClipRect.right + mShiftX < mClipRect.right) {
- mMinScrollX = mViewClipRect.right - mClipRect.right;
- }
- if (mViewClipRect.left + mShiftX > mClipRect.left) {
- mMaxScrollX = mViewClipRect.left - mClipRect.left;
- }
- if (mViewClipRect.top + mShiftY > mClipRect.top) {
- mMaxScrollY = mViewClipRect.top - mClipRect.top;
- }
- if (mViewClipRect.bottom + mShiftY < mClipRect.bottom) {
- mMinScrollY = mViewClipRect.bottom - mClipRect.bottom;
- }
- // Now that we know how much we need to scroll, we can intersect with mViewClipRect.
- mClipRect.intersect(mViewClipRect);
-
- mLeftExtrusion = mTouch.x - mClipRect.left;
- mRightExtrusion = mClipRect.right - mTouch.x;
- mTopExtrusion = mTouch.y - mClipRect.top;
- mBottomExtrusion = mClipRect.bottom - mTouch.y;
-
- // Set an initial scroll position to take touch point into account.
- float percentX =
- (mTouch.x - mTargetBounds.centerX()) / (mTargetBounds.width() / 2.f) + .5f;
- float percentY =
- (mTouch.y - mTargetBounds.centerY()) / (mTargetBounds.height() / 2.f) + .5f;
-
- float scrollWidth = mMaxScrollX - mMinScrollX;
- float scrollHeight = mMaxScrollY - mMinScrollY;
- mPopupScrollX = scrollWidth * percentX * -1f;
- mPopupScrollY = scrollHeight * percentY * -1f;
- // Constrain initial scroll position within allowed bounds.
- mPopupScrollX = constrain(mPopupScrollX, mMinScrollX, mMaxScrollX);
- mPopupScrollY = constrain(mPopupScrollY, mMinScrollY, mMaxScrollY);
- }
-
- /*
- * Tests override it as the PopupZoomer is never attached to the view hierarchy.
- */
- protected boolean acceptZeroSizeView() {
- return false;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- if (!isShowing() || mZoomedBitmap == null) return;
- if (!acceptZeroSizeView() && (getWidth() == 0 || getHeight() == 0)) return;
-
- if (mNeedsToInitDimensions) {
- mNeedsToInitDimensions = false;
- initDimensions();
- }
-
- canvas.save();
- // Calculate the elapsed fraction of animation.
- float time = (SystemClock.uptimeMillis() - mAnimationStartTime + mTimeLeft) /
- ((float) ANIMATION_DURATION);
- time = constrain(time, 0, 1);
- if (time >= 1) {
- mAnimating = false;
- if (!isShowing()) {
- hideImmediately();
- return;
- }
- } else {
- invalidate();
- }
-
- // Fraction of the animation to actally show.
- float fractionAnimation;
- if (mShowing) {
- fractionAnimation = mShowInterpolator.getInterpolation(time);
- } else {
- fractionAnimation = mHideInterpolator.getInterpolation(time);
- }
-
- // Draw a faded color over the entire view to fade out the original content, increasing
- // the alpha value as fractionAnimation increases.
- // TODO(nileshagrawal): We should use time here instead of fractionAnimation
- // as fractionAnimaton is interpolated and can go over 1.
- canvas.drawARGB((int) (80 * fractionAnimation), 0, 0, 0);
- canvas.save();
-
- // Since we want the content to appear directly above its counterpart we need to make
- // sure that it starts out at exactly the same size as it appears in the page,
- // i.e. scale grows from 1/mScale to 1. Note that extrusion values are already zoomed
- // with mScale.
- float scale = fractionAnimation * (mScale - 1.0f) / mScale + 1.0f / mScale;
-
- // Since we want the content to appear directly above its counterpart on the
- // page, we need to remove the mShiftX/Y effect at the beginning of the animation.
- // The unshifting decreases with the animation.
- float unshiftX = -mShiftX * (1.0f - fractionAnimation) / mScale;
- float unshiftY = -mShiftY * (1.0f - fractionAnimation) / mScale;
-
- // Compute the rect to show.
- RectF rect = new RectF();
- rect.left = mTouch.x - mLeftExtrusion * scale + unshiftX;
- rect.top = mTouch.y - mTopExtrusion * scale + unshiftY;
- rect.right = mTouch.x + mRightExtrusion * scale + unshiftX;
- rect.bottom = mTouch.y + mBottomExtrusion * scale + unshiftY;
- canvas.clipRect(rect);
-
- // Since the canvas transform APIs all pre-concat the transformations, this is done in
- // reverse order. The canvas is first scaled up, then shifted the appropriate amount of
- // pixels.
- canvas.scale(scale, scale, rect.left, rect.top);
- canvas.translate(mPopupScrollX, mPopupScrollY);
- canvas.drawBitmap(mZoomedBitmap, rect.left, rect.top, null);
- canvas.restore();
- Drawable overlayNineTile = getOverlayDrawable(getContext());
- overlayNineTile.setBounds((int) rect.left - sOverlayPadding.left,
- (int) rect.top - sOverlayPadding.top,
- (int) rect.right + sOverlayPadding.right,
- (int) rect.bottom + sOverlayPadding.bottom);
- // TODO(nileshagrawal): We should use time here instead of fractionAnimation
- // as fractionAnimaton is interpolated and can go over 1.
- int alpha = constrain((int) (fractionAnimation * 255), 0, 255);
- overlayNineTile.setAlpha(alpha);
- overlayNineTile.draw(canvas);
- canvas.restore();
- }
-
- /**
- * Show the PopupZoomer view with given target bounds.
- */
- public void show(Rect rect) {
- if (mShowing || mZoomedBitmap == null) return;
-
- setTargetBounds(rect);
- startAnimation(true);
- }
-
- /**
- * Hide the PopupZoomer view.
- * @param animation true if hide with animation.
- */
- public void hide(boolean animation) {
- if (!mShowing) return;
-
- if (animation) {
- startAnimation(false);
- } else {
- hideImmediately();
- }
- }
-
- /**
- * Converts the coordinates to a point on the original un-zoomed view.
- */
- private PointF convertTouchPoint(float x, float y) {
- x -= mShiftX;
- y -= mShiftY;
- x = mTouch.x + (x - mTouch.x - mPopupScrollX) / mScale;
- y = mTouch.y + (y - mTouch.y - mPopupScrollY) / mScale;
- return new PointF(x, y);
- }
-
- /**
- * Returns true if the point is inside the final drawable area for this popup zoomer.
- */
- private boolean isTouchOutsideArea(float x, float y) {
- return !mClipRect.contains(x, y);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- mGestureDetector.onTouchEvent(event);
- return true;
- }
-
- private static class ReverseInterpolator implements Interpolator {
- private final Interpolator mInterpolator;
-
- public ReverseInterpolator(Interpolator i) {
- mInterpolator = i;
- }
-
- @Override
- public float getInterpolation(float input) {
- input = 1.0f - input;
- if (mInterpolator == null) return input;
- return mInterpolator.getInterpolation(input);
- }
- }
-}

Powered by Google App Engine
This is Rietveld 408576698