Commit 07f47ea3 authored by Collin Baker's avatar Collin Baker Committed by Commit Bot

Animate in-product help app menu button highlight

This implements an animated app menu button highlight when an
in-product help promo is showing. A custom InkDropMask is used.

Bug: 909755
Change-Id: Ib282525c8af1cdda416002641332164ba64942e5
Reviewed-on: https://chromium-review.googlesource.com/c/1450671
Commit-Queue: Collin Baker <collinbaker@chromium.org>
Reviewed-by: default avatarPeter Boström <pbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#630552}
parent cf3d5b9e
...@@ -53,7 +53,7 @@ void ReopenTabPromoController::OnTabReopened(int command_id) { ...@@ -53,7 +53,7 @@ void ReopenTabPromoController::OnTabReopened(int command_id) {
iph_service_->TabReopened(); iph_service_->TabReopened();
if (command_id == AppMenuModel::kMinRecentTabsCommandId) { if (command_id == AppMenuModel::kMinRecentTabsCommandId) {
DCHECK_EQ(StepAtDismissal::kBubbleShown, promo_step_); DCHECK_EQ(StepAtDismissal::kMenuOpened, promo_step_);
promo_step_ = StepAtDismissal::kTabReopened; promo_step_ = StepAtDismissal::kTabReopened;
} }
} }
...@@ -71,6 +71,9 @@ void ReopenTabPromoController::AppMenuShown() { ...@@ -71,6 +71,9 @@ void ReopenTabPromoController::AppMenuShown() {
// Close the promo bubble since it doesn't automatically close on click. // Close the promo bubble since it doesn't automatically close on click.
promo_bubble_->GetWidget()->Close(); promo_bubble_->GetWidget()->Close();
// Stop showing promo on app menu button.
browser_view_->toolbar()->app_menu_button()->SetPromoFeature(base::nullopt);
promo_step_ = StepAtDismissal::kMenuOpened; promo_step_ = StepAtDismissal::kMenuOpened;
} }
......
...@@ -32,12 +32,16 @@ ...@@ -32,12 +32,16 @@
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "ui/base/theme_provider.h" #include "ui/base/theme_provider.h"
#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_features.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h" #include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h" #include "ui/gfx/color_utils.h"
#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/paint_vector_icon.h"
#include "ui/views/animation/ink_drop.h" #include "ui/views/animation/ink_drop.h"
#include "ui/views/animation/ink_drop_highlight.h" #include "ui/views/animation/ink_drop_highlight.h"
#include "ui/views/animation/ink_drop_mask.h"
#include "ui/views/animation/ink_drop_state.h" #include "ui/views/animation/ink_drop_state.h"
#include "ui/views/controls/button/label_button_border.h" #include "ui/views/controls/button/label_button_border.h"
#include "ui/views/metrics.h" #include "ui/views/metrics.h"
...@@ -58,6 +62,65 @@ namespace { ...@@ -58,6 +62,65 @@ namespace {
// maybe move this into theme system. // maybe move this into theme system.
constexpr SkColor kFeaturePromoHighlightColor = gfx::kGoogleBlue600; constexpr SkColor kFeaturePromoHighlightColor = gfx::kGoogleBlue600;
// Cycle duration of ink drop pulsing animation used for in-product help.
constexpr base::TimeDelta kFeaturePromoPulseDuration =
base::TimeDelta::FromMilliseconds(800);
// Max inset for pulsing animation.
constexpr float kFeaturePromoPulseInsetDip = 3.0f;
// An InkDropMask used to animate the size of the BrowserAppMenuButton's ink
// drop. This is used when showing in-product help.
class PulsingInkDropMask : public gfx::AnimationDelegate,
public views::InkDropMask {
public:
PulsingInkDropMask(const gfx::Size& layer_size,
float normal_corner_radius,
float max_inset)
: views::InkDropMask(layer_size),
normal_corner_radius_(normal_corner_radius),
max_inset_(max_inset),
throb_animation_(this) {
throb_animation_.SetThrobDuration(
kFeaturePromoPulseDuration.InMilliseconds());
throb_animation_.StartThrobbing(-1);
}
private:
// views::InkDropMask:
void OnPaintLayer(const ui::PaintContext& context) override {
cc::PaintFlags flags;
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setAntiAlias(true);
ui::PaintRecorder recorder(context, layer()->size());
gfx::RectF bounds(layer()->bounds());
const float current_inset =
throb_animation_.CurrentValueBetween(0.0f, max_inset_);
bounds.Inset(gfx::InsetsF(current_inset));
const float corner_radius = normal_corner_radius_ - current_inset;
recorder.canvas()->DrawRoundRect(bounds, corner_radius, flags);
}
// gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override {
DCHECK_EQ(animation, &throb_animation_);
layer()->SchedulePaint(gfx::Rect(layer()->size()));
}
// Normal corner radius of the ink drop without animation. This is also the
// corner radius at the largest instant of the animation.
const float normal_corner_radius_;
// Max inset, used at the smallest instant of the animation.
const float max_inset_;
gfx::ThrobAnimation throb_animation_;
};
} // namespace } // namespace
#endif #endif
...@@ -106,11 +169,30 @@ void BrowserAppMenuButton::SetPromoFeature( ...@@ -106,11 +169,30 @@ void BrowserAppMenuButton::SetPromoFeature(
return; return;
promo_feature_ = promo_feature; promo_feature_ = promo_feature;
// We override GetInkDropBaseColor below when |promo_feature_| is non-null.
// This sets the ink drop into the activated state, which will highlight it in // We override GetInkDropBaseColor() and CreateInkDropMask(), returning the
// the desired color. // promo values if we are showing an in-product help promo. Calling
GetInkDrop()->AnimateToState(promo_feature_ ? views::InkDropState::ACTIVATED // HostSizeChanged() will force the new mask and color to be fetched.
: views::InkDropState::HIDDEN); //
// TODO(collinbaker): Consider adding explicit way to recreate mask instead of
// relying on HostSizeChanged() to do so.
GetInkDrop()->HostSizeChanged(size());
views::InkDropState next_state;
if (promo_feature_ || IsMenuShowing()) {
// If we are showing a promo, we must use the ACTIVATED state to show the
// highlight. Otherwise, if the menu is currently showing, we need to keep
// the ink drop in the ACTIVATED state.
next_state = views::InkDropState::ACTIVATED;
} else {
// If we are not showing a promo and the menu is hidden, we use the
// DEACTIVATED state.
next_state = views::InkDropState::DEACTIVATED;
// TODO(collinbaker): this is brittle since we don't know if something else
// should keep this ACTIVATED or in some other state. Consider adding code
// to track the correct state and restore to that.
}
GetInkDrop()->AnimateToState(next_state);
UpdateIcon(); UpdateIcon();
SchedulePaint(); SchedulePaint();
...@@ -293,6 +375,20 @@ BrowserAppMenuButton::CreateInkDropHighlight() const { ...@@ -293,6 +375,20 @@ BrowserAppMenuButton::CreateInkDropHighlight() const {
return CreateToolbarInkDropHighlight(this); return CreateToolbarInkDropHighlight(this);
} }
std::unique_ptr<views::InkDropMask> BrowserAppMenuButton::CreateInkDropMask()
const {
#if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP)
if (promo_feature_) {
const float corner_radius = height() / 2.0f;
return std::make_unique<PulsingInkDropMask>(ink_drop_container()->size(),
corner_radius,
kFeaturePromoPulseInsetDip);
}
#endif
return AppMenuButton::CreateInkDropMask();
}
SkColor BrowserAppMenuButton::GetInkDropBaseColor() const { SkColor BrowserAppMenuButton::GetInkDropBaseColor() const {
#if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP) #if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP)
if (promo_feature_) if (promo_feature_)
......
...@@ -83,6 +83,7 @@ class BrowserAppMenuButton : public AppMenuButton, ...@@ -83,6 +83,7 @@ class BrowserAppMenuButton : public AppMenuButton,
int OnPerformDrop(const ui::DropTargetEvent& event) override; int OnPerformDrop(const ui::DropTargetEvent& event) override;
std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
const override; const override;
std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override;
SkColor GetInkDropBaseColor() const override; SkColor GetInkDropBaseColor() const override;
AppMenuIconController::TypeAndSeverity type_and_severity_{ AppMenuIconController::TypeAndSeverity type_and_severity_{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment