Commit 7d2d8cc1 authored by Noah Rose Ledesma's avatar Noah Rose Ledesma Committed by Commit Bot

GMC: Redesign audio picker UI

Implement the new UI for the audio device picker in global media
controls. As part of this change, the MediaNotificationBackground will
draw a gradient between the device picker and notification artwork if
the picker is availabile.

Screenshots of this updated UI will be posted on the crbug.

Change-Id: Ic7186c770102663b08e85b56eeddfbfa13833c3c
Bug: 1117160
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2358512
Commit-Queue: Noah Rose Ledesma <noahrose@google.com>
Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#800243}
parent 4c09e3d6
...@@ -1167,6 +1167,12 @@ Chromium is unable to recover your settings. ...@@ -1167,6 +1167,12 @@ Chromium is unable to recover your settings.
</message> </message>
</if> </if>
<!-- Global Media Controls -->
<if expr="not is_android">
<message name="IDS_GLOBAL_MEDIA_CONTROLS_DEVICES_BUTTON_LABEL" desc="Label for a button that opens a menu for picking an audio device to play from.">
Devices
</message>
</if>
</messages> </messages>
</release> </release>
</grit> </grit>
768895d5a9d7cb3c5816e91af22e01b359eb646f
\ No newline at end of file
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
#include "ui/views/controls/button/md_text_button.h" #include "ui/views/controls/button/md_text_button.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
namespace views { namespace {
class Button; class AudioDeviceEntryView;
} // namespace views } // anonymous namespace
class MediaNotificationAudioDeviceSelectorViewDelegate; class MediaNotificationAudioDeviceSelectorViewDelegate;
class MediaNotificationService; class MediaNotificationService;
...@@ -24,27 +24,30 @@ class MediaNotificationAudioDeviceSelectorView : public views::View, ...@@ -24,27 +24,30 @@ class MediaNotificationAudioDeviceSelectorView : public views::View,
MediaNotificationAudioDeviceSelectorView( MediaNotificationAudioDeviceSelectorView(
MediaNotificationAudioDeviceSelectorViewDelegate* delegate, MediaNotificationAudioDeviceSelectorViewDelegate* delegate,
MediaNotificationService* service, MediaNotificationService* service,
gfx::Size size, const std::string& current_device_id,
const std::string& current_device_id); const SkColor& foreground_color,
MediaNotificationAudioDeviceSelectorView( const SkColor& background_color);
const MediaNotificationAudioDeviceSelectorView&) = delete;
MediaNotificationAudioDeviceSelectorView& operator=(
const MediaNotificationAudioDeviceSelectorView&) = delete;
~MediaNotificationAudioDeviceSelectorView() override; ~MediaNotificationAudioDeviceSelectorView() override;
// Called when audio output devices are discovered. // Called when audio output devices are discovered.
void UpdateAvailableAudioDevices( void UpdateAvailableAudioDevices(
const media::AudioDeviceDescriptions& device_descriptions); const media::AudioDeviceDescriptions& device_descriptions);
// Called when an audio device switch has occurred // Called when an audio device switch has occurred
void UpdateCurrentAudioDevice(std::string current_device_id); void UpdateCurrentAudioDevice(const std::string& current_device_id);
void OnColorsChanged(const SkColor& foreground_color,
const SkColor& background_color);
// views::ButtonListener // ButtonListener
void ButtonPressed(views::Button* sender, const ui::Event& event) override; void ButtonPressed(views::Button* sender, const ui::Event& event) override;
static std::string get_entry_label_for_testing(views::View* entry_view);
static bool get_entry_is_highlighted_for_testing(views::View* entry_view);
private: private:
FRIEND_TEST_ALL_PREFIXES(MediaNotificationAudioDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationAudioDeviceSelectorViewTest,
DeviceButtonsCreated); DeviceButtonsCreated);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationAudioDeviceSelectorViewTest,
ExpandButtonOpensEntryContainer);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationAudioDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationAudioDeviceSelectorViewTest,
DeviceButtonClickNotifiesContainer); DeviceButtonClickNotifiesContainer);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationAudioDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationAudioDeviceSelectorViewTest,
...@@ -54,31 +57,27 @@ class MediaNotificationAudioDeviceSelectorView : public views::View, ...@@ -54,31 +57,27 @@ class MediaNotificationAudioDeviceSelectorView : public views::View,
FRIEND_TEST_ALL_PREFIXES(MediaNotificationAudioDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationAudioDeviceSelectorViewTest,
DeviceButtonsChange); DeviceButtonsChange);
void CreateDeviceButton(
const media::AudioDeviceDescription& device_description);
bool ShouldBeVisible( bool ShouldBeVisible(
const media::AudioDeviceDescriptions& device_descriptions); const media::AudioDeviceDescriptions& device_descriptions);
void ShowDevices();
void HideDevices();
bool is_expanded_ = false;
MediaNotificationAudioDeviceSelectorViewDelegate* const delegate_; MediaNotificationAudioDeviceSelectorViewDelegate* const delegate_;
MediaNotificationService* const service_; std::string current_device_id_;
SkColor foreground_color_, background_color_;
AudioDeviceEntryView* current_device_entry_view_ = nullptr;
// Child views
views::View* expand_button_strip_;
views::LabelButton* expand_button_;
views::View* audio_device_entries_container_;
std::unique_ptr<MediaNotificationDeviceProvider:: std::unique_ptr<MediaNotificationDeviceProvider::
GetOutputDevicesCallbackList::Subscription> GetOutputDevicesCallbackList::Subscription>
audio_device_subscription_; audio_device_subscription_;
// Subviews
views::View* device_button_container_ = nullptr;
views::View* expand_button_container_ = nullptr;
views::ToggleImageButton* expand_button_ = nullptr;
views::MdTextButton* current_device_button_ = nullptr;
std::string current_device_id_;
// Maps button pointers to the string ID of the audio sink they represent.
std::map<views::Button*, std::string> sink_id_map_;
base::WeakPtrFactory<MediaNotificationAudioDeviceSelectorView> base::WeakPtrFactory<MediaNotificationAudioDeviceSelectorView>
weak_ptr_factory_{this}; weak_ptr_factory_{this};
}; };
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/ui/views/global_media_controls/media_notification_audio_device_selector_view.h" #include "chrome/browser/ui/views/global_media_controls/media_notification_audio_device_selector_view.h"
#include <memory>
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/util/ranges/algorithm.h"
#include "chrome/browser/media/router/media_router_factory.h" #include "chrome/browser/media/router/media_router_factory.h"
#include "chrome/browser/media/router/test/mock_media_router.h" #include "chrome/browser/media/router/test/mock_media_router.h"
#include "chrome/browser/ui/global_media_controls/media_notification_device_provider.h" #include "chrome/browser/ui/global_media_controls/media_notification_device_provider.h"
...@@ -16,8 +16,7 @@ ...@@ -16,8 +16,7 @@
#include "chrome/test/views/chrome_views_test_base.h" #include "chrome/test/views/chrome_views_test_base.h"
#include "media/audio/audio_device_description.h" #include "media/audio/audio_device_description.h"
#include "ui/events/base_event_utils.h" #include "ui/events/base_event_utils.h"
#include "ui/views/controls/button/label_button.h" #include "ui/gfx/color_palette.h"
#include "ui/views/controls/button/md_text_button.h"
class MediaNotificationContainerObserver; class MediaNotificationContainerObserver;
...@@ -93,6 +92,23 @@ class MediaNotificationAudioDeviceSelectorViewTest ...@@ -93,6 +92,23 @@ class MediaNotificationAudioDeviceSelectorViewTest
ChromeViewsTestBase::TearDown(); ChromeViewsTestBase::TearDown();
} }
void SimulateButtonClick(views::View* view) {
view_->ButtonPressed(
static_cast<views::Button*>(view),
ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
ui::EventTimeForNow(), 0, 0));
}
static std::string EntryLabelText(views::View* entry_view) {
return MediaNotificationAudioDeviceSelectorView::
get_entry_label_for_testing(entry_view);
}
static bool IsHighlighted(views::View* entry_view) {
return MediaNotificationAudioDeviceSelectorView::
get_entry_is_highlighted_for_testing(entry_view);
}
std::string GetButtonText(views::View* view) { std::string GetButtonText(views::View* view) {
return base::UTF16ToUTF8(static_cast<views::LabelButton*>(view)->GetText()); return base::UTF16ToUTF8(static_cast<views::LabelButton*>(view)->GetText());
} }
...@@ -112,25 +128,37 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, DeviceButtonsCreated) { ...@@ -112,25 +128,37 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, DeviceButtonsCreated) {
MockMediaNotificationAudioDeviceSelectorViewDelegate delegate; MockMediaNotificationAudioDeviceSelectorViewDelegate delegate;
view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>( view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>(
&delegate, service_.get(), gfx::Size(), "1"); &delegate, service_.get(), "1", gfx::kPlaceholderColor,
gfx::kPlaceholderColor);
std::vector<std::string> button_texts;
ASSERT_TRUE(view_->device_button_container_ != nullptr); ASSERT_TRUE(view_->audio_device_entries_container_ != nullptr);
std::transform( auto container_children = view_->audio_device_entries_container_->children();
view_->device_button_container_->children().cbegin(), ASSERT_EQ(container_children.size(), 3u);
view_->device_button_container_->children().cend(),
std::back_inserter(button_texts), [](views::View* child) { EXPECT_EQ(EntryLabelText(container_children.at(0)), "Speaker");
return base::UTF16ToASCII( EXPECT_EQ(EntryLabelText(container_children.at(1)), "Headphones");
static_cast<const views::LabelButton*>(child)->GetText()); EXPECT_EQ(EntryLabelText(container_children.at(2)), "Earbuds");
}); }
EXPECT_THAT(button_texts, testing::UnorderedElementsAre(
"Speaker", "Headphones", "Earbuds")); TEST_F(MediaNotificationAudioDeviceSelectorViewTest,
ExpandButtonOpensEntryContainer) {
provider_->AddDevice("Speaker", "1");
service_->set_device_provider_for_testing(std::move(provider_));
MockMediaNotificationAudioDeviceSelectorViewDelegate delegate;
view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>(
&delegate, service_.get(), "1", gfx::kPlaceholderColor,
gfx::kPlaceholderColor);
ASSERT_TRUE(view_->expand_button_);
EXPECT_FALSE(view_->audio_device_entries_container_->GetVisible());
SimulateButtonClick(view_->expand_button_);
EXPECT_TRUE(view_->audio_device_entries_container_->GetVisible());
} }
TEST_F(MediaNotificationAudioDeviceSelectorViewTest, TEST_F(MediaNotificationAudioDeviceSelectorViewTest,
DeviceButtonClickNotifiesContainer) { DeviceButtonClickNotifiesContainer) {
// When buttons are clicked the media notification container should be // When buttons are clicked the media notification delegate should be
// informed. // informed.
provider_->AddDevice("Speaker", "1"); provider_->AddDevice("Speaker", "1");
provider_->AddDevice("Headphones", "2"); provider_->AddDevice("Headphones", "2");
...@@ -143,13 +171,12 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, ...@@ -143,13 +171,12 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest,
EXPECT_CALL(delegate, OnAudioSinkChosen("3")).Times(1); EXPECT_CALL(delegate, OnAudioSinkChosen("3")).Times(1);
view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>( view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>(
&delegate, service_.get(), gfx::Size(), "1"); &delegate, service_.get(), "1", gfx::kPlaceholderColor,
gfx::kPlaceholderColor);
for (views::View* child : view_->device_button_container_->children()) { for (views::View* child :
view_->ButtonPressed( view_->audio_device_entries_container_->children()) {
static_cast<views::Button*>(child), SimulateButtonClick(child);
ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
ui::EventTimeForNow(), 0, 0));
} }
} }
...@@ -163,12 +190,13 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, CurrentDeviceHighlighted) { ...@@ -163,12 +190,13 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, CurrentDeviceHighlighted) {
MockMediaNotificationAudioDeviceSelectorViewDelegate delegate; MockMediaNotificationAudioDeviceSelectorViewDelegate delegate;
view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>( view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>(
&delegate, service_.get(), gfx::Size(), "3"); &delegate, service_.get(), "3", gfx::kPlaceholderColor,
gfx::kPlaceholderColor);
auto* first_button = static_cast<views::MdTextButton*>( auto* first_entry = static_cast<views::MdTextButton*>(
view_->device_button_container_->children().front()); view_->audio_device_entries_container_->children().front());
EXPECT_EQ(first_button->GetText(), base::UTF8ToUTF16("Earbuds")); EXPECT_EQ(EntryLabelText(first_entry), "Earbuds");
EXPECT_TRUE(first_button->GetProminent()); EXPECT_TRUE(IsHighlighted(first_entry));
} }
TEST_F(MediaNotificationAudioDeviceSelectorViewTest, TEST_F(MediaNotificationAudioDeviceSelectorViewTest,
...@@ -181,31 +209,26 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, ...@@ -181,31 +209,26 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest,
MockMediaNotificationAudioDeviceSelectorViewDelegate delegate; MockMediaNotificationAudioDeviceSelectorViewDelegate delegate;
view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>( view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>(
&delegate, service_.get(), gfx::Size(), "1"); &delegate, service_.get(), "1", gfx::kPlaceholderColor,
gfx::kPlaceholderColor);
auto button_is_highlighted = [](views::View* view) {
return static_cast<views::MdTextButton*>(view)->GetProminent();
};
auto& buttons = view_->device_button_container_->children(); auto& container_children = view_->audio_device_entries_container_->children();
// There should be only one highlighted button. It should be the first button. // There should be only one highlighted button. It should be the first button.
// It's text should be "Speaker" // It's text should be "Speaker"
EXPECT_EQ( EXPECT_EQ(util::ranges::count_if(container_children, IsHighlighted), 1);
std::count_if(buttons.begin(), buttons.end(), button_is_highlighted), 1); EXPECT_EQ(util::ranges::find_if(container_children, IsHighlighted),
EXPECT_EQ(std::find_if(buttons.begin(), buttons.end(), button_is_highlighted), container_children.begin());
buttons.begin()); EXPECT_EQ(EntryLabelText(container_children.front()), "Speaker");
EXPECT_EQ(GetButtonText(buttons.front()), "Speaker");
// Simulate a device change // Simulate a device change
view_->UpdateCurrentAudioDevice("3"); view_->UpdateCurrentAudioDevice("3");
// The button for "Earbuds" should come before all others & be highlighted. // The button for "Earbuds" should come before all others & be highlighted.
EXPECT_EQ( EXPECT_EQ(util::ranges::count_if(container_children, IsHighlighted), 1);
std::count_if(buttons.begin(), buttons.end(), button_is_highlighted), 1); EXPECT_EQ(util::ranges::find_if(container_children, IsHighlighted),
EXPECT_EQ(std::find_if(buttons.begin(), buttons.end(), button_is_highlighted), container_children.begin());
buttons.begin()); EXPECT_EQ(EntryLabelText(container_children.front()), "Earbuds");
EXPECT_EQ(GetButtonText(buttons.front()), "Earbuds");
} }
TEST_F(MediaNotificationAudioDeviceSelectorViewTest, DeviceButtonsChange) { TEST_F(MediaNotificationAudioDeviceSelectorViewTest, DeviceButtonsChange) {
...@@ -219,10 +242,8 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, DeviceButtonsChange) { ...@@ -219,10 +242,8 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, DeviceButtonsChange) {
MockMediaNotificationAudioDeviceSelectorViewDelegate delegate; MockMediaNotificationAudioDeviceSelectorViewDelegate delegate;
view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>( view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>(
&delegate, service_.get(), gfx::Size(), "1"); &delegate, service_.get(), "1", gfx::kPlaceholderColor,
gfx::kPlaceholderColor);
std::vector<std::string> button_texts;
ASSERT_TRUE(view_->device_button_container_ != nullptr);
provider->ResetDevices(); provider->ResetDevices();
// Make "Monitor" the default device. // Make "Monitor" the default device.
...@@ -230,15 +251,14 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, DeviceButtonsChange) { ...@@ -230,15 +251,14 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, DeviceButtonsChange) {
media::AudioDeviceDescription::kDefaultDeviceId); media::AudioDeviceDescription::kDefaultDeviceId);
provider->RunUICallback(); provider->RunUICallback();
EXPECT_EQ(view_->device_button_container_->children().size(), 1u); auto& container_children = view_->audio_device_entries_container_->children();
ASSERT_FALSE(view_->device_button_container_->children().empty()); EXPECT_EQ(container_children.size(), 1u);
auto* button = static_cast<const views::MdTextButton*>( ASSERT_FALSE(container_children.empty());
view_->device_button_container_->children().at(0)); EXPECT_EQ(EntryLabelText(container_children.front()), "Monitor");
EXPECT_EQ(base::UTF16ToUTF8(button->GetText()), "Monitor");
// When the device highlighted in the UI is removed, the UI should fall back // When the device highlighted in the UI is removed, the UI should fall back
// to highlighting the default device. // to highlighting the default device.
EXPECT_TRUE(button->GetProminent()); EXPECT_TRUE(IsHighlighted(container_children.front()));
} }
TEST_F(MediaNotificationAudioDeviceSelectorViewTest, VisibilityChanges) { TEST_F(MediaNotificationAudioDeviceSelectorViewTest, VisibilityChanges) {
...@@ -253,7 +273,8 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, VisibilityChanges) { ...@@ -253,7 +273,8 @@ TEST_F(MediaNotificationAudioDeviceSelectorViewTest, VisibilityChanges) {
MockMediaNotificationAudioDeviceSelectorViewDelegate delegate; MockMediaNotificationAudioDeviceSelectorViewDelegate delegate;
EXPECT_CALL(delegate, OnAudioDeviceSelectorViewSizeChanged).Times(1); EXPECT_CALL(delegate, OnAudioDeviceSelectorViewSizeChanged).Times(1);
view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>( view_ = std::make_unique<MediaNotificationAudioDeviceSelectorView>(
&delegate, service_.get(), gfx::Size(), "1"); &delegate, service_.get(), "1", gfx::kPlaceholderColor,
gfx::kPlaceholderColor);
EXPECT_FALSE(view_->GetVisible()); EXPECT_FALSE(view_->GetVisible());
testing::Mock::VerifyAndClearExpectations(&delegate); testing::Mock::VerifyAndClearExpectations(&delegate);
......
...@@ -50,9 +50,6 @@ constexpr int kMinVisibleActionsForExpanding = 4; ...@@ -50,9 +50,6 @@ constexpr int kMinVisibleActionsForExpanding = 4;
// press as a click. // press as a click.
constexpr int kMinMovementSquaredToBeDragging = 10; constexpr int kMinMovementSquaredToBeDragging = 10;
// The height of the |MediaNotificationAudioDeviceSelectorView|.
constexpr int kAudioDeviceSelectorViewHeight = 40;
} // anonymous namespace } // anonymous namespace
class MediaNotificationContainerImplView::DismissButton class MediaNotificationContainerImplView::DismissButton
...@@ -128,8 +125,8 @@ MediaNotificationContainerImplView::MediaNotificationContainerImplView( ...@@ -128,8 +125,8 @@ MediaNotificationContainerImplView::MediaNotificationContainerImplView(
!is_cast_notification) { !is_cast_notification) {
auto audio_device_selector_view = auto audio_device_selector_view =
std::make_unique<MediaNotificationAudioDeviceSelectorView>( std::make_unique<MediaNotificationAudioDeviceSelectorView>(
this, service_, gfx::Size(kWidth, kAudioDeviceSelectorViewHeight), this, service_, audio_sink_id_, foreground_color_,
audio_sink_id_); background_color_);
audio_device_selector_view_ = audio_device_selector_view_ =
AddChildView(std::move(audio_device_selector_view)); AddChildView(std::move(audio_device_selector_view));
view_->UpdateCornerRadius(message_center::kNotificationCornerRadius, 0); view_->UpdateCornerRadius(message_center::kNotificationCornerRadius, 0);
...@@ -334,6 +331,8 @@ void MediaNotificationContainerImplView::OnColorsChanged(SkColor foreground, ...@@ -334,6 +331,8 @@ void MediaNotificationContainerImplView::OnColorsChanged(SkColor foreground,
background_color_ = background; background_color_ = background;
UpdateDismissButtonBackground(); UpdateDismissButtonBackground();
} }
if (audio_device_selector_view_)
audio_device_selector_view_->OnColorsChanged(foreground, background);
} }
void MediaNotificationContainerImplView::OnHeaderClicked() { void MediaNotificationContainerImplView::OnHeaderClicked() {
...@@ -484,6 +483,8 @@ void MediaNotificationContainerImplView::OnSizeChanged() { ...@@ -484,6 +483,8 @@ void MediaNotificationContainerImplView::OnSizeChanged() {
DCHECK(audio_device_selector_view_size.width() == kWidth); DCHECK(audio_device_selector_view_size.width() == kWidth);
new_size.set_height(new_size.height() + new_size.set_height(new_size.height() +
audio_device_selector_view_size.height()); audio_device_selector_view_size.height());
view_->UpdateAudioDeviceSelectorAvailability(
audio_device_selector_view_->GetVisible());
} }
if (overlay_) if (overlay_)
......
...@@ -302,6 +302,25 @@ void MediaNotificationBackground::Paint(gfx::Canvas* canvas, ...@@ -302,6 +302,25 @@ void MediaNotificationBackground::Paint(gfx::Canvas* canvas,
canvas->DrawRect(draw_bounds, flags); canvas->DrawRect(draw_bounds, flags);
} }
if (audio_device_selector_availability_) {
// Draw a gradient to fade the color background of the audio device picker
// and the image together.
gfx::Rect draw_bounds = GetBottomGradientBounds(*view);
const SkColor colors[2] = {
background_color, SkColorSetA(background_color, SK_AlphaTRANSPARENT)};
const SkPoint points[2] = {gfx::PointToSkPoint(draw_bounds.bottom_center()),
gfx::PointToSkPoint(draw_bounds.top_center())};
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setShader(cc::PaintShader::MakeLinearGradient(points, colors, nullptr,
2, SkTileMode::kClamp));
canvas->DrawRect(draw_bounds, flags);
}
} }
void MediaNotificationBackground::UpdateArtwork(const gfx::ImageSkia& image) { void MediaNotificationBackground::UpdateArtwork(const gfx::ImageSkia& image) {
...@@ -344,6 +363,14 @@ void MediaNotificationBackground::UpdateFavicon(const gfx::ImageSkia& icon) { ...@@ -344,6 +363,14 @@ void MediaNotificationBackground::UpdateFavicon(const gfx::ImageSkia& icon) {
UpdateColorsInternal(); UpdateColorsInternal();
} }
void MediaNotificationBackground::UpdateAudioDeviceSelectorAvailability(
bool availability) {
if (audio_device_selector_availability_ == availability)
return;
audio_device_selector_availability_ = availability;
}
SkColor MediaNotificationBackground::GetBackgroundColor( SkColor MediaNotificationBackground::GetBackgroundColor(
const views::View& owner) const { const views::View& owner) const {
if (background_color_.has_value()) if (background_color_.has_value())
...@@ -421,6 +448,20 @@ gfx::Rect MediaNotificationBackground::GetGradientBounds( ...@@ -421,6 +448,20 @@ gfx::Rect MediaNotificationBackground::GetGradientBounds(
view_bounds.y(), kMediaImageGradientWidth, view_bounds.height())); view_bounds.y(), kMediaImageGradientWidth, view_bounds.height()));
} }
gfx::Rect MediaNotificationBackground::GetBottomGradientBounds(
const views::View& owner) const {
if (artwork_.isNull())
return gfx::Rect(0, 0, 0, 0);
const gfx::Rect& view_bounds = owner.GetContentsBounds();
return owner.GetMirroredRect(gfx::Rect(
gfx::Point(
view_bounds.width() - GetArtworkVisibleWidth(view_bounds.size()),
view_bounds.bottom() - kMediaImageGradientWidth),
gfx::Size(GetArtworkVisibleWidth(view_bounds.size()),
kMediaImageGradientWidth)));
}
SkPoint MediaNotificationBackground::GetGradientStartPoint( SkPoint MediaNotificationBackground::GetGradientStartPoint(
const gfx::Rect& draw_bounds) const { const gfx::Rect& draw_bounds) const {
return gfx::PointToSkPoint(base::i18n::IsRTL() ? draw_bounds.right_center() return gfx::PointToSkPoint(base::i18n::IsRTL() ? draw_bounds.right_center()
......
...@@ -41,6 +41,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationBackground ...@@ -41,6 +41,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationBackground
bool UpdateCornerRadius(int top_radius, int bottom_radius); bool UpdateCornerRadius(int top_radius, int bottom_radius);
bool UpdateArtworkMaxWidthPct(double max_width_pct); bool UpdateArtworkMaxWidthPct(double max_width_pct);
void UpdateFavicon(const gfx::ImageSkia& icon); void UpdateFavicon(const gfx::ImageSkia& icon);
void UpdateAudioDeviceSelectorAvailability(bool availability);
SkColor GetBackgroundColor(const views::View& owner) const; SkColor GetBackgroundColor(const views::View& owner) const;
SkColor GetForegroundColor(const views::View& owner) const; SkColor GetForegroundColor(const views::View& owner) const;
...@@ -59,6 +60,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationBackground ...@@ -59,6 +60,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationBackground
gfx::Rect GetArtworkBounds(const views::View& owner) const; gfx::Rect GetArtworkBounds(const views::View& owner) const;
gfx::Rect GetFilledBackgroundBounds(const views::View& owner) const; gfx::Rect GetFilledBackgroundBounds(const views::View& owner) const;
gfx::Rect GetGradientBounds(const views::View& owner) const; gfx::Rect GetGradientBounds(const views::View& owner) const;
gfx::Rect GetBottomGradientBounds(const views::View& owner) const;
SkPoint GetGradientStartPoint(const gfx::Rect& draw_bounds) const; SkPoint GetGradientStartPoint(const gfx::Rect& draw_bounds) const;
SkPoint GetGradientEndPoint(const gfx::Rect& draw_bounds) const; SkPoint GetGradientEndPoint(const gfx::Rect& draw_bounds) const;
SkColor GetDefaultBackgroundColor(const views::View& owner) const; SkColor GetDefaultBackgroundColor(const views::View& owner) const;
...@@ -70,6 +72,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationBackground ...@@ -70,6 +72,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationBackground
gfx::ImageSkia favicon_; gfx::ImageSkia favicon_;
gfx::ImageSkia artwork_; gfx::ImageSkia artwork_;
double artwork_max_width_pct_; double artwork_max_width_pct_;
bool audio_device_selector_availability_;
base::Optional<SkColor> background_color_; base::Optional<SkColor> background_color_;
base::Optional<SkColor> foreground_color_; base::Optional<SkColor> foreground_color_;
......
...@@ -474,6 +474,12 @@ void MediaNotificationViewImpl::OnThemeChanged() { ...@@ -474,6 +474,12 @@ void MediaNotificationViewImpl::OnThemeChanged() {
UpdateForegroundColor(); UpdateForegroundColor();
} }
void MediaNotificationViewImpl::UpdateAudioDeviceSelectorAvailability(
bool availability) {
GetMediaNotificationBackground()->UpdateAudioDeviceSelectorAvailability(
availability);
}
views::Button* MediaNotificationViewImpl::GetHeaderRowForTesting() const { views::Button* MediaNotificationViewImpl::GetHeaderRowForTesting() const {
return header_row_; return header_row_;
} }
......
...@@ -83,6 +83,8 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewImpl ...@@ -83,6 +83,8 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewImpl
void UpdateWithVectorIcon(const gfx::VectorIcon& vector_icon) override; void UpdateWithVectorIcon(const gfx::VectorIcon& vector_icon) override;
void OnThemeChanged() override; void OnThemeChanged() override;
void UpdateAudioDeviceSelectorAvailability(bool availability);
const views::Label* title_label_for_testing() const { return title_label_; } const views::Label* title_label_for_testing() const { return title_label_; }
const views::Label* artist_label_for_testing() const { return artist_label_; } const views::Label* artist_label_for_testing() const { return artist_label_; }
......
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