Commit 7a676a12 authored by Yasmin's avatar Yasmin Committed by Commit Bot

Refactoring Click to Call Icon View to be reused by other features




Bug: 988461
Change-Id: I2cc57ddd1ee3b93036a10a7243045a3f7320d8e1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1725635
Commit-Queue: Yasmin Molazadeh <yasmo@chromium.org>
Reviewed-by: default avatarRichard Knoll <knollr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683126}
parent a0740c61
......@@ -2993,6 +2993,8 @@ jumbo_split_static_library("ui") {
"views/sharing/click_to_call/click_to_call_dialog_view.h",
"views/sharing/click_to_call/click_to_call_icon_view.cc",
"views/sharing/click_to_call/click_to_call_icon_view.h",
"views/sharing/sharing_icon_view.cc",
"views/sharing/sharing_icon_view.h",
"views/simple_message_box_views.cc",
"views/simple_message_box_views.h",
"views/status_bubble_views.cc",
......
......@@ -7,30 +7,16 @@
#include <algorithm>
#include "base/memory/ptr_util.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.h"
#include "chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/material_design/material_design_controller.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/animation/ink_drop.h"
namespace {
// Height of the loader bar in DIP.
constexpr float kLoaderHeight = 4.0f;
// Width of the loader bar in percent of its range.
constexpr float kLoaderWidth = 0.2f;
// TODO(knollr): move these into IconLabelBubbleView.
constexpr int kIconTextSpacing = 8;
constexpr int kIconTextSpacingTouch = 10;
ClickToCallSharingDialogController* GetControllerFromWebContents(
content::WebContents* web_contents) {
if (!web_contents)
......@@ -39,17 +25,10 @@ ClickToCallSharingDialogController* GetControllerFromWebContents(
return ClickToCallSharingDialogController::GetOrCreateFromWebContents(
web_contents);
}
} // namespace
ClickToCallIconView::ClickToCallIconView(PageActionIconView::Delegate* delegate)
: PageActionIconView(/*command_updater=*/nullptr,
/*command_id=*/0,
delegate) {
SetVisible(false);
UpdateLoaderColor();
SetUpForInOutAnimation();
}
: SharingIconView(delegate) {}
ClickToCallIconView::~ClickToCallIconView() = default;
......@@ -73,7 +52,7 @@ bool ClickToCallIconView::Update() {
if (controller->is_loading())
StartLoadingAnimation();
else
StopLoadingAnimation();
StopLoadingAnimation(IDS_BROWSER_SHARING_CLICK_TO_CALL_DIALOG_SEND_SUCCESS);
const bool is_bubble_showing = IsBubbleShowing();
......@@ -91,140 +70,10 @@ bool ClickToCallIconView::Update() {
return visibility_changed;
}
void ClickToCallIconView::StartLoadingAnimation() {
if (loading_animation_)
return;
loading_animation_ = std::make_unique<gfx::ThrobAnimation>(this);
loading_animation_->SetTweenType(gfx::Tween::LINEAR);
loading_animation_->SetThrobDuration(750);
loading_animation_->StartThrobbing(-1);
SchedulePaint();
}
void ClickToCallIconView::StopLoadingAnimation() {
if (!loading_animation_)
return;
if (!show_error_)
AnimateIn(IDS_BROWSER_SHARING_CLICK_TO_CALL_DIALOG_SEND_SUCCESS);
loading_animation_.reset();
SchedulePaint();
}
void ClickToCallIconView::PaintButtonContents(gfx::Canvas* canvas) {
PageActionIconView::PaintButtonContents(canvas);
if (!loading_animation_)
return;
// TODO(knollr): Add support for this animation to PageActionIconView if other
// features need it as well.
gfx::ScopedCanvas scoped_canvas(canvas);
const float scale = canvas->UndoDeviceScaleFactor();
const gfx::Rect icon_bounds =
gfx::ScaleToEnclosedRect(image()->bounds(), scale);
const float progress = loading_animation_->GetCurrentValue();
const float range = icon_bounds.width();
const float offset = icon_bounds.x();
// Calculate start and end in percent of range.
float start = std::max(0.0f, (progress - kLoaderWidth) / (1 - kLoaderWidth));
float end = std::min(1.0f, progress / (1 - kLoaderWidth));
// Convert percentages to actual location.
const float size = kLoaderHeight * scale;
start = start * (range - size);
end = end * (range - size) + size;
gfx::RectF bounds(start + offset, icon_bounds.bottom() - size, end - start,
size);
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(loader_color_);
canvas->DrawRoundRect(bounds, bounds.height() / 2, flags);
}
double ClickToCallIconView::WidthMultiplier() const {
double multiplier = PageActionIconView::WidthMultiplier();
double min_width = image()->GetPreferredSize().width() + GetInsets().width();
double spacing = ui::MaterialDesignController::touch_ui()
? kIconTextSpacingTouch
: kIconTextSpacing;
double label_width = label()->GetPreferredSize().width();
double max_width = min_width + spacing + label_width;
// We offset the width multiplier to start expanding the label straight away
// instead of completely hide the icon and expanding it from zero width.
double offset = min_width / max_width;
return multiplier * (1 - offset) + offset;
}
void ClickToCallIconView::AnimationProgressed(const gfx::Animation* animation) {
if (animation != loading_animation_.get()) {
UpdateOpacity();
return PageActionIconView::AnimationProgressed(animation);
}
SchedulePaint();
}
void ClickToCallIconView::AnimationEnded(const gfx::Animation* animation) {
PageActionIconView::AnimationEnded(animation);
UpdateOpacity();
Update();
}
void ClickToCallIconView::OnThemeChanged() {
PageActionIconView::OnThemeChanged();
UpdateLoaderColor();
}
void ClickToCallIconView::UpdateOpacity() {
if (!IsShrinking()) {
DestroyLayer();
SetTextSubpixelRenderingEnabled(true);
return;
}
if (!layer()) {
SetPaintToLayer();
SetTextSubpixelRenderingEnabled(false);
layer()->SetFillsBoundsOpaquely(false);
}
layer()->SetOpacity(PageActionIconView::WidthMultiplier());
}
void ClickToCallIconView::UpdateInkDrop(bool activate) {
auto target_state =
activate ? views::InkDropState::ACTIVATED : views::InkDropState::HIDDEN;
if (GetInkDrop()->GetTargetInkDropState() != target_state)
AnimateInkDrop(target_state, /*event=*/nullptr);
}
void ClickToCallIconView::UpdateLoaderColor() {
loader_color_ = GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_ProminentButtonColor);
}
bool ClickToCallIconView::IsTriggerableEvent(const ui::Event& event) {
// We do nothing when the icon is clicked.
return false;
}
void ClickToCallIconView::OnExecuting(
PageActionIconView::ExecuteSource execute_source) {}
const gfx::VectorIcon& ClickToCallIconView::GetVectorIcon() const {
return vector_icons::kCallIcon;
}
const gfx::VectorIcon& ClickToCallIconView::GetVectorIconBadge() const {
return show_error_ ? kBlockedBadgeIcon : gfx::kNoneIcon;
}
base::string16 ClickToCallIconView::GetTextForTooltipAndAccessibleName() const {
return l10n_util::GetStringUTF16(
IDS_BROWSER_SHARING_CLICK_TO_CALL_DIALOG_TITLE_LABEL);
......
......@@ -10,23 +10,15 @@
#include "base/macros.h"
#include "base/strings/string16.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
#include "chrome/browser/ui/views/sharing/sharing_icon_view.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/vector_icon_types.h"
namespace gfx {
class Canvas;
class ThrobAnimation;
} // namespace gfx
namespace ui {
class Event;
} // namespace ui
class ClickToCallSharingDialogController;
// The location bar icon to show the click to call bubble where the user can
// choose to send a phone number to a target device or use an OS handler app.
class ClickToCallIconView : public PageActionIconView {
class ClickToCallIconView : public SharingIconView {
public:
explicit ClickToCallIconView(PageActionIconView::Delegate* delegate);
~ClickToCallIconView() override;
......@@ -36,35 +28,11 @@ class ClickToCallIconView : public PageActionIconView {
bool Update() override;
base::string16 GetTextForTooltipAndAccessibleName() const override;
// views::Button:
void PaintButtonContents(gfx::Canvas* canvas) override;
// views::View:
void OnThemeChanged() override;
void StartLoadingAnimation();
void StopLoadingAnimation();
protected:
// PageActionIconView:
void OnExecuting(PageActionIconView::ExecuteSource execute_source) override;
const gfx::VectorIcon& GetVectorIcon() const override;
const gfx::VectorIcon& GetVectorIconBadge() const override;
bool IsTriggerableEvent(const ui::Event& event) override;
double WidthMultiplier() const override;
// gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
void AnimationEnded(const gfx::Animation* animation) override;
private:
void UpdateInkDrop(bool activate);
void UpdateLoaderColor();
void UpdateOpacity();
SkColor loader_color_;
std::unique_ptr<gfx::ThrobAnimation> loading_animation_;
bool show_error_ = false;
ClickToCallSharingDialogController* last_controller_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ClickToCallIconView);
......
// Copyright 2019 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/sharing/sharing_icon_view.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/views/animation/ink_drop.h"
namespace {
// Height of the loader bar in DIP.
constexpr float kLoaderHeight = 4.0f;
// Width of the loader bar in percent of its range.
constexpr float kLoaderWidth = 0.2f;
// TODO(knollr): move these into IconLabelBubbleView.
constexpr int kIconTextSpacing = 8;
constexpr int kIconTextSpacingTouch = 10;
} // namespace
SharingIconView::SharingIconView(PageActionIconView::Delegate* delegate)
: PageActionIconView(/*command_updater=*/nullptr,
/*command_id=*/0,
delegate) {
SetVisible(false);
UpdateLoaderColor();
SetUpForInOutAnimation();
}
SharingIconView::~SharingIconView() = default;
void SharingIconView::StartLoadingAnimation() {
if (loading_animation_)
return;
loading_animation_ = std::make_unique<gfx::ThrobAnimation>(this);
loading_animation_->SetTweenType(gfx::Tween::LINEAR);
loading_animation_->SetThrobDuration(750);
loading_animation_->StartThrobbing(-1);
SchedulePaint();
}
void SharingIconView::StopLoadingAnimation(base::Optional<int> string_id) {
if (!loading_animation_)
return;
if (!show_error_)
AnimateIn(string_id);
loading_animation_.reset();
SchedulePaint();
}
void SharingIconView::UpdateLoaderColor() {
loader_color_ = GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_ProminentButtonColor);
}
void SharingIconView::OnThemeChanged() {
PageActionIconView::OnThemeChanged();
UpdateLoaderColor();
}
void SharingIconView::PaintButtonContents(gfx::Canvas* canvas) {
PageActionIconView::PaintButtonContents(canvas);
if (!loading_animation_)
return;
// TODO(knollr): Add support for this animation to PageActionIconView if other
// features need it as well.
gfx::ScopedCanvas scoped_canvas(canvas);
const float scale = canvas->UndoDeviceScaleFactor();
const gfx::Rect icon_bounds =
gfx::ScaleToEnclosedRect(image()->bounds(), scale);
const float progress = loading_animation_->GetCurrentValue();
const float range = icon_bounds.width();
const float offset = icon_bounds.x();
// Calculate start and end in percent of range.
float start = std::max(0.0f, (progress - kLoaderWidth) / (1 - kLoaderWidth));
float end = std::min(1.0f, progress / (1 - kLoaderWidth));
// Convert percentages to actual location.
const float size = kLoaderHeight * scale;
start = start * (range - size);
end = end * (range - size) + size;
gfx::RectF bounds(start + offset, icon_bounds.bottom() - size, end - start,
size);
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(loader_color_);
canvas->DrawRoundRect(bounds, bounds.height() / 2, flags);
}
double SharingIconView::WidthMultiplier() const {
double multiplier = PageActionIconView::WidthMultiplier();
double min_width = image()->GetPreferredSize().width() + GetInsets().width();
double spacing = ui::MaterialDesignController::touch_ui()
? kIconTextSpacingTouch
: kIconTextSpacing;
double label_width = label()->GetPreferredSize().width();
double max_width = min_width + spacing + label_width;
// We offset the width multiplier to start expanding the label straight away
// instead of completely hide the icon and expanding it from zero width.
double offset = min_width / max_width;
return multiplier * (1 - offset) + offset;
}
void SharingIconView::AnimationProgressed(const gfx::Animation* animation) {
if (animation != loading_animation_.get()) {
UpdateOpacity();
return PageActionIconView::AnimationProgressed(animation);
}
SchedulePaint();
}
void SharingIconView::AnimationEnded(const gfx::Animation* animation) {
PageActionIconView::AnimationEnded(animation);
UpdateOpacity();
Update();
}
void SharingIconView::UpdateOpacity() {
if (!IsShrinking()) {
DestroyLayer();
SetTextSubpixelRenderingEnabled(true);
return;
}
if (!layer()) {
SetPaintToLayer();
SetTextSubpixelRenderingEnabled(false);
layer()->SetFillsBoundsOpaquely(false);
}
layer()->SetOpacity(PageActionIconView::WidthMultiplier());
}
void SharingIconView::UpdateInkDrop(bool activate) {
auto target_state =
activate ? views::InkDropState::ACTIVATED : views::InkDropState::HIDDEN;
if (GetInkDrop()->GetTargetInkDropState() != target_state)
AnimateInkDrop(target_state, /*event=*/nullptr);
}
bool SharingIconView::IsTriggerableEvent(const ui::Event& event) {
// We do nothing when the icon is clicked.
return false;
}
const gfx::VectorIcon& SharingIconView::GetVectorIconBadge() const {
return show_error_ ? kBlockedBadgeIcon : gfx::kNoneIcon;
}
void SharingIconView::OnExecuting(
PageActionIconView::ExecuteSource execute_source) {}
// Copyright 2019 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_SHARING_SHARING_ICON_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_SHARING_SHARING_ICON_VIEW_H_
#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
#include "third_party/skia/include/core/SkColor.h"
namespace gfx {
class Canvas;
class ThrobAnimation;
} // namespace gfx
// The location bar icon to show the sharing features bubble.
class SharingIconView : public PageActionIconView {
public:
explicit SharingIconView(PageActionIconView::Delegate* delegate);
~SharingIconView() override;
void StartLoadingAnimation();
void StopLoadingAnimation(base::Optional<int> string_id);
// views::View:
void OnThemeChanged() override;
// views::Button:
void PaintButtonContents(gfx::Canvas* canvas) override;
protected:
// PageActionIconView:
void OnExecuting(PageActionIconView::ExecuteSource execute_source) override;
bool IsTriggerableEvent(const ui::Event& event) override;
double WidthMultiplier() const override;
const gfx::VectorIcon& GetVectorIconBadge() const override;
// gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
void AnimationEnded(const gfx::Animation* animation) override;
void UpdateInkDrop(bool activate);
void UpdateOpacity();
void UpdateLoaderColor();
std::unique_ptr<gfx::ThrobAnimation> loading_animation_;
bool show_error_ = false;
SkColor loader_color_;
DISALLOW_COPY_AND_ASSIGN(SharingIconView);
};
#endif // CHROME_BROWSER_UI_VIEWS_SHARING_SHARING_ICON_VIEW_H_
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