blob: f86ec572d719784519c39d9389e698f5108b14b1 [file] [log] [blame]
// Copyright 2017 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/feature_promos/feature_promo_bubble_view.h"
#include <memory>
#include "base/metrics/user_metrics.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "components/variations/variations_associated_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/theme_provider.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/text_utils.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/event_monitor.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
namespace {
// The amount of time the promo should stay onscreen if the user
// never hovers over it.
constexpr base::TimeDelta kDelayDefault = base::TimeDelta::FromSeconds(10);
// The amount of time the promo should stay onscreen after the
// user stops hovering over it.
constexpr base::TimeDelta kDelayShort = base::TimeDelta::FromSeconds(3);
// The insets from the bubble border to the text inside.
constexpr gfx::Insets kBubbleContentsInsets(12, 16);
} // namespace
FeaturePromoBubbleView::FeaturePromoBubbleView(
views::View* anchor_view,
views::BubbleBorder::Arrow arrow,
int string_specifier,
ActivationAction activation_action)
: FeaturePromoBubbleView(anchor_view,
gfx::Rect(),
arrow,
string_specifier,
activation_action) {}
FeaturePromoBubbleView::FeaturePromoBubbleView(const gfx::Rect& anchor_rect,
views::BubbleBorder::Arrow arrow,
int string_specifier)
: FeaturePromoBubbleView(nullptr,
anchor_rect,
arrow,
string_specifier,
ActivationAction::ACTIVATE) {}
FeaturePromoBubbleView::FeaturePromoBubbleView(
views::View* anchor_view,
const gfx::Rect& anchor_rect,
views::BubbleBorder::Arrow arrow,
int string_specifier,
ActivationAction activation_action)
: BubbleDialogDelegateView(anchor_view, arrow),
activation_action_(activation_action) {
UseCompactMargins();
if (!anchor_view)
SetAnchorRect(anchor_rect);
// We get the theme provider from the anchor view since our widget hasn't been
// created yet.
const ui::ThemeProvider* theme_provider = anchor_view->GetThemeProvider();
DCHECK(theme_provider);
const SkColor background_color = theme_provider->GetColor(
ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_BACKGROUND);
const SkColor text_color = theme_provider->GetColor(
ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_TEXT);
auto box_layout = std::make_unique<views::BoxLayout>(
views::BoxLayout::kVertical, kBubbleContentsInsets, 0);
box_layout->set_main_axis_alignment(
views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
box_layout->set_cross_axis_alignment(
views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
SetLayoutManager(std::move(box_layout));
auto* label = new views::Label(l10n_util::GetStringUTF16(string_specifier));
label->SetBackgroundColor(background_color);
label->SetEnabledColor(text_color);
AddChildView(label);
if (activation_action == ActivationAction::DO_NOT_ACTIVATE) {
SetCanActivate(activation_action == ActivationAction::ACTIVATE);
set_shadow(views::BubbleBorder::BIG_SHADOW);
}
set_margins(gfx::Insets());
set_title_margins(gfx::Insets());
set_color(background_color);
views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble(this);
GetBubbleFrameView()->bubble_border()->SetCornerRadius(
ChromeLayoutProvider::Get()->GetCornerRadiusMetric(views::EMPHASIS_HIGH));
widget->Show();
if (activation_action == ActivationAction::ACTIVATE)
StartAutoCloseTimer(kDelayDefault);
}
FeaturePromoBubbleView::~FeaturePromoBubbleView() = default;
// static
FeaturePromoBubbleView* FeaturePromoBubbleView::CreateOwned(
views::View* anchor_view,
views::BubbleBorder::Arrow arrow,
int string_specifier,
ActivationAction activation_action) {
return new FeaturePromoBubbleView(anchor_view, arrow, string_specifier,
activation_action);
}
void FeaturePromoBubbleView::CloseBubble() {
GetWidget()->Close();
}
int FeaturePromoBubbleView::GetDialogButtons() const {
return ui::DIALOG_BUTTON_NONE;
}
bool FeaturePromoBubbleView::OnMousePressed(const ui::MouseEvent& event) {
base::RecordAction(
base::UserMetricsAction("InProductHelp.Promos.BubbleClicked"));
return false;
}
void FeaturePromoBubbleView::OnMouseEntered(const ui::MouseEvent& event) {
timer_.Stop();
}
void FeaturePromoBubbleView::OnMouseExited(const ui::MouseEvent& event) {
StartAutoCloseTimer(kDelayShort);
}
gfx::Rect FeaturePromoBubbleView::GetBubbleBounds() {
gfx::Rect bounds = BubbleDialogDelegateView::GetBubbleBounds();
if (activation_action_ == ActivationAction::DO_NOT_ACTIVATE) {
if (base::i18n::IsRTL())
bounds.Offset(5, 0);
else
bounds.Offset(-5, 0);
}
return bounds;
}
void FeaturePromoBubbleView::StartAutoCloseTimer(
base::TimeDelta auto_close_duration) {
timer_.Start(FROM_HERE, auto_close_duration, this,
&FeaturePromoBubbleView::CloseBubble);
}