Index: chrome/android/java_staging/src/org/chromium/chrome/browser/widget/findinpage/FindResultBar.java |
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/widget/findinpage/FindResultBar.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/widget/findinpage/FindResultBar.java |
deleted file mode 100644 |
index a0e094a54522ce36d39261c830da904595d9de43..0000000000000000000000000000000000000000 |
--- a/chrome/android/java_staging/src/org/chromium/chrome/browser/widget/findinpage/FindResultBar.java |
+++ /dev/null |
@@ -1,401 +0,0 @@ |
-// Copyright 2015 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.chrome.browser.widget.findinpage; |
- |
-import android.animation.Animator; |
-import android.animation.AnimatorListenerAdapter; |
-import android.animation.ObjectAnimator; |
-import android.annotation.SuppressLint; |
-import android.content.Context; |
-import android.content.res.Resources; |
-import android.graphics.Canvas; |
-import android.graphics.Paint; |
-import android.graphics.RectF; |
-import android.view.Gravity; |
-import android.view.MotionEvent; |
-import android.view.View; |
-import android.view.ViewGroup; |
-import android.widget.FrameLayout; |
- |
-import org.chromium.base.annotations.SuppressFBWarnings; |
-import org.chromium.chrome.R; |
-import org.chromium.chrome.browser.Tab; |
-import org.chromium.chrome.browser.findinpage.FindInPageBridge; |
-import org.chromium.chrome.browser.util.MathUtils; |
-import org.chromium.ui.UiUtils; |
-import org.chromium.ui.base.LocalizationUtils; |
-import org.chromium.ui.interpolators.BakedBezierInterpolator; |
- |
-import java.util.ArrayList; |
-import java.util.Arrays; |
-import java.util.Collections; |
-import java.util.Comparator; |
-import java.util.List; |
- |
-/** |
- * The view that shows the positions of the find in page matches and allows scrubbing |
- * between the entries. |
- */ |
-class FindResultBar extends View { |
- private static final int VISIBILTY_ANIMATION_DURATION_MS = 200; |
- |
- private final int mBackgroundColor; |
- private final int mBackgroundBorderColor; |
- private final int mResultColor; |
- private final int mResultBorderColor; |
- private final int mActiveColor; |
- private final int mActiveBorderColor; |
- |
- private final int mBarTouchWidth; |
- private final int mBarDrawWidth; |
- private final int mResultMinHeight; |
- private final int mActiveMinHeight; |
- private final int mBarVerticalPadding; |
- private final int mMinGapBetweenStacks; |
- private final int mStackedResultHeight; |
- |
- private final Tab mTab; |
- private FindInPageBridge mFindInPageBridge; |
- |
- int mRectsVersion = -1; |
- private RectF[] mMatches = new RectF[0]; |
- private RectF mActiveMatch; |
- |
- private ArrayList<Tickmark> mTickmarks = new ArrayList<Tickmark>(0); |
- private int mBarHeightForWhichTickmarksWereCached = -1; |
- |
- private Animator mVisibilityAnimation; |
- private boolean mDismissing; |
- |
- private final Paint mFillPaint; |
- private final Paint mStrokePaint; |
- |
- boolean mWaitingForActivateAck = false; |
- |
- private static Comparator<RectF> sComparator = new Comparator<RectF>() { |
- @Override |
- public int compare(RectF a, RectF b) { |
- if (a.top != b.top) return a.top > b.top ? 1 : -1; |
- if (a.top != b.top) return a.left > b.left ? 1 : -1; |
- return 0; |
- } |
- }; |
- |
- /** |
- * Creates an instance of a {@link FindResultBar}. |
- * @param context The Context to create this {@link FindResultBar} under. |
- * @param tab The Tab containing the ContentView this {@link FindResultBar} will be drawn in. |
- */ |
- public FindResultBar(Context context, Tab tab, FindInPageBridge findInPageBridge) { |
- super(context); |
- |
- Resources res = context.getResources(); |
- mBackgroundColor = res.getColor( |
- R.color.find_result_bar_background_color); |
- mBackgroundBorderColor = res.getColor( |
- R.color.find_result_bar_background_border_color); |
- mResultColor = res.getColor( |
- R.color.find_result_bar_result_color); |
- mResultBorderColor = res.getColor( |
- R.color.find_result_bar_result_border_color); |
- mActiveColor = res.getColor( |
- R.color.find_result_bar_active_color); |
- mActiveBorderColor = res.getColor( |
- R.color.find_result_bar_active_border_color); |
- mBarTouchWidth = res.getDimensionPixelSize( |
- R.dimen.find_result_bar_touch_width); |
- mBarDrawWidth = res.getDimensionPixelSize(R.dimen.find_result_bar_draw_width) |
- + res.getDimensionPixelSize(R.dimen.find_in_page_separator_width); |
- mResultMinHeight = res.getDimensionPixelSize(R.dimen.find_result_bar_result_min_height); |
- mActiveMinHeight = res.getDimensionPixelSize( |
- R.dimen.find_result_bar_active_min_height); |
- mBarVerticalPadding = res.getDimensionPixelSize( |
- R.dimen.find_result_bar_vertical_padding); |
- mMinGapBetweenStacks = res.getDimensionPixelSize( |
- R.dimen.find_result_bar_min_gap_between_stacks); |
- mStackedResultHeight = res.getDimensionPixelSize( |
- R.dimen.find_result_bar_stacked_result_height); |
- |
- mFillPaint = new Paint(); |
- mStrokePaint = new Paint(); |
- mFillPaint.setAntiAlias(true); |
- mStrokePaint.setAntiAlias(true); |
- mFillPaint.setStyle(Paint.Style.FILL); |
- mStrokePaint.setStyle(Paint.Style.STROKE); |
- mStrokePaint.setStrokeWidth(1.0f); |
- |
- mFindInPageBridge = findInPageBridge; |
- mTab = tab; |
- mTab.getContentViewCore().getContainerView().addView( |
- this, new FrameLayout.LayoutParams(mBarTouchWidth, |
- ViewGroup.LayoutParams.MATCH_PARENT, Gravity.END)); |
- setTranslationX( |
- MathUtils.flipSignIf(mBarTouchWidth, LocalizationUtils.isLayoutRtl())); |
- |
- mVisibilityAnimation = ObjectAnimator.ofFloat(this, TRANSLATION_X, 0); |
- mVisibilityAnimation.setDuration(VISIBILTY_ANIMATION_DURATION_MS); |
- mVisibilityAnimation.setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE); |
- mTab.getWindowAndroid().startAnimationOverContent(mVisibilityAnimation); |
- } |
- |
- /** Dismisses this results bar by removing it from the view hierarchy. */ |
- public void dismiss() { |
- mDismissing = true; |
- if (mVisibilityAnimation != null && mVisibilityAnimation.isRunning()) { |
- mVisibilityAnimation.cancel(); |
- } |
- |
- mVisibilityAnimation = ObjectAnimator.ofFloat(this, TRANSLATION_X, |
- MathUtils.flipSignIf(mBarTouchWidth, LocalizationUtils.isLayoutRtl())); |
- mVisibilityAnimation.setDuration(VISIBILTY_ANIMATION_DURATION_MS); |
- mVisibilityAnimation.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); |
- mTab.getWindowAndroid().startAnimationOverContent(mVisibilityAnimation); |
- mVisibilityAnimation.addListener(new AnimatorListenerAdapter() { |
- @Override |
- public void onAnimationEnd(Animator animation) { |
- super.onAnimationEnd(animation); |
- |
- if (getParent() != null) ((ViewGroup) getParent()).removeView(FindResultBar.this); |
- } |
- }); |
- } |
- |
- /** Setup the tickmarks to draw using the rects of the find results. */ |
- public void setMatchRects(int version, RectF[] rects, RectF activeRect) { |
- if (mRectsVersion != version) { |
- mRectsVersion = version; |
- assert rects != null; |
- mMatches = rects; |
- mTickmarks.clear(); |
- Arrays.sort(mMatches, sComparator); |
- mBarHeightForWhichTickmarksWereCached = -1; |
- } |
- mActiveMatch = activeRect; // Can be null. |
- invalidate(); |
- } |
- |
- /** Clears the tickmarks. */ |
- public void clearMatchRects() { |
- setMatchRects(-1, new RectF[0], null); |
- } |
- |
- @Override |
- @SuppressLint("ClickableViewAccessibility") |
- public boolean onTouchEvent(MotionEvent event) { |
- if (!mDismissing && mTickmarks.size() > 0 && mTickmarks.size() == mMatches.length |
- && !mWaitingForActivateAck && event.getAction() != MotionEvent.ACTION_CANCEL) { |
- // We decided it's more important to get the keyboard out of the |
- // way asap; the user can compensate if their next MotionEvent |
- // scrolls somewhere unintended. |
- UiUtils.hideKeyboard(this); |
- |
- // Identify which drawn tickmark is closest to the user's finger. |
- int closest = Collections.binarySearch(mTickmarks, |
- new Tickmark(event.getY(), event.getY())); |
- if (closest < 0) { |
- // No exact match, so must determine nearest. |
- int insertionPoint = -1 - closest; |
- if (insertionPoint == 0) { |
- closest = 0; |
- } else if (insertionPoint == mTickmarks.size()) { |
- closest = mTickmarks.size() - 1; |
- } else { |
- float distanceA = Math.abs(event.getY() |
- - mTickmarks.get(insertionPoint - 1).centerY()); |
- float distanceB = Math.abs(event.getY() |
- - mTickmarks.get(insertionPoint).centerY()); |
- closest = insertionPoint - (distanceA <= distanceB ? 1 : 0); |
- } |
- } |
- |
- // Now activate the find match corresponding to that tickmark. |
- // Since mTickmarks may be outdated, we can't just pass the index. |
- // Instead we send the renderer the coordinates of the center of the |
- // find match's rect (as originally received in setMatchRects), and |
- // it will activate whatever find result is currently closest to |
- // that point (which will usually be the same one). |
- mWaitingForActivateAck = true; |
- mFindInPageBridge.activateNearestFindResult( |
- mMatches[closest].centerX(), |
- mMatches[closest].centerY()); |
- } |
- return true; // Consume the event, whether or not we acted upon it. |
- } |
- |
- @Override |
- protected void onSizeChanged(int w, int h, int oldw, int oldh) { |
- super.onSizeChanged(w, h, oldw, oldh); |
- // Check for new rects, as they may move if the document size changes. |
- if (!mDismissing && mMatches.length > 0) { |
- mFindInPageBridge.requestFindMatchRects(mRectsVersion); |
- } |
- } |
- |
- @Override |
- protected void onDraw(Canvas canvas) { |
- super.onDraw(canvas); |
- |
- int leftMargin = getLeftMargin(); |
- mFillPaint.setColor(mBackgroundColor); |
- mStrokePaint.setColor(mBackgroundBorderColor); |
- canvas.drawRect(leftMargin, 0, |
- leftMargin + mBarDrawWidth, getHeight(), mFillPaint); |
- float lineX = LocalizationUtils.isLayoutRtl() |
- ? leftMargin + mBarDrawWidth - 0.5f |
- : leftMargin + 0.5f; |
- canvas.drawLine(lineX, 0, lineX, getHeight(), mStrokePaint); |
- |
- if (mMatches.length == 0) { |
- return; |
- } |
- |
- if (mBarHeightForWhichTickmarksWereCached != getHeight()) { |
- calculateTickmarks(); |
- } |
- |
- // Draw all matches (since they're sorted by increasing y-position |
- // overlapping tickmarks will form nice stacks). |
- mFillPaint.setColor(mResultColor); |
- mStrokePaint.setColor(mResultBorderColor); |
- for (Tickmark tickmark : mTickmarks) { |
- RectF rect = tickmark.toRectF(); |
- canvas.drawRoundRect(rect, 2, 2, mFillPaint); |
- canvas.drawRoundRect(rect, 2, 2, mStrokePaint); |
- } |
- |
- // Draw the active tickmark on top (covering up the inactive tickmark |
- // we probably already drew for it). |
- if (mActiveMatch != null) { |
- Tickmark tickmark; |
- int i = Arrays.binarySearch(mMatches, mActiveMatch, sComparator); |
- if (i >= 0) { |
- // We've already generated a tickmark for all rects in mMatches, |
- // so use the corresponding one. However it was generated |
- // assuming the match would be inactive. Keep the position, but |
- // re-expand it using mActiveMinHeight. |
- tickmark = expandTickmarkToMinHeight(mTickmarks.get(i), true); |
- } else { |
- // How strange - mActiveMatch isn't in mMatches. Do our best to |
- // draw it anyway (though it might not line up exactly). |
- tickmark = tickmarkForRect(mActiveMatch, true); |
- } |
- RectF rect = tickmark.toRectF(); |
- mFillPaint.setColor(mActiveColor); |
- mStrokePaint.setColor(mActiveBorderColor); |
- canvas.drawRoundRect(rect, 2, 2, mFillPaint); |
- canvas.drawRoundRect(rect, 2, 2, mStrokePaint); |
- } |
- } |
- |
- private int getLeftMargin() { |
- return LocalizationUtils.isLayoutRtl() ? 0 : getWidth() - mBarDrawWidth; |
- } |
- |
- private void calculateTickmarks() { |
- // TODO(johnme): Simplify calculation, and switch to integer arithmetic |
- // where possible (tickmarks within groups will still need fractional |
- // y-positions for anti-aliasing, but the start and end positions of |
- // groups can and should be integer-aligned [will give crisp borders], |
- // and the intermediary logic uses more floats than necessary). |
- // TODO(johnme): Consider adding unit tests for this. |
- |
- mBarHeightForWhichTickmarksWereCached = getHeight(); |
- |
- // Generate tickmarks, neatly clustering any overlapping matches. |
- mTickmarks = new ArrayList<Tickmark>(mMatches.length); |
- int i = 0; |
- Tickmark nextTickmark = tickmarkForRect(mMatches[i], false); |
- float lastGroupEnd = -mMinGapBetweenStacks; |
- while (i < mMatches.length) { |
- // Find next cluster of overlapping tickmarks. |
- List<Tickmark> cluster = new ArrayList<Tickmark>(); |
- cluster.add(nextTickmark); |
- i++; |
- while (i < mMatches.length) { |
- nextTickmark = tickmarkForRect(mMatches[i], false); |
- if (nextTickmark.mTop <= cluster.get(cluster.size() - 1).mBottom |
- + mMinGapBetweenStacks) { |
- cluster.add(nextTickmark); |
- i++; |
- } else { |
- break; |
- } |
- } |
- |
- // Draw cluster. |
- int cn = cluster.size(); |
- float minStart = lastGroupEnd + mMinGapBetweenStacks; |
- lastGroupEnd = cluster.get(cn - 1).mBottom; |
- float preferredStart = lastGroupEnd |
- - (cn - 1) * mStackedResultHeight |
- - mResultMinHeight; |
- float maxStart = cluster.get(0).mTop; |
- float start = Math.round(MathUtils.clamp(preferredStart, minStart, maxStart)); |
- float scale = start >= preferredStart ? 1.0f : |
- (lastGroupEnd - start) / (lastGroupEnd - preferredStart); |
- float spacing = cn == 1 ? 0 : (lastGroupEnd - start |
- - scale * mResultMinHeight) / (cn - 1); |
- for (int j = 0; j < cn; j++) { |
- Tickmark tickmark = cluster.get(j); |
- tickmark.mTop = start + j * spacing; |
- if (j != cn - 1) { |
- tickmark.mBottom = tickmark.mTop + scale * mResultMinHeight; |
- } |
- mTickmarks.add(tickmark); |
- } |
- } |
- } |
- |
- private Tickmark tickmarkForRect(RectF r, boolean active) { |
- // Ratio of results bar height to page height |
- float vScale = mBarHeightForWhichTickmarksWereCached - 2 * mBarVerticalPadding; |
- Tickmark tickmark = new Tickmark( |
- r.top * vScale + mBarVerticalPadding, |
- r.bottom * vScale + mBarVerticalPadding); |
- return expandTickmarkToMinHeight(tickmark, active); |
- } |
- |
- private Tickmark expandTickmarkToMinHeight(Tickmark tickmark, |
- boolean active) { |
- int minHeight = active ? mActiveMinHeight : mResultMinHeight; |
- float missingHeight = minHeight - tickmark.height(); |
- if (missingHeight > 0) { |
- return new Tickmark(tickmark.mTop - missingHeight / 2.0f, |
- tickmark.mBottom + missingHeight / 2.0f); |
- } |
- return tickmark; |
- } |
- |
- /** Like android.graphics.RectF, but without a left or right. */ |
- private class Tickmark implements Comparable<Tickmark> { |
- float mTop; |
- float mBottom; |
- Tickmark(float top, float bottom) { |
- this.mTop = top; |
- this.mBottom = bottom; |
- } |
- float height() { |
- return mBottom - mTop; |
- } |
- float centerY() { |
- return (mTop + mBottom) * 0.5f; |
- } |
- RectF toRectF() { |
- int leftMargin = getLeftMargin(); |
- RectF rect = new RectF(leftMargin, mTop, leftMargin + mBarDrawWidth, mBottom); |
- rect.inset(2.0f, 0.5f); |
- rect.offset(LocalizationUtils.isLayoutRtl() ? -0.5f : 0.5f, 0); |
- return rect; |
- } |
- @SuppressFBWarnings("EQ_COMPARETO_USE_OBJECT_EQUAL") |
- @Override |
- public int compareTo(Tickmark other) { |
- float center = centerY(); |
- float otherCenter = other.centerY(); |
- if (center == otherCenter) return 0; |
- return center > otherCenter ? 1 : -1; |
- } |
- } |
-} |