Commit fa5fb125 authored by Olesia Marukhno's avatar Olesia Marukhno Committed by Chromium LUCI CQ

Separate UI component from PermissionChip

Change-Id: If80df7991f4499fd913787db66da5121f0900d32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2587019
Commit-Queue: Olesia Marukhno <olesiamarukhno@google.com>
Reviewed-by: default avatarBret Sepulveda <bsep@chromium.org>
Cr-Commit-Position: refs/heads/master@{#845121}
parent 4a498d8c
......@@ -3775,6 +3775,8 @@ static_library("ui") {
"views/location_bar/location_bar_view.h",
"views/location_bar/location_icon_view.cc",
"views/location_bar/location_icon_view.h",
"views/location_bar/omnibox_chip_button.cc",
"views/location_bar/omnibox_chip_button.h",
"views/location_bar/permission_chip.cc",
"views/location_bar/permission_chip.h",
"views/location_bar/selected_keyword_view.cc",
......
// Copyright 2020 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.
#include "chrome/browser/ui/views/location_bar/omnibox_chip_button.h"
#include "base/location.h"
#include "base/time/time.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/controls/highlight_path_generator.h"
OmniboxChipButton::OmniboxChipButton(PressedCallback callback,
int button_context)
: MdTextButton(std::move(callback), base::string16(), button_context) {
views::InstallPillHighlightPathGenerator(this);
SetProminent(true);
SetCornerRadius(GetIconSize());
SetHorizontalAlignment(gfx::ALIGN_LEFT);
SetElideBehavior(gfx::ElideBehavior::FADE_TAIL);
SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
// Equalizing padding on the left, right and between icon and label.
SetImageLabelSpacing(
GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left());
SetCustomPadding(
gfx::Insets(GetLayoutConstant(LOCATION_BAR_CHILD_INTERIOR_PADDING),
GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left()));
constexpr auto kAnimationDuration = base::TimeDelta::FromMilliseconds(350);
animation_ = std::make_unique<gfx::SlideAnimation>(this);
animation_->SetSlideDuration(kAnimationDuration);
}
OmniboxChipButton::~OmniboxChipButton() = default;
void OmniboxChipButton::AnimateCollapse() {
constexpr auto kAnimationDuration = base::TimeDelta::FromMilliseconds(250);
animation_->SetSlideDuration(kAnimationDuration);
animation_->Hide();
}
void OmniboxChipButton::AnimateExpand() {
constexpr auto kAnimationDuration = base::TimeDelta::FromMilliseconds(350);
animation_->SetSlideDuration(kAnimationDuration);
animation_->Show();
}
void OmniboxChipButton::ResetAnimation() {
animation_->Reset();
}
void OmniboxChipButton::SetIcon(const gfx::VectorIcon* icon) {
icon_ = icon;
UpdateIconAndTextColor();
}
void OmniboxChipButton::SetExpandAnimationEndedCallback(
base::RepeatingCallback<void()> callback) {
expand_animation_ended_callback_ = callback;
}
gfx::Size OmniboxChipButton::CalculatePreferredSize() const {
const int fixed_width = GetIconSize() + GetInsets().width();
const int collapsable_width =
label()->GetPreferredSize().width() + GetInsets().right();
const int width =
std::round(collapsable_width * animation_->GetCurrentValue()) +
fixed_width;
return gfx::Size(width, GetHeightForWidth(width));
}
void OmniboxChipButton::OnThemeChanged() {
View::OnThemeChanged();
UpdateIconAndTextColor();
}
void OmniboxChipButton::AnimationEnded(const gfx::Animation* animation) {
if (animation != animation_.get())
return;
is_fully_collapsed_ = animation->GetCurrentValue() != 1.0;
if (animation->GetCurrentValue() == 1.0)
expand_animation_ended_callback_.Run();
}
void OmniboxChipButton::AnimationProgressed(const gfx::Animation* animation) {
if (animation == animation_.get())
PreferredSizeChanged();
}
int OmniboxChipButton::GetIconSize() const {
return GetLayoutConstant(LOCATION_BAR_ICON_SIZE);
}
void OmniboxChipButton::UpdateIconAndTextColor() {
// Set label and icon color to be the same color.
SkColor enabled_text_color = views::style::GetColor(
*this, label()->GetTextContext(),
GetProminent() ? views::style::STYLE_DIALOG_BUTTON_DEFAULT
: views::style::STYLE_PRIMARY);
if (icon_) {
SetEnabledTextColors(enabled_text_color);
SetImageModel(views::Button::STATE_NORMAL,
ui::ImageModel::FromVectorIcon(*icon_, enabled_text_color,
GetIconSize()));
}
}
// Copyright 2020 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.
#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_OMNIBOX_CHIP_BUTTON_H_
#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_OMNIBOX_CHIP_BUTTON_H_
#include "ui/gfx/animation/slide_animation.h"
#include "ui/views/controls/button/md_text_button.h"
// UI component for chip button located in the omnibox. A button with an icon
// and text, with rounded corners.
class OmniboxChipButton : public views::MdTextButton {
public:
explicit OmniboxChipButton(
PressedCallback callback,
int button_context = views::style::CONTEXT_BUTTON_MD);
OmniboxChipButton(const OmniboxChipButton& button) = delete;
OmniboxChipButton& operator=(const OmniboxChipButton& button) = delete;
~OmniboxChipButton() override;
void AnimateCollapse();
void AnimateExpand();
void ResetAnimation();
void SetIcon(const gfx::VectorIcon* icon);
void SetExpandAnimationEndedCallback(
base::RepeatingCallback<void()> callback);
bool is_fully_collapsed() { return is_fully_collapsed_; }
// views::AnimationDelegateViews:
void AnimationEnded(const gfx::Animation* animation) override;
void AnimationProgressed(const gfx::Animation* animation) override;
// views::MdTextButton:
gfx::Size CalculatePreferredSize() const override;
void OnThemeChanged() override;
private:
int GetIconSize() const;
void UpdateIconAndTextColor();
// An animation used for expanding and collapsing the chip.
std::unique_ptr<gfx::SlideAnimation> animation_;
// If chip is collapsed. In the collapsed state, only an icon is visible,
// without text.
bool is_fully_collapsed_ = false;
const gfx::VectorIcon* icon_ = nullptr;
base::RepeatingCallback<void()> expand_animation_ended_callback_;
};
#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_OMNIBOX_CHIP_BUTTON_H_
......@@ -4,37 +4,21 @@
#include "chrome/browser/ui/views/location_bar/permission_chip.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.h"
#include "chrome/browser/ui/views/permission_bubble/permission_prompt_style.h"
#include "chrome/grit/generated_resources.h"
#include "components/permissions/permission_request.h"
#include "components/permissions/request_type.h"
#include "components/strings/grit/components_strings.h"
#include "components/vector_icons/vector_icons.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/events/event.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/button_controller.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/style/typography.h"
#include "ui/views/widget/widget.h"
namespace {
......@@ -79,32 +63,21 @@ class BubbleButtonController : public views::ButtonController {
BubbleOwnerDelegate* bubble_owner_ = nullptr;
};
PermissionChip::PermissionChip(Browser* browser)
: views::AnimationDelegateViews(this), browser_(browser) {
PermissionChip::PermissionChip(Browser* browser) : browser_(browser) {
SetLayoutManager(std::make_unique<views::FillLayout>());
SetVisible(false);
chip_button_ =
AddChildView(std::make_unique<views::MdTextButton>(base::BindRepeating(
AddChildView(std::make_unique<OmniboxChipButton>(base::BindRepeating(
&PermissionChip::ChipButtonPressed, base::Unretained(this))));
chip_button_->SetProminent(true);
chip_button_->SetCornerRadius(GetIconSize());
chip_button_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
chip_button_->SetElideBehavior(gfx::ElideBehavior::FADE_TAIL);
chip_button_->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
// Equalizing padding on the left, right and between icon and label.
chip_button_->SetImageLabelSpacing(
GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left());
chip_button_->SetCustomPadding(
gfx::Insets(GetLayoutConstant(LOCATION_BAR_CHILD_INTERIOR_PADDING),
GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left()));
chip_button_->SetButtonController(std::make_unique<BubbleButtonController>(
chip_button_, this,
std::make_unique<views::Button::DefaultButtonControllerDelegate>(
chip_button_)));
animation_ = std::make_unique<gfx::SlideAnimation>(this);
chip_button_->SetExpandAnimationEndedCallback(base::BindRepeating(
&PermissionChip::StartCollapseTimer, base::Unretained(this)));
}
PermissionChip::~PermissionChip() {
......@@ -131,14 +104,13 @@ void PermissionChip::DisplayRequest(
}
chip_button_->SetText(GetPermissionMessage());
UpdatePermissionIconAndTextColor();
chip_button_->SetIcon(&GetPermissionIconId());
SetVisible(true);
// TODO(olesiamarukhno): Add tests for animation logic.
animation_->Reset();
if (!delegate_->WasCurrentRequestAlreadyDisplayed()) {
AnimateExpand();
}
chip_button_->ResetAnimation();
if (!delegate_->WasCurrentRequestAlreadyDisplayed())
chip_button_->AnimateExpand();
requested_time_ = base::TimeTicks::Now();
PreferredSizeChanged();
......@@ -168,9 +140,9 @@ void PermissionChip::Reshow() {
SetVisible(true);
// TODO(olesiamarukhno): Add tests for animation logic.
animation_->Reset();
chip_button_->ResetAnimation();
if (!delegate_->WasCurrentRequestAlreadyDisplayed())
AnimateExpand();
chip_button_->AnimateExpand();
PreferredSizeChanged();
}
......@@ -178,59 +150,20 @@ void PermissionChip::Hide() {
SetVisible(false);
}
void PermissionChip::AnimateCollapse() {
constexpr auto kAnimationDuration = base::TimeDelta::FromMilliseconds(250);
animation_->SetSlideDuration(kAnimationDuration);
animation_->Hide();
}
void PermissionChip::AnimateExpand() {
constexpr auto kAnimationDuration = base::TimeDelta::FromMilliseconds(350);
animation_->SetSlideDuration(kAnimationDuration);
animation_->Show();
}
bool PermissionChip::HasActiveRequest() {
return delegate_;
}
gfx::Size PermissionChip::CalculatePreferredSize() const {
const int fixed_width = GetIconSize() + chip_button_->GetInsets().width();
const int collapsable_width =
chip_button_->GetPreferredSize().width() - fixed_width;
const int width =
std::round(collapsable_width * animation_->GetCurrentValue()) +
fixed_width;
return gfx::Size(width, GetHeightForWidth(width));
}
void PermissionChip::OnMouseEntered(const ui::MouseEvent& event) {
// Restart the timer after user hovers the view.
StartCollapseTimer();
}
void PermissionChip::OnThemeChanged() {
View::OnThemeChanged();
UpdatePermissionIconAndTextColor();
}
void PermissionChip::AnimationEnded(const gfx::Animation* animation) {
DCHECK_EQ(animation, animation_.get());
is_collapsed_ = animation->GetCurrentValue() != 1.0;
if (animation->GetCurrentValue() == 1.0)
StartCollapseTimer();
}
void PermissionChip::AnimationProgressed(const gfx::Animation* animation) {
DCHECK_EQ(animation, animation_.get());
PreferredSizeChanged();
}
void PermissionChip::OnWidgetDestroying(views::Widget* widget) {
DCHECK_EQ(widget, prompt_bubble_->GetWidget());
widget->RemoveObserver(this);
prompt_bubble_ = nullptr;
AnimateCollapse();
chip_button_->AnimateCollapse();
}
void PermissionChip::OpenBubble() {
......@@ -266,7 +199,7 @@ void PermissionChip::Collapse() {
if (IsMouseHovered() || prompt_bubble_) {
StartCollapseTimer();
} else {
AnimateCollapse();
chip_button_->AnimateCollapse();
}
}
......@@ -277,26 +210,6 @@ void PermissionChip::StartCollapseTimer() {
&PermissionChip::Collapse);
}
int PermissionChip::GetIconSize() const {
return GetLayoutConstant(LOCATION_BAR_ICON_SIZE);
}
void PermissionChip::UpdatePermissionIconAndTextColor() {
if (!delegate_)
return;
// Set label and icon color to be the same color.
SkColor enabled_text_color =
views::style::GetColor(*chip_button_, views::style::CONTEXT_BUTTON_MD,
views::style::STYLE_DIALOG_BUTTON_DEFAULT);
chip_button_->SetEnabledTextColors(enabled_text_color);
chip_button_->SetImageModel(
views::Button::STATE_NORMAL,
ui::ImageModel::FromVectorIcon(GetPermissionIconId(), enabled_text_color,
GetIconSize()));
}
const gfx::VectorIcon& PermissionChip::GetPermissionIconId() {
auto requests = delegate_->Requests();
if (requests.size() == 1)
......
......@@ -6,13 +6,10 @@
#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_PERMISSION_CHIP_H_
#include "base/timer/timer.h"
#include "chrome/browser/ui/views/location_bar/omnibox_chip_button.h"
#include "components/permissions/permission_prompt.h"
#include "components/permissions/permission_request.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/views/accessible_pane_view.h"
#include "ui/views/animation/animation_delegate_views.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/widget/widget_observer.h"
class Browser;
......@@ -30,13 +27,12 @@ class BubbleOwnerDelegate {
// A chip view shown in the location bar to notify user about a permission
// request. Shows a permission bubble on click.
class PermissionChip : public views::AccessiblePaneView,
public views::AnimationDelegateViews,
public views::WidgetObserver,
public BubbleOwnerDelegate {
public:
explicit PermissionChip(Browser* browser);
PermissionChip(const PermissionChip& mask_layer) = delete;
PermissionChip& operator=(const PermissionChip& mask_layer) = delete;
PermissionChip(const PermissionChip& chip) = delete;
PermissionChip& operator=(const PermissionChip& chip) = delete;
~PermissionChip() override;
......@@ -48,16 +44,10 @@ class PermissionChip : public views::AccessiblePaneView,
bool HasActiveRequest();
views::Button* button() { return chip_button_; }
bool is_collapsed() { return is_collapsed_; }
// views::AnimationDelegateViews:
void AnimationEnded(const gfx::Animation* animation) override;
void AnimationProgressed(const gfx::Animation* animation) override;
bool is_fully_collapsed() { return chip_button_->is_fully_collapsed(); }
// views::View:
gfx::Size CalculatePreferredSize() const override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnThemeChanged() override;
// views::WidgetObserver:
void OnWidgetDestroying(views::Widget* widget) override;
......@@ -73,8 +63,6 @@ class PermissionChip : public views::AccessiblePaneView,
void ChipButtonPressed();
void Collapse();
void StartCollapseTimer();
int GetIconSize() const;
void UpdatePermissionIconAndTextColor();
base::string16 GetPermissionMessage();
const gfx::VectorIcon& GetPermissionIconId();
void AnnouncePermissionRequested();
......@@ -86,26 +74,19 @@ class PermissionChip : public views::AccessiblePaneView,
permissions::PermissionPrompt::Delegate* delegate_ = nullptr;
PermissionPromptBubbleView* prompt_bubble_ = nullptr;
// An animation used for expanding and collapsing the chip.
std::unique_ptr<gfx::SlideAnimation> animation_;
// A timer used to collapse the chip after a delay.
base::OneShotTimer timer_;
base::OneShotTimer announce_timer_;
// The button that displays the icon and text.
views::MdTextButton* chip_button_;
OmniboxChipButton* chip_button_ = nullptr;
// The time when the permission was requested.
base::TimeTicks requested_time_;
// If uma metric was already recorded on the button click.
bool already_recorded_interaction_ = false;
// If chip is collapsed. In the collapsed state, only an icon is visible,
// without text.
bool is_collapsed_ = false;
};
#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_PERMISSION_CHIP_H_
......@@ -107,7 +107,7 @@ void PermissionPromptImpl::UpdateAnchorPosition() {
DCHECK(permission_chip_);
// If there is fresh pending request shown as chip UI and location bar
// isn't visible anymore, show bubble UI instead.
if (!permission_chip_->is_collapsed() && !is_location_bar_drawn) {
if (!permission_chip_->is_fully_collapsed() && !is_location_bar_drawn) {
permission_chip_->FinalizeRequest();
permission_chip_ = nullptr;
ShowBubble();
......
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