Index: chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchImageControl.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchImageControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchImageControl.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e2f24f919c82a9f714f6427260b7226de6869112 |
--- /dev/null |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchImageControl.java |
@@ -0,0 +1,205 @@ |
+// Copyright 2016 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.compositor.bottombar.contextualsearch; |
+ |
+import android.content.Context; |
+import android.support.v4.view.animation.PathInterpolatorCompat; |
+import android.text.TextUtils; |
+import android.view.animation.Interpolator; |
+ |
+import org.chromium.chrome.R; |
+import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelAnimation; |
+import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; |
+ |
+/** |
+ * Controls the image shown in the Bar. Owns the {@link ContextualSearchIconSpriteControl} and |
+ * details about the thumbnail, and handles animating between the two. |
+ */ |
+public class ContextualSearchImageControl |
+ implements ChromeAnimation.Animatable<ContextualSearchImageControl.AnimationType> { |
+ /** |
+ * Animation properties. |
+ */ |
+ protected enum AnimationType { |
+ THUMBNAIL_VISIBILITY |
+ } |
+ |
+ /** The current context. */ |
+ private final Context mContext; |
+ |
+ /** The OverlayPanelAnimation used to add animations. */ |
+ private final OverlayPanelAnimation mOverlayPanelAnimation; |
+ |
+ public ContextualSearchImageControl(OverlayPanelAnimation overlayPanelAnimation, |
+ Context context) { |
+ mContext = context; |
+ mOverlayPanelAnimation = overlayPanelAnimation; |
+ } |
+ |
+ // ============================================================================================ |
+ // Search Provider Icon Sprite |
+ // ============================================================================================ |
+ |
+ private ContextualSearchIconSpriteControl mIconSpriteControl; |
+ |
+ /** |
+ * @return The {@link ContextualSearchIconSpriteControl} for the panel. |
+ */ |
+ public ContextualSearchIconSpriteControl getIconSpriteControl() { |
+ if (mIconSpriteControl == null) { |
+ mIconSpriteControl = |
+ new ContextualSearchIconSpriteControl(mOverlayPanelAnimation, mContext); |
+ } |
+ return mIconSpriteControl; |
+ } |
+ |
+ /** |
+ * @param shouldAnimateIconSprite Whether the search provider icon sprite should be animated. |
+ */ |
+ public void setShouldAnimateIconSprite(boolean shouldAnimateIconSprite) { |
+ getIconSpriteControl().setShouldAnimateAppearance(shouldAnimateIconSprite); |
+ } |
+ |
+ // ============================================================================================ |
+ // Thumbnail |
+ // ============================================================================================ |
+ |
+ /** |
+ * The URL of the thumbnail to display. |
+ */ |
+ private String mThumbnailUrl; |
+ |
+ /** |
+ * The height and width of the thumbnail. |
+ */ |
+ private int mThumbnailSize; |
+ |
+ /** |
+ * Whether the thumbnail is visible. |
+ */ |
+ private boolean mThumbnailVisible; |
+ |
+ /** |
+ * The thumbnail visibility percentage, which dictates how and where to draw the thumbnail. |
+ * The thumbnail is not visible at all at 0.f and completely visible at 1.f. |
+ */ |
+ private float mThumbnailVisibilityPercentage = 0.f; |
+ |
+ /** |
+ * @param thumbnailUrl The URL of the thumbnail to display |
+ */ |
+ public void setThumbnailUrl(String thumbnailUrl) { |
+ mThumbnailUrl = thumbnailUrl; |
+ } |
+ |
+ /** |
+ * @return The URL used to fetch a thumbnail to display in the Bar. Will return an empty string |
+ * if no thumbnail is available. |
+ */ |
+ public String getThumbnailUrl() { |
+ return mThumbnailUrl != null ? mThumbnailUrl : ""; |
+ } |
+ |
+ /** |
+ * Hides the thumbnail if it is visible and makes the icon sprite visible. Also resets the |
+ * thumbnail URL. |
+ * @param animate Whether hiding the thumbnail should be animated. |
+ */ |
+ public void hideThumbnail(boolean animate) { |
+ getIconSpriteControl().setIsVisible(true); |
+ if (mThumbnailVisible && animate) { |
+ animateThumbnailVisibility(false); |
+ } else { |
+ mOverlayPanelAnimation.cancelAnimation(this, AnimationType.THUMBNAIL_VISIBILITY); |
+ onThumbnailHidden(); |
+ } |
+ } |
+ |
+ /** |
+ * @return The height and width of the thumbnail in px. |
+ */ |
+ public int getThumbnailSize() { |
+ if (mThumbnailSize == 0) { |
+ mThumbnailSize = mContext.getResources().getDimensionPixelSize( |
+ R.dimen.contextual_search_thumbnail_size); |
+ } |
+ return mThumbnailSize; |
+ } |
+ |
+ /** |
+ * @return Whether the thumbnail is visible. |
+ */ |
+ public boolean getThumbnailVisible() { |
+ return mThumbnailVisible; |
+ } |
+ |
+ /** |
+ * @return The thumbnail visibility percentage, which dictates how and where to draw the |
+ * thumbnail. The thumbnail is not visible at all at 0.f and completely visible at 1.f. |
+ */ |
+ public float getThumbnailVisibilityPercentage() { |
+ return mThumbnailVisibilityPercentage; |
+ } |
+ |
+ /** |
+ * Called when the thumbnail has finished being fetched. |
+ * @param success Whether fetching the thumbnail was successful. |
+ */ |
+ public void onThumbnailFetched(boolean success) { |
+ // Check if the thumbnail URL was cleared before the thumbnail fetch completed. This may |
+ // occur if the user taps to refine the search. |
+ mThumbnailVisible = success && !TextUtils.isEmpty(mThumbnailUrl); |
+ if (!mThumbnailVisible) return; |
+ |
+ // TODO(twellington): if the icon sprite is animating wait to start the thumbnail visibility |
+ // animation. |
+ animateThumbnailVisibility(true); |
+ } |
+ |
+ private void onThumbnailHidden() { |
+ mThumbnailUrl = ""; |
+ mThumbnailVisible = false; |
+ getIconSpriteControl().setIsVisible(true); |
+ mThumbnailVisibilityPercentage = 0.f; |
+ } |
+ |
+ // ============================================================================================ |
+ // Thumbnail Animation |
+ // ============================================================================================ |
+ |
+ private Interpolator mThumbnailVisibilityInterpolator; |
+ |
+ private void animateThumbnailVisibility(boolean visible) { |
+ if (mThumbnailVisibilityInterpolator == null) { |
+ mThumbnailVisibilityInterpolator = PathInterpolatorCompat.create(0.4f, 0.f, 0.6f, 1.f); |
+ } |
+ |
+ mOverlayPanelAnimation.cancelAnimation(this, AnimationType.THUMBNAIL_VISIBILITY); |
+ |
+ float endValue = visible ? 1.f : 0.f; |
+ mOverlayPanelAnimation.addToAnimation(this, AnimationType.THUMBNAIL_VISIBILITY, |
+ mThumbnailVisibilityPercentage, endValue, |
+ OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, 0, false, |
+ mThumbnailVisibilityInterpolator); |
+ } |
+ |
+ @Override |
+ public void setProperty(AnimationType prop, float val) { |
+ if (prop == AnimationType.THUMBNAIL_VISIBILITY) { |
+ mThumbnailVisibilityPercentage = val; |
+ } |
+ } |
+ |
+ @Override |
+ public void onPropertyAnimationFinished(AnimationType prop) { |
+ if (prop == AnimationType.THUMBNAIL_VISIBILITY) { |
+ if (mThumbnailVisibilityPercentage == 0.f) { |
+ onThumbnailHidden(); |
+ } else { |
+ getIconSpriteControl().setIsVisible(false); |
+ } |
+ } |
+ } |
+ |
+} |