blob: ca52ffe958d181f20785d64f5486fd85109070ff [file] [log] [blame]
// 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 "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/layout_constants.h"
#include "components/vector_icons/vector_icons.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/theme_provider.h"
#include "ui/color/color_id.h"
#include "ui/color/color_provider.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/background.h"
#include "ui/views/controls/highlight_path_generator.h"
#include "ui/views/painter.h"
namespace {
// Padding between chip's icon and label.
constexpr int kChipImagePadding = 4;
// An extra space between chip's label and right edge.
constexpr int kExtraRightPadding = 4;
} // namespace
OmniboxChipButton::OmniboxChipButton(PressedCallback callback,
const gfx::VectorIcon& icon_on,
const gfx::VectorIcon& icon_off,
std::u16string message,
bool is_prominent)
: MdTextButton(std::move(callback),
std::u16string(),
views::style::CONTEXT_BUTTON_MD),
icon_on_(icon_on),
icon_off_(icon_off) {
views::InstallPillHighlightPathGenerator(this);
SetText(message);
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(kChipImagePadding);
SetCustomPadding(
gfx::Insets(GetLayoutConstant(LOCATION_BAR_CHILD_INTERIOR_PADDING),
GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left()));
constexpr auto kAnimationDuration = base::Milliseconds(350);
animation_ = std::make_unique<gfx::SlideAnimation>(this);
animation_->SetSlideDuration(kAnimationDuration);
UpdateIconAndColors();
}
OmniboxChipButton::~OmniboxChipButton() = default;
void OmniboxChipButton::AnimateCollapse() {
constexpr auto kAnimationDuration = base::Milliseconds(250);
animation_->SetSlideDuration(kAnimationDuration);
animation_->Hide();
}
void OmniboxChipButton::AnimateExpand() {
constexpr auto kAnimationDuration = base::Milliseconds(350);
animation_->SetSlideDuration(kAnimationDuration);
animation_->Show();
}
void OmniboxChipButton::ResetAnimation(double value) {
animation_->Reset(value);
}
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() +
kChipImagePadding + kExtraRightPadding;
const double animation_value =
force_expanded_for_testing_ ? 1.0 : animation_->GetCurrentValue();
const int width =
std::round(collapsable_width * animation_value) + fixed_width;
return gfx::Size(width, GetHeightForWidth(width));
}
void OmniboxChipButton::OnThemeChanged() {
MdTextButton::OnThemeChanged();
UpdateIconAndColors();
}
void OmniboxChipButton::UpdateBackgroundColor() {
SetBackground(
CreateBackgroundFromPainter(views::Painter::CreateSolidRoundRectPainter(
GetBackgroundColor(), GetIconSize())));
}
void OmniboxChipButton::AnimationEnded(const gfx::Animation* animation) {
if (animation != animation_.get())
return;
fully_collapsed_ = animation->GetCurrentValue() != 1.0;
if (animation->GetCurrentValue() == 1.0 && expand_animation_ended_callback_)
expand_animation_ended_callback_.Run();
}
void OmniboxChipButton::AnimationProgressed(const gfx::Animation* animation) {
if (animation == animation_.get())
PreferredSizeChanged();
}
void OmniboxChipButton::SetTheme(Theme theme) {
theme_ = theme;
UpdateIconAndColors();
}
int OmniboxChipButton::GetIconSize() const {
return GetLayoutConstant(LOCATION_BAR_ICON_SIZE);
}
void OmniboxChipButton::UpdateIconAndColors() {
if (!GetWidget())
return;
SetEnabledTextColors(GetTextAndIconColor());
SetImageModel(views::Button::STATE_NORMAL,
ui::ImageModel::FromVectorIcon(
show_blocked_icon_ ? icon_off_ : icon_on_,
GetTextAndIconColor(), GetIconSize(), nullptr));
}
SkColor OmniboxChipButton::GetTextAndIconColor() {
switch (theme_) {
case Theme::kNormalVisibility: {
// TODO(crbug.com/1274118) Instead of using constants or toolbar colors,
// add the chip's properties.
return color_utils::IsDark(
GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR))
? gfx::kGoogleBlue300
: gfx::kGoogleBlue600;
}
case Theme::kLowVisibility: {
return GetThemeProvider()->GetColor(
ThemeProperties::COLOR_TAB_FOREGROUND_ACTIVE_FRAME_ACTIVE);
}
}
}
SkColor OmniboxChipButton::GetBackgroundColor() {
SkColor active_tab_color =
GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR);
if (theme_ == Theme::kLowVisibility) {
return active_tab_color;
}
// TODO(crbug.com/1274118) Instead of using constants or toolbar colors, add
// the chip's properties.
return ThemeProperties::GetDefaultColor(
ThemeProperties::COLOR_TOOLBAR, false,
/*dark_mode=*/color_utils::IsDark(active_tab_color));
}
void OmniboxChipButton::SetForceExpandedForTesting(
bool force_expanded_for_testing) {
force_expanded_for_testing_ = force_expanded_for_testing;
}
void OmniboxChipButton::SetShowBlockedIcon(bool show_blocked_icon) {
if (show_blocked_icon_ != show_blocked_icon) {
show_blocked_icon_ = show_blocked_icon;
theme_ =
show_blocked_icon ? Theme::kLowVisibility : Theme::kNormalVisibility;
UpdateIconAndColors();
}
}
BEGIN_METADATA(OmniboxChipButton, views::MdTextButton)
ADD_READONLY_PROPERTY_METADATA(int, IconSize)
END_METADATA