Commit fd572db8 authored by Jan Krcal's avatar Jan Krcal Committed by Commit Bot

[Avatar button] Keep the email shown while parent is highlighted

This CL keeps the user email shown also if parent container is focused
or hovered. It introduces a notification from the container towards the
avatar button when the highlight state changes.

In a follow-up CL the same notification will also be used to hide the
border of the button.

Bug: 967317
Change-Id: I80866957d7098c675ad20d7fd03d1f45ad5aeec9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1826678
Commit-Queue: Jan Krcal <jkrcal@chromium.org>
Reviewed-by: default avatarPeter Boström <pbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704595}
parent 2918ebbe
...@@ -113,12 +113,17 @@ const gfx::Image& GetAvatarImage(Profile* profile, ...@@ -113,12 +113,17 @@ const gfx::Image& GetAvatarImage(Profile* profile,
} // namespace } // namespace
AvatarToolbarButton::AvatarToolbarButton(Browser* browser) AvatarToolbarButton::AvatarToolbarButton(Browser* browser)
: AvatarToolbarButton(browser, nullptr) {}
AvatarToolbarButton::AvatarToolbarButton(Browser* browser,
ToolbarIconContainerView* parent)
: ToolbarButton(nullptr), : ToolbarButton(nullptr),
#if !defined(OS_CHROMEOS) #if !defined(OS_CHROMEOS)
error_controller_(this, browser->profile()), error_controller_(this, browser->profile()),
#endif // !defined(OS_CHROMEOS) #endif // !defined(OS_CHROMEOS)
browser_(browser), browser_(browser),
profile_(browser_->profile()) { profile_(browser_->profile()),
parent_(parent) {
profile_observer_.Add(&GetProfileAttributesStorage()); profile_observer_.Add(&GetProfileAttributesStorage());
State state = GetState(); State state = GetState();
...@@ -169,10 +174,19 @@ AvatarToolbarButton::AvatarToolbarButton(Browser* browser) ...@@ -169,10 +174,19 @@ AvatarToolbarButton::AvatarToolbarButton(Browser* browser)
UpdateText(); UpdateText();
md_observer_.Add(ui::MaterialDesignController::GetInstance()); md_observer_.Add(ui::MaterialDesignController::GetInstance());
// TODO(crbug.com/922525): DCHECK(parent_) instead of the if, once we always
// have a parent.
if (parent_)
parent_->AddObserver(this);
} }
AvatarToolbarButton::~AvatarToolbarButton() { AvatarToolbarButton::~AvatarToolbarButton() {
BrowserList::RemoveObserver(this); BrowserList::RemoveObserver(this);
// TODO(crbug.com/922525): Remove the if, once we always have a parent.
if (parent_)
parent_->RemoveObserver(this);
} }
void AvatarToolbarButton::UpdateIcon() { void AvatarToolbarButton::UpdateIcon() {
...@@ -272,10 +286,7 @@ void AvatarToolbarButton::ShowAvatarHighlightAnimation() { ...@@ -272,10 +286,7 @@ void AvatarToolbarButton::ShowAvatarHighlightAnimation() {
void AvatarToolbarButton::NotifyClick(const ui::Event& event) { void AvatarToolbarButton::NotifyClick(const ui::Event& event) {
Button::NotifyClick(event); Button::NotifyClick(event);
if (identity_animation_state_ == MaybeHideIdentityAnimation();
IdentityAnimationState::kShowingUntilNoLongerHoveredOrFocused) {
HideIdentityAnimationWhenNotHoveredOrFocused();
}
// TODO(bsep): Other toolbar buttons have ToolbarView as a listener and let it // TODO(bsep): Other toolbar buttons have ToolbarView as a listener and let it
// call ExecuteCommandWithDisposition on their behalf. Unfortunately, it's not // call ExecuteCommandWithDisposition on their behalf. Unfortunately, it's not
// possible to plumb IsKeyEvent through, so this has to be a special case. // possible to plumb IsKeyEvent through, so this has to be a special case.
...@@ -286,18 +297,12 @@ void AvatarToolbarButton::NotifyClick(const ui::Event& event) { ...@@ -286,18 +297,12 @@ void AvatarToolbarButton::NotifyClick(const ui::Event& event) {
} }
void AvatarToolbarButton::OnMouseExited(const ui::MouseEvent& event) { void AvatarToolbarButton::OnMouseExited(const ui::MouseEvent& event) {
if (identity_animation_state_ == MaybeHideIdentityAnimation();
IdentityAnimationState::kShowingUntilNoLongerHoveredOrFocused) {
HideIdentityAnimationWhenNotHoveredOrFocused();
}
ToolbarButton::OnMouseExited(event); ToolbarButton::OnMouseExited(event);
} }
void AvatarToolbarButton::OnBlur() { void AvatarToolbarButton::OnBlur() {
if (identity_animation_state_ == MaybeHideIdentityAnimation();
IdentityAnimationState::kShowingUntilNoLongerHoveredOrFocused) {
HideIdentityAnimationWhenNotHoveredOrFocused();
}
ToolbarButton::OnBlur(); ToolbarButton::OnBlur();
} }
...@@ -394,42 +399,51 @@ void AvatarToolbarButton::OnTouchUiChanged() { ...@@ -394,42 +399,51 @@ void AvatarToolbarButton::OnTouchUiChanged() {
PreferredSizeChanged(); PreferredSizeChanged();
} }
void AvatarToolbarButton::OnHighlightChanged() {
DCHECK(parent_);
MaybeHideIdentityAnimation();
}
void AvatarToolbarButton::ShowIdentityAnimation() { void AvatarToolbarButton::ShowIdentityAnimation() {
DCHECK_EQ(identity_animation_state_, DCHECK_EQ(identity_animation_state_,
IdentityAnimationState::kWaitingForImage); IdentityAnimationState::kWaitingForImage);
identity_animation_state_ = IdentityAnimationState::kShowing; identity_animation_state_ = IdentityAnimationState::kShowingUntilTimeout;
UpdateText(); UpdateText();
// Hide the pill after a while. // Hide the pill after a while.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, FROM_HERE,
base::BindOnce( base::BindOnce(&AvatarToolbarButton::OnIdentityAnimationTimeout,
&AvatarToolbarButton::HideIdentityAnimationWhenNotHoveredOrFocused, weak_ptr_factory_.GetWeakPtr()),
weak_ptr_factory_.GetWeakPtr()),
kIdentityAnimationDuration); kIdentityAnimationDuration);
} }
void AvatarToolbarButton::HideIdentityAnimationWhenNotHoveredOrFocused() { void AvatarToolbarButton::OnIdentityAnimationTimeout() {
// No-op if it has been reset already. DCHECK_EQ(identity_animation_state_,
if (identity_animation_state_ == IdentityAnimationState::kNotShowing) IdentityAnimationState::kShowingUntilTimeout);
identity_animation_state_ =
IdentityAnimationState::kShowingUntilNoLongerInUse;
MaybeHideIdentityAnimation();
}
void AvatarToolbarButton::MaybeHideIdentityAnimation() {
// No-op if not showing or if the timeout hasn't passed, yet.
if (identity_animation_state_ !=
IdentityAnimationState::kShowingUntilNoLongerInUse) {
return; return;
}
// Keep email visible while hovering or being focused. // Keep identity visible if this button is in use (hovered or has focus) or
if (IsMouseHovered() || HasFocus()) { // if |parent_| is in use (which makes it highlighted). We should not move
// TODO(crbug.com/967317): Include also the case when some other button from // things around when the user wants to click on |this| or another button in
// the parent container is shown and hovered / focused. // |parent_|.
identity_animation_state_ = if (this->IsMouseHovered() || this->HasFocus() ||
IdentityAnimationState::kShowingUntilNoLongerHoveredOrFocused; (parent_ && parent_->IsHighlighted())) {
return; return;
} }
HideIdentityAnimation();
}
void AvatarToolbarButton::HideIdentityAnimation() {
DCHECK_NE(identity_animation_state_, IdentityAnimationState::kNotShowing);
identity_animation_state_ = IdentityAnimationState::kNotShowing; identity_animation_state_ = IdentityAnimationState::kNotShowing;
// Update the text to the pre-shown state. This also makes sure that we now // Update the text to the pre-shown state. This also makes sure that we now
// reflect changes that happened while the identity pill was shown. // reflect changes that happened while the identity pill was shown.
UpdateText(); UpdateText();
...@@ -530,9 +544,10 @@ AvatarToolbarButton::State AvatarToolbarButton::GetState() const { ...@@ -530,9 +544,10 @@ AvatarToolbarButton::State AvatarToolbarButton::GetState() const {
return State::kGenericProfile; return State::kGenericProfile;
} }
if (identity_animation_state_ == IdentityAnimationState::kShowing || if (identity_animation_state_ ==
IdentityAnimationState::kShowingUntilTimeout ||
identity_animation_state_ == identity_animation_state_ ==
IdentityAnimationState::kShowingUntilNoLongerHoveredOrFocused) { IdentityAnimationState::kShowingUntilNoLongerInUse) {
return State::kAnimatedUserIdentity; return State::kAnimatedUserIdentity;
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_list_observer.h" #include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/views/toolbar/toolbar_button.h" #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h"
#include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_manager.h"
#include "ui/base/material_design/material_design_controller.h" #include "ui/base/material_design/material_design_controller.h"
#include "ui/base/material_design/material_design_controller_observer.h" #include "ui/base/material_design/material_design_controller_observer.h"
...@@ -27,9 +28,13 @@ class AvatarToolbarButton : public ToolbarButton, ...@@ -27,9 +28,13 @@ class AvatarToolbarButton : public ToolbarButton,
public BrowserListObserver, public BrowserListObserver,
public ProfileAttributesStorage::Observer, public ProfileAttributesStorage::Observer,
public signin::IdentityManager::Observer, public signin::IdentityManager::Observer,
public ui::MaterialDesignControllerObserver { public ui::MaterialDesignControllerObserver,
ToolbarIconContainerView::Observer {
public: public:
// TODO(crbug.com/922525): Remove this constructor when this button always has
// ToolbarIconContainerView as a parent.
explicit AvatarToolbarButton(Browser* browser); explicit AvatarToolbarButton(Browser* browser);
AvatarToolbarButton(Browser* browser, ToolbarIconContainerView* parent);
~AvatarToolbarButton() override; ~AvatarToolbarButton() override;
void UpdateIcon(); void UpdateIcon();
...@@ -55,8 +60,8 @@ class AvatarToolbarButton : public ToolbarButton, ...@@ -55,8 +60,8 @@ class AvatarToolbarButton : public ToolbarButton,
enum class IdentityAnimationState { enum class IdentityAnimationState {
kNotShowing, kNotShowing,
kWaitingForImage, kWaitingForImage,
kShowing, kShowingUntilTimeout,
kShowingUntilNoLongerHoveredOrFocused kShowingUntilNoLongerInUse
}; };
// ToolbarButton: // ToolbarButton:
...@@ -97,9 +102,12 @@ class AvatarToolbarButton : public ToolbarButton, ...@@ -97,9 +102,12 @@ class AvatarToolbarButton : public ToolbarButton,
// ui::MaterialDesignControllerObserver: // ui::MaterialDesignControllerObserver:
void OnTouchUiChanged() override; void OnTouchUiChanged() override;
// ToolbarIconContainerView::Observer:
void OnHighlightChanged() override;
void ShowIdentityAnimation(); void ShowIdentityAnimation();
void HideIdentityAnimationWhenNotHoveredOrFocused(); void OnIdentityAnimationTimeout();
void HideIdentityAnimation(); void MaybeHideIdentityAnimation();
base::string16 GetAvatarTooltipText() const; base::string16 GetAvatarTooltipText() const;
base::string16 GetProfileName() const; base::string16 GetProfileName() const;
...@@ -126,6 +134,7 @@ class AvatarToolbarButton : public ToolbarButton, ...@@ -126,6 +134,7 @@ class AvatarToolbarButton : public ToolbarButton,
Browser* const browser_; Browser* const browser_;
Profile* const profile_; Profile* const profile_;
ToolbarIconContainerView* const parent_;
// Whether the avatar highlight animation is visible. If true, hide avatar // Whether the avatar highlight animation is visible. If true, hide avatar
// button sync paused/error state and update highlight color. // button sync paused/error state and update highlight color.
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/test_with_browser_view.h" #include "chrome/browser/ui/views/frame/test_with_browser_view.h"
#include "chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.h"
#include "ui/base/theme_provider.h" #include "ui/base/theme_provider.h"
#include "ui/gfx/color_utils.h" #include "ui/gfx/color_utils.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
...@@ -18,7 +19,8 @@ class AvatarToolbarButtonTest : public TestWithBrowserView {}; ...@@ -18,7 +19,8 @@ class AvatarToolbarButtonTest : public TestWithBrowserView {};
#if !defined(OS_CHROMEOS) #if !defined(OS_CHROMEOS)
TEST_F(AvatarToolbarButtonTest, HighlightMeetsMinimumContrast) { TEST_F(AvatarToolbarButtonTest, HighlightMeetsMinimumContrast) {
auto button = std::make_unique<AvatarToolbarButton>(browser()); auto parent = std::make_unique<ToolbarIconContainerView>(browser());
auto button = std::make_unique<AvatarToolbarButton>(browser(), parent.get());
button->set_owned_by_client(); button->set_owned_by_client();
browser_view()->GetWidget()->GetContentsView()->AddChildView(button.get()); browser_view()->GetWidget()->GetContentsView()->AddChildView(button.get());
......
...@@ -24,7 +24,7 @@ ToolbarAccountIconContainerView::ToolbarAccountIconContainerView( ...@@ -24,7 +24,7 @@ ToolbarAccountIconContainerView::ToolbarAccountIconContainerView(
Browser* browser) Browser* browser)
: ToolbarIconContainerView( : ToolbarIconContainerView(
/*uses_highlight=*/!browser->profile()->IsIncognitoProfile()), /*uses_highlight=*/!browser->profile()->IsIncognitoProfile()),
avatar_(new AvatarToolbarButton(browser)), avatar_(new AvatarToolbarButton(browser, this)),
browser_(browser) { browser_(browser) {
PageActionIconContainerView::Params params; PageActionIconContainerView::Params params;
params.types_enabled = { params.types_enabled = {
......
...@@ -41,6 +41,14 @@ void ToolbarIconContainerView::AddMainButton(views::Button* main_button) { ...@@ -41,6 +41,14 @@ void ToolbarIconContainerView::AddMainButton(views::Button* main_button) {
AddChildView(main_button_); AddChildView(main_button_);
} }
void ToolbarIconContainerView::AddObserver(Observer* obs) {
observers_.AddObserver(obs);
}
void ToolbarIconContainerView::RemoveObserver(const Observer* obs) {
observers_.RemoveObserver(obs);
}
void ToolbarIconContainerView::OnHighlightChanged( void ToolbarIconContainerView::OnHighlightChanged(
views::Button* observed_button, views::Button* observed_button,
bool highlighted) { bool highlighted) {
...@@ -115,11 +123,22 @@ bool ToolbarIconContainerView::ShouldDisplayHighlight() { ...@@ -115,11 +123,22 @@ bool ToolbarIconContainerView::ShouldDisplayHighlight() {
} }
void ToolbarIconContainerView::UpdateHighlight() { void ToolbarIconContainerView::UpdateHighlight() {
bool showing_before = highlight_animation_.IsShowing();
if (ShouldDisplayHighlight()) { if (ShouldDisplayHighlight()) {
highlight_animation_.Show(); highlight_animation_.Show();
} else { } else {
highlight_animation_.Hide(); highlight_animation_.Hide();
} }
if (showing_before == highlight_animation_.IsShowing())
return;
for (Observer& observer : observers_)
observer.OnHighlightChanged();
}
bool ToolbarIconContainerView::IsHighlighted() {
return ShouldDisplayHighlight();
} }
void ToolbarIconContainerView::SetHighlightBorder() { void ToolbarIconContainerView::SetHighlightBorder() {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_ICON_CONTAINER_VIEW_H_ #define CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_ICON_CONTAINER_VIEW_H_
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.h"
#include "ui/gfx/animation/animation_delegate.h" #include "ui/gfx/animation/animation_delegate.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/button_observer.h" #include "ui/views/controls/button/button_observer.h"
...@@ -17,6 +18,11 @@ class ToolbarIconContainerView : public views::View, ...@@ -17,6 +18,11 @@ class ToolbarIconContainerView : public views::View,
public views::ButtonObserver, public views::ButtonObserver,
public views::ViewObserver { public views::ViewObserver {
public: public:
class Observer : public base::CheckedObserver {
public:
virtual void OnHighlightChanged() = 0;
};
explicit ToolbarIconContainerView(bool uses_highlight); explicit ToolbarIconContainerView(bool uses_highlight);
~ToolbarIconContainerView() override; ~ToolbarIconContainerView() override;
...@@ -26,6 +32,11 @@ class ToolbarIconContainerView : public views::View, ...@@ -26,6 +32,11 @@ class ToolbarIconContainerView : public views::View,
// Adds the RHS child as well as setting its margins. // Adds the RHS child as well as setting its margins.
void AddMainButton(views::Button* main_button); void AddMainButton(views::Button* main_button);
void AddObserver(Observer* obs);
void RemoveObserver(const Observer* obs);
bool IsHighlighted();
// views::ButtonObserver: // views::ButtonObserver:
void OnHighlightChanged(views::Button* observed_button, void OnHighlightChanged(views::Button* observed_button,
bool highlighted) override; bool highlighted) override;
...@@ -68,6 +79,8 @@ class ToolbarIconContainerView : public views::View, ...@@ -68,6 +79,8 @@ class ToolbarIconContainerView : public views::View,
// Fade-in/out animation for the highlight border. // Fade-in/out animation for the highlight border.
gfx::SlideAnimation highlight_animation_{this}; gfx::SlideAnimation highlight_animation_{this};
base::ObserverList<Observer> observers_;
DISALLOW_COPY_AND_ASSIGN(ToolbarIconContainerView); DISALLOW_COPY_AND_ASSIGN(ToolbarIconContainerView);
}; };
......
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