Commit 8f1d3e6d authored by Muyao Xu's avatar Muyao Xu Committed by Commit Bot

[Cast+Zenith] Modify the Cast/AudioDeviceEntryView UI

AudioDeviceEntryView is changed to be a sub-class of HoverButton.
Changed button colors and added ink drop effects in
Cast/AudioDeviceEntryView.

Bug: b/161610050, 1107162
Change-Id: If91d5041cbf81954bd2a3c9a8b5fd79fe3fdf22e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2387204
Commit-Queue: Muyao Xu <muyaoxu@google.com>
Reviewed-by: default avatarTakumi Fujimoto <takumif@chromium.org>
Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#808420}
parent 7d41cc89
...@@ -6,91 +6,74 @@ ...@@ -6,91 +6,74 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "components/vector_icons/vector_icons.h" #include "components/vector_icons/vector_icons.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/animation/ink_drop.h"
#include "ui/views/background.h" #include "ui/views/background.h"
#include "ui/views/controls/button/label_button.h" #include "ui/views/controls/styled_label.h"
#include "ui/views/layout/box_layout.h"
namespace { namespace {
constexpr gfx::Insets kIconContainerInsets{10, 15}; constexpr int kDeviceIconSize = 20;
constexpr int kDeviceIconSize = 18; constexpr auto kDeviceIconBorder = gfx::Insets(6);
constexpr gfx::Insets kLabelsContainerInsets{18, 0};
constexpr gfx::Size kDeviceEntryViewSize{400, 30}; constexpr gfx::Size kDeviceEntryViewSize{400, 30};
constexpr int kEntryHighlightOpacity = 45; constexpr int kEntryHighlightOpacity = 45;
void ChangeEntryColor(views::ImageView* image_view,
views::StyledLabel* title_view,
views::Label* subtitle_view,
const gfx::VectorIcon* icon,
SkColor foreground_color,
SkColor background_color) {
image_view->SetImage(
gfx::CreateVectorIcon(*icon, kDeviceIconSize, foreground_color));
title_view->SetDisplayedOnBackgroundColor(background_color);
if (!title_view->GetText().empty()) {
views::StyledLabel::RangeStyleInfo style_info;
style_info.text_style = views::style::STYLE_PRIMARY;
style_info.override_color = foreground_color;
title_view->ClearStyleRanges();
title_view->AddStyleRange(gfx::Range(0, title_view->GetText().length()),
style_info);
title_view->SizeToFit(0);
}
if (subtitle_view) {
subtitle_view->SetEnabledColor(foreground_color);
subtitle_view->SetBackgroundColor(background_color);
}
}
std::unique_ptr<views::ImageView> GetAudioDeviceIcon() {
auto icon_view = std::make_unique<views::ImageView>();
icon_view->SetImage(gfx::CreateVectorIcon(
vector_icons::kHeadsetIcon, kDeviceIconSize, gfx::kPlaceholderColor));
icon_view->SetBorder(views::CreateEmptyBorder(kDeviceIconBorder));
return icon_view;
}
} // namespace } // namespace
DeviceEntryUI::DeviceEntryUI(SkColor foreground_color, DeviceEntryUI::DeviceEntryUI(const std::string& raw_device_id,
SkColor background_color,
const std::string& raw_device_id,
const std::string& device_name, const std::string& device_name,
const gfx::VectorIcon* icon, const gfx::VectorIcon* icon,
const std::string& subtext) const std::string& subtext)
: foreground_color_(foreground_color), : raw_device_id_(raw_device_id), device_name_(device_name), icon_(icon) {}
background_color_(background_color),
raw_device_id_(raw_device_id), AudioDeviceEntryView::AudioDeviceEntryView(
device_name_(device_name), views::ButtonListener* button_listener,
icon_(icon) {} SkColor foreground_color,
SkColor background_color,
std::string DeviceEntryUI::GetEntryLabelForTesting() { const std::string& raw_device_id,
return base::UTF16ToUTF8(device_name_label_->GetText()); const std::string& device_name,
} const std::string& subtext)
: DeviceEntryUI(raw_device_id, device_name, &vector_icons::kHeadsetIcon),
AudioDeviceEntryView::AudioDeviceEntryView(SkColor foreground_color, HoverButton(button_listener,
SkColor background_color, GetAudioDeviceIcon(),
const std::string& raw_device_id, base::UTF8ToUTF16(device_name),
const std::string& device_name, base::UTF8ToUTF16(subtext)) {
const std::string& subtext) ChangeEntryColor(static_cast<views::ImageView*>(icon_view()), title(),
: DeviceEntryUI(foreground_color, subtitle(), icon_, foreground_color, background_color);
background_color,
raw_device_id,
device_name,
&vector_icons::kHeadsetIcon) {
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal));
icon_container_ = AddChildView(std::make_unique<views::View>());
auto* icon_container_layout =
icon_container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, kIconContainerInsets));
icon_container_layout->set_main_axis_alignment(
views::BoxLayout::MainAxisAlignment::kCenter);
icon_container_layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter);
device_icon_ =
icon_container_->AddChildView(std::make_unique<views::ImageView>());
device_icon_->SetImage(
gfx::CreateVectorIcon(*icon_, kDeviceIconSize, foreground_color));
labels_container_ = AddChildView(std::make_unique<views::View>());
auto* labels_container_layout =
labels_container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, kLabelsContainerInsets));
labels_container_layout->set_main_axis_alignment(
views::BoxLayout::MainAxisAlignment::kCenter);
labels_container_layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kStart);
views::Label::CustomFont device_name_label_font{
views::Label::GetDefaultFontList().DeriveWithSizeDelta(1)};
device_name_label_ =
labels_container_->AddChildView(std::make_unique<views::Label>(
base::UTF8ToUTF16(device_name_), device_name_label_font));
device_name_label_->SetEnabledColor(foreground_color);
device_name_label_->SetBackgroundColor(background_color);
if (!subtext.empty()) {
device_subtext_label_ = labels_container_->AddChildView(
std::make_unique<views::Label>(base::UTF8ToUTF16(subtext)));
device_subtext_label_->SetTextStyle(
views::style::TextStyle::STYLE_SECONDARY);
device_subtext_label_->SetEnabledColor(foreground_color);
device_subtext_label_->SetBackgroundColor(background_color);
}
// Ensures that hovering over these items also hovers this view.
icon_container_->set_can_process_events_within_subtree(false);
labels_container_->set_can_process_events_within_subtree(false);
SetFocusBehavior(views::View::FocusBehavior::ALWAYS); SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
SetInkDropMode(Button::InkDropMode::ON); SetInkDropMode(Button::InkDropMode::ON);
...@@ -115,46 +98,55 @@ void AudioDeviceEntryView::SetHighlighted(bool highlighted) { ...@@ -115,46 +98,55 @@ void AudioDeviceEntryView::SetHighlighted(bool highlighted) {
void AudioDeviceEntryView::OnColorsChanged(SkColor foreground_color, void AudioDeviceEntryView::OnColorsChanged(SkColor foreground_color,
SkColor background_color) { SkColor background_color) {
foreground_color_ = foreground_color; set_ink_drop_base_color(foreground_color);
background_color_ = background_color;
set_ink_drop_base_color(foreground_color_);
device_icon_->SetImage(
gfx::CreateVectorIcon(*icon_, kDeviceIconSize, foreground_color_));
device_name_label_->SetEnabledColor(foreground_color_);
device_name_label_->SetBackgroundColor(background_color_);
if (device_subtext_label_) { ChangeEntryColor(static_cast<views::ImageView*>(icon_view()), title(),
device_subtext_label_->SetEnabledColor(foreground_color_); subtitle(), icon_, foreground_color, background_color);
device_subtext_label_->SetBackgroundColor(background_color_);
}
// Reapply highlight formatting as some effects rely on these colors. // Reapply highlight formatting as some effects rely on these colors.
SetHighlighted(is_highlighted_); SetHighlighted(is_highlighted_);
} }
SkColor AudioDeviceEntryView::GetInkDropBaseColor() const {
return views::Button::GetInkDropBaseColor();
}
DeviceEntryUIType AudioDeviceEntryView::GetType() const { DeviceEntryUIType AudioDeviceEntryView::GetType() const {
return DeviceEntryUIType::kAudio; return DeviceEntryUIType::kAudio;
} }
CastDeviceEntryView::CastDeviceEntryView(SkColor foreground_color, CastDeviceEntryView::CastDeviceEntryView(views::ButtonListener* button_listener,
SkColor foreground_color,
SkColor background_color, SkColor background_color,
const media_router::UIMediaSink& sink) const media_router::UIMediaSink& sink)
: DeviceEntryUI(foreground_color, : DeviceEntryUI(sink.id,
background_color,
sink.id,
base::UTF16ToUTF8(sink.friendly_name), base::UTF16ToUTF8(sink.friendly_name),
// TODO(muyaoxu): change device icon CastDialogSinkButton::GetVectorIcon(sink.icon_type)),
&vector_icons::kHeadsetIcon), CastDialogSinkButton(button_listener,
CastDialogSinkButton(nullptr,
sink, sink,
/* TODO(muyaoxu): change this to button_tag */ 0) {} /* TODO(muyaoxu): button tag */ -1) {
// TODO(muyaoxu): change the sink's style based on its UIMediaSinkState
ChangeEntryColor(static_cast<views::ImageView*>(icon_view()), title(),
subtitle(), icon_, foreground_color, background_color);
SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
SetInkDropMode(Button::InkDropMode::ON);
set_ink_drop_base_color(foreground_color);
set_has_ink_drop_action_on_click(true);
SetPreferredSize(kDeviceEntryViewSize);
}
// TODO(muyaoxu): Implement this function
void CastDeviceEntryView::OnColorsChanged(SkColor foreground_color, void CastDeviceEntryView::OnColorsChanged(SkColor foreground_color,
SkColor background_color) {} SkColor background_color) {
set_ink_drop_base_color(foreground_color);
ChangeEntryColor(static_cast<views::ImageView*>(icon_view()), title(),
subtitle(), icon_, foreground_color, background_color);
}
DeviceEntryUIType CastDeviceEntryView::GetType() const { DeviceEntryUIType CastDeviceEntryView::GetType() const {
return DeviceEntryUIType::kCast; return DeviceEntryUIType::kCast;
} }
SkColor CastDeviceEntryView::GetInkDropBaseColor() const {
return views::Button::GetInkDropBaseColor();
}
...@@ -6,14 +6,6 @@ ...@@ -6,14 +6,6 @@
#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_ENTRY_UI_H_ #define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_ENTRY_UI_H_
#include "chrome/browser/ui/views/media_router/cast_dialog_sink_button.h" #include "chrome/browser/ui/views/media_router/cast_dialog_sink_button.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/vector_icon_types.h"
#include "ui/views/controls/button/button.h"
namespace views {
class ImageView;
class Label;
} // namespace views
enum class DeviceEntryUIType { enum class DeviceEntryUIType {
kAudio = 0, kAudio = 0,
...@@ -23,9 +15,7 @@ enum class DeviceEntryUIType { ...@@ -23,9 +15,7 @@ enum class DeviceEntryUIType {
class DeviceEntryUI { class DeviceEntryUI {
public: public:
DeviceEntryUI(SkColor foreground_color, DeviceEntryUI(const std::string& raw_device_id,
SkColor background_color,
const std::string& raw_device_id,
const std::string& device_name, const std::string& device_name,
const gfx::VectorIcon* icon_, const gfx::VectorIcon* icon_,
const std::string& subtext = ""); const std::string& subtext = "");
...@@ -41,45 +31,41 @@ class DeviceEntryUI { ...@@ -41,45 +31,41 @@ class DeviceEntryUI {
SkColor background_color) = 0; SkColor background_color) = 0;
virtual DeviceEntryUIType GetType() const = 0; virtual DeviceEntryUIType GetType() const = 0;
std::string GetEntryLabelForTesting();
bool GetEntryIsHighlightedForTesting() const { return is_highlighted_; } bool GetEntryIsHighlightedForTesting() const { return is_highlighted_; }
protected: protected:
SkColor foreground_color_, background_color_;
const std::string raw_device_id_; const std::string raw_device_id_;
const std::string device_name_; const std::string device_name_;
bool is_highlighted_ = false; bool is_highlighted_ = false;
const gfx::VectorIcon* const icon_; const gfx::VectorIcon* const icon_;
views::Label* device_name_label_ = nullptr;
}; };
class AudioDeviceEntryView : public views::Button, public DeviceEntryUI { class AudioDeviceEntryView : public DeviceEntryUI, public HoverButton {
public: public:
AudioDeviceEntryView(SkColor foreground_color, AudioDeviceEntryView(views::ButtonListener* button_listener,
SkColor foreground_color,
SkColor background_color, SkColor background_color,
const std::string& raw_device_id, const std::string& raw_device_id,
const std::string& name, const std::string& name,
const std::string& subtext = ""); const std::string& subtext = "");
~AudioDeviceEntryView() override = default; ~AudioDeviceEntryView() override = default;
void SetHighlighted(bool highlighted);
// DeviceEntryUI // DeviceEntryUI
void OnColorsChanged(SkColor foreground_color, void OnColorsChanged(SkColor foreground_color,
SkColor background_color) override; SkColor background_color) override;
DeviceEntryUIType GetType() const override; DeviceEntryUIType GetType() const override;
private: // HoverButton
views::View* icon_container_ = nullptr; SkColor GetInkDropBaseColor() const override;
views::ImageView* device_icon_ = nullptr;
views::View* labels_container_ = nullptr; void SetHighlighted(bool highlighted);
views::Label* device_subtext_label_ = nullptr;
}; };
class CastDeviceEntryView : public DeviceEntryUI, class CastDeviceEntryView : public DeviceEntryUI,
public media_router::CastDialogSinkButton { public media_router::CastDialogSinkButton {
public: public:
CastDeviceEntryView(SkColor foreground_color, CastDeviceEntryView(views::ButtonListener* button_listener,
SkColor foreground_color,
SkColor background_color, SkColor background_color,
const media_router::UIMediaSink& sink); const media_router::UIMediaSink& sink);
~CastDeviceEntryView() override = default; ~CastDeviceEntryView() override = default;
...@@ -88,6 +74,9 @@ class CastDeviceEntryView : public DeviceEntryUI, ...@@ -88,6 +74,9 @@ class CastDeviceEntryView : public DeviceEntryUI,
void OnColorsChanged(SkColor foreground_color, void OnColorsChanged(SkColor foreground_color,
SkColor background_color) override; SkColor background_color) override;
DeviceEntryUIType GetType() const override; DeviceEntryUIType GetType() const override;
// HoverButton
SkColor GetInkDropBaseColor() const override;
}; };
#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_ENTRY_UI_H_ #endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_ENTRY_UI_H_
...@@ -184,9 +184,8 @@ void MediaNotificationDeviceSelectorView::UpdateAvailableAudioDevices( ...@@ -184,9 +184,8 @@ void MediaNotificationDeviceSelectorView::UpdateAvailableAudioDevices(
bool current_device_still_exists = false; bool current_device_still_exists = false;
for (auto description : device_descriptions) { for (auto description : device_descriptions) {
auto device_entry_view = std::make_unique<AudioDeviceEntryView>( auto device_entry_view = std::make_unique<AudioDeviceEntryView>(
foreground_color_, background_color_, description.unique_id, this, foreground_color_, background_color_, description.unique_id,
description.device_name, ""); description.device_name, "");
device_entry_view->set_listener(this);
device_entry_view->set_tag(next_tag_++); device_entry_view->set_tag(next_tag_++);
device_entry_ui_map_[device_entry_view->tag()] = device_entry_view.get(); device_entry_ui_map_[device_entry_view->tag()] = device_entry_view.get();
device_entry_views_container_->AddChildView(std::move(device_entry_view)); device_entry_views_container_->AddChildView(std::move(device_entry_view));
...@@ -354,13 +353,14 @@ void MediaNotificationDeviceSelectorView::OnModelUpdated( ...@@ -354,13 +353,14 @@ void MediaNotificationDeviceSelectorView::OnModelUpdated(
RemoveDevicesOfType(DeviceEntryUIType::kCast); RemoveDevicesOfType(DeviceEntryUIType::kCast);
for (auto sink : model.media_sinks()) { for (auto sink : model.media_sinks()) {
auto device_entry_view = std::make_unique<CastDeviceEntryView>( auto device_entry_view = std::make_unique<CastDeviceEntryView>(
foreground_color_, background_color_, sink); this, foreground_color_, background_color_, sink);
device_entry_view->set_tag(next_tag_++); device_entry_view->set_tag(next_tag_++);
device_entry_ui_map_[device_entry_view->tag()] = device_entry_view.get(); device_entry_ui_map_[device_entry_view->tag()] = device_entry_view.get();
device_entry_views_container_->AddChildView(std::move(device_entry_view)); device_entry_views_container_->AddChildView(std::move(device_entry_view));
} }
SetVisible(true); SetVisible(true);
delegate_->OnDeviceSelectorViewSizeChanged(); delegate_->OnDeviceSelectorViewSizeChanged();
Layout();
} }
void MediaNotificationDeviceSelectorView::OnControllerInvalidated() { void MediaNotificationDeviceSelectorView::OnControllerInvalidated() {
......
...@@ -11,9 +11,6 @@ ...@@ -11,9 +11,6 @@
#include "chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.h" #include "chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.h"
#include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h" #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
#include "media/audio/audio_device_description.h" #include "media/audio/audio_device_description.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/layout/box_layout.h"
namespace { namespace {
class ExpandDeviceSelectorButton; class ExpandDeviceSelectorButton;
...@@ -73,13 +70,13 @@ class MediaNotificationDeviceSelectorView ...@@ -73,13 +70,13 @@ class MediaNotificationDeviceSelectorView
FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest,
ExpandButtonOpensEntryContainer); ExpandButtonOpensEntryContainer);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest,
DeviceButtonClickNotifiesContainer); AudioDeviceButtonClickNotifiesContainer);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest,
CurrentDeviceHighlighted); CurrentAudioDeviceHighlighted);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest,
DeviceHighlightedOnChange); AudioDeviceHighlightedOnChange);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest,
DeviceButtonsChange); AudioDeviceButtonsChange);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest,
AudioDevicesCountHistogramRecorded); AudioDevicesCountHistogramRecorded);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/time/time.h" #include "base/time/time.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"
#include "chrome/browser/ui/global_media_controls/media_notification_service.h" #include "chrome/browser/ui/global_media_controls/media_notification_service.h"
#include "chrome/browser/ui/media_router/cast_dialog_model.h"
#include "chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_delegate.h" #include "chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_delegate.h"
#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"
...@@ -18,10 +19,29 @@ ...@@ -18,10 +19,29 @@
#include "ui/events/base_event_utils.h" #include "ui/events/base_event_utils.h"
#include "ui/gfx/color_palette.h" #include "ui/gfx/color_palette.h"
using media_router::CastDialogController;
using media_router::CastDialogModel;
using media_router::UIMediaSink;
using media_router::UIMediaSinkState;
class MediaNotificationContainerObserver; class MediaNotificationContainerObserver;
namespace { namespace {
UIMediaSink CreateAvailableSink() {
UIMediaSink sink;
sink.friendly_name = base::UTF8ToUTF16("Nest Hub");
sink.id = "sink_available";
sink.state = UIMediaSinkState::AVAILABLE;
return sink;
}
CastDialogModel CreateModelWithSinks(std::vector<UIMediaSink> sinks) {
CastDialogModel model;
model.set_media_sinks(std::move(sinks));
return model;
}
class MockMediaNotificationDeviceProvider class MockMediaNotificationDeviceProvider
: public MediaNotificationDeviceProvider { : public MediaNotificationDeviceProvider {
public: public:
...@@ -101,6 +121,19 @@ class MockMediaNotificationDeviceSelectorViewDelegate ...@@ -101,6 +121,19 @@ class MockMediaNotificationDeviceSelectorViewDelegate
base::RepeatingCallback<void(bool)> supports_switching_callback_; base::RepeatingCallback<void(bool)> supports_switching_callback_;
}; };
class MockCastDialogController : public CastDialogController {
public:
MOCK_METHOD1(AddObserver, void(CastDialogController::Observer* observer));
MOCK_METHOD1(RemoveObserver, void(CastDialogController::Observer* observer));
MOCK_METHOD2(StartCasting,
void(const std::string& sink_id,
media_router::MediaCastMode cast_mode));
MOCK_METHOD1(StopCasting, void(const std::string& route_id));
MOCK_METHOD1(
ChooseLocalFile,
void(base::OnceCallback<void(const ui::SelectedFileInfo*)> callback));
MOCK_METHOD1(ClearIssue, void(const media_router::Issue::Id& issue_id));
};
} // anonymous namespace } // anonymous namespace
class MediaNotificationDeviceSelectorViewTest : public ChromeViewsTestBase { class MediaNotificationDeviceSelectorViewTest : public ChromeViewsTestBase {
...@@ -116,6 +149,14 @@ class MediaNotificationDeviceSelectorViewTest : public ChromeViewsTestBase { ...@@ -116,6 +149,14 @@ class MediaNotificationDeviceSelectorViewTest : public ChromeViewsTestBase {
ChromeViewsTestBase::TearDown(); ChromeViewsTestBase::TearDown();
} }
void AddAudioDevices(
MockMediaNotificationDeviceSelectorViewDelegate& delegate) {
auto* provider = delegate.GetProvider();
provider->AddDevice("Speaker", "1");
provider->AddDevice("Headphones", "2");
provider->AddDevice("Earbuds", "3");
}
void SimulateButtonClick(views::View* view) { void SimulateButtonClick(views::View* view) {
view_->ButtonPressed( view_->ButtonPressed(
static_cast<views::Button*>(view), static_cast<views::Button*>(view),
...@@ -140,37 +181,31 @@ class MediaNotificationDeviceSelectorViewTest : public ChromeViewsTestBase { ...@@ -140,37 +181,31 @@ class MediaNotificationDeviceSelectorViewTest : public ChromeViewsTestBase {
}; };
TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceButtonsCreated) { TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceButtonsCreated) {
// Buttons should be created for every device reported by the provider // Buttons should be created for every device reported by the provider.
MockMediaNotificationDeviceSelectorViewDelegate delegate; MockMediaNotificationDeviceSelectorViewDelegate delegate;
auto* provider = delegate.GetProvider(); AddAudioDevices(delegate);
provider->AddDevice("Speaker", "1");
provider->AddDevice("Headphones", "2");
provider->AddDevice("Earbuds", "3");
view_ = std::make_unique<MediaNotificationDeviceSelectorView>( view_ = std::make_unique<MediaNotificationDeviceSelectorView>(
&delegate, /* media_router::CastDialogController*/ nullptr, "1", &delegate, std::make_unique<MockCastDialogController>(), "1",
gfx::kPlaceholderColor, gfx::kPlaceholderColor); gfx::kPlaceholderColor, gfx::kPlaceholderColor);
view_->OnModelUpdated(CreateModelWithSinks({CreateAvailableSink()}));
ASSERT_TRUE(view_->device_entry_views_container_ != nullptr); ASSERT_TRUE(view_->device_entry_views_container_ != nullptr);
auto container_children = view_->device_entry_views_container_->children(); auto container_children = view_->device_entry_views_container_->children();
ASSERT_EQ(container_children.size(), 3u); ASSERT_EQ(container_children.size(), 4u);
EXPECT_EQ(EntryLabelText(container_children.at(0)), "Speaker"); EXPECT_EQ(EntryLabelText(container_children.at(0)), "Speaker");
EXPECT_EQ(EntryLabelText(container_children.at(1)), "Headphones"); EXPECT_EQ(EntryLabelText(container_children.at(1)), "Headphones");
EXPECT_EQ(EntryLabelText(container_children.at(2)), "Earbuds"); EXPECT_EQ(EntryLabelText(container_children.at(2)), "Earbuds");
EXPECT_EQ(EntryLabelText(container_children.at(3)), "Nest Hub");
} }
TEST_F(MediaNotificationDeviceSelectorViewTest, TEST_F(MediaNotificationDeviceSelectorViewTest,
ExpandButtonOpensEntryContainer) { ExpandButtonOpensEntryContainer) {
MockMediaNotificationDeviceSelectorViewDelegate delegate; MockMediaNotificationDeviceSelectorViewDelegate delegate;
auto* provider = delegate.GetProvider(); AddAudioDevices(delegate);
provider->AddDevice("Speaker", "1");
provider->AddDevice("Headphones", "2");
provider->AddDevice("Earbuds", "3");
view_ = std::make_unique<MediaNotificationDeviceSelectorView>( view_ = std::make_unique<MediaNotificationDeviceSelectorView>(
&delegate, /* media_router::CastDialogController*/ nullptr, "1", &delegate, std::make_unique<MockCastDialogController>(), "1",
gfx::kPlaceholderColor, gfx::kPlaceholderColor); gfx::kPlaceholderColor, gfx::kPlaceholderColor);
ASSERT_TRUE(view_->expand_button_); ASSERT_TRUE(view_->expand_button_);
...@@ -180,17 +215,13 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, ...@@ -180,17 +215,13 @@ TEST_F(MediaNotificationDeviceSelectorViewTest,
} }
TEST_F(MediaNotificationDeviceSelectorViewTest, TEST_F(MediaNotificationDeviceSelectorViewTest,
DeviceButtonClickNotifiesContainer) { AudioDeviceButtonClickNotifiesContainer) {
// When buttons are clicked the media notification delegate should be // When buttons are clicked the media notification delegate should be
// informed. // informed.
MockMediaNotificationDeviceSelectorViewDelegate delegate; MockMediaNotificationDeviceSelectorViewDelegate delegate;
auto* provider = delegate.GetProvider(); AddAudioDevices(delegate);
provider->AddDevice("Speaker", "1");
provider->AddDevice("Headphones", "2");
provider->AddDevice("Earbuds", "3");
view_ = std::make_unique<MediaNotificationDeviceSelectorView>( view_ = std::make_unique<MediaNotificationDeviceSelectorView>(
&delegate, /* media_router::CastDialogController*/ nullptr, "1", &delegate, std::make_unique<MockCastDialogController>(), "1",
gfx::kPlaceholderColor, gfx::kPlaceholderColor); gfx::kPlaceholderColor, gfx::kPlaceholderColor);
EXPECT_CALL(delegate, OnAudioSinkChosen("1")).Times(1); EXPECT_CALL(delegate, OnAudioSinkChosen("1")).Times(1);
...@@ -202,17 +233,13 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, ...@@ -202,17 +233,13 @@ TEST_F(MediaNotificationDeviceSelectorViewTest,
} }
} }
TEST_F(MediaNotificationDeviceSelectorViewTest, CurrentDeviceHighlighted) { TEST_F(MediaNotificationDeviceSelectorViewTest, CurrentAudioDeviceHighlighted) {
// The 'current' audio device should be highlighted in the UI and appear // The 'current' audio device should be highlighted in the UI and appear
// before other devices. // before other devices.
MockMediaNotificationDeviceSelectorViewDelegate delegate; MockMediaNotificationDeviceSelectorViewDelegate delegate;
auto* provider = delegate.GetProvider(); AddAudioDevices(delegate);
provider->AddDevice("Speaker", "1");
provider->AddDevice("Headphones", "2");
provider->AddDevice("Earbuds", "3");
view_ = std::make_unique<MediaNotificationDeviceSelectorView>( view_ = std::make_unique<MediaNotificationDeviceSelectorView>(
&delegate, /* media_router::CastDialogController*/ nullptr, "3", &delegate, std::make_unique<MockCastDialogController>(), "3",
gfx::kPlaceholderColor, gfx::kPlaceholderColor); gfx::kPlaceholderColor, gfx::kPlaceholderColor);
auto* first_entry = view_->device_entry_views_container_->children().front(); auto* first_entry = view_->device_entry_views_container_->children().front();
...@@ -220,16 +247,13 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, CurrentDeviceHighlighted) { ...@@ -220,16 +247,13 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, CurrentDeviceHighlighted) {
EXPECT_TRUE(IsHighlighted(first_entry)); EXPECT_TRUE(IsHighlighted(first_entry));
} }
TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceHighlightedOnChange) { TEST_F(MediaNotificationDeviceSelectorViewTest,
AudioDeviceHighlightedOnChange) {
// When the audio output device changes, the UI should highlight that one. // When the audio output device changes, the UI should highlight that one.
MockMediaNotificationDeviceSelectorViewDelegate delegate; MockMediaNotificationDeviceSelectorViewDelegate delegate;
auto* provider = delegate.GetProvider(); AddAudioDevices(delegate);
provider->AddDevice("Speaker", "1");
provider->AddDevice("Headphones", "2");
provider->AddDevice("Earbuds", "3");
view_ = std::make_unique<MediaNotificationDeviceSelectorView>( view_ = std::make_unique<MediaNotificationDeviceSelectorView>(
&delegate, /* media_router::CastDialogController*/ nullptr, "1", &delegate, std::make_unique<MockCastDialogController>(), "1",
gfx::kPlaceholderColor, gfx::kPlaceholderColor); gfx::kPlaceholderColor, gfx::kPlaceholderColor);
auto& container_children = view_->device_entry_views_container_->children(); auto& container_children = view_->device_entry_views_container_->children();
...@@ -252,19 +276,16 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceHighlightedOnChange) { ...@@ -252,19 +276,16 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceHighlightedOnChange) {
EXPECT_EQ(EntryLabelText(container_children.front()), "Earbuds"); EXPECT_EQ(EntryLabelText(container_children.front()), "Earbuds");
} }
TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceButtonsChange) { TEST_F(MediaNotificationDeviceSelectorViewTest, AudioDeviceButtonsChange) {
// If the device provider reports a change in connect audio devices, the UI // If the device provider reports a change in connect audio devices, the UI
// should update accordingly. // should update accordingly.
MockMediaNotificationDeviceSelectorViewDelegate delegate; MockMediaNotificationDeviceSelectorViewDelegate delegate;
auto* provider = delegate.GetProvider(); AddAudioDevices(delegate);
provider->AddDevice("Speaker", "1");
provider->AddDevice("Headphones", "2");
provider->AddDevice("Earbuds", "3");
view_ = std::make_unique<MediaNotificationDeviceSelectorView>( view_ = std::make_unique<MediaNotificationDeviceSelectorView>(
&delegate, /* media_router::CastDialogController*/ nullptr, "1", &delegate, std::make_unique<MockCastDialogController>(), "1",
gfx::kPlaceholderColor, gfx::kPlaceholderColor); gfx::kPlaceholderColor, gfx::kPlaceholderColor);
auto* provider = delegate.GetProvider();
provider->ResetDevices(); provider->ResetDevices();
// Make "Monitor" the default device. // Make "Monitor" the default device.
provider->AddDevice("Monitor", provider->AddDevice("Monitor",
...@@ -283,9 +304,7 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceButtonsChange) { ...@@ -283,9 +304,7 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceButtonsChange) {
} }
provider->ResetDevices(); provider->ResetDevices();
provider->AddDevice("Speaker", "1"); AddAudioDevices(delegate);
provider->AddDevice("Headphones", "2");
provider->AddDevice("Earbuds", "3");
provider->RunUICallback(); provider->RunUICallback();
{ {
...@@ -312,7 +331,7 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, VisibilityChanges) { ...@@ -312,7 +331,7 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, VisibilityChanges) {
EXPECT_CALL(delegate, OnDeviceSelectorViewSizeChanged).Times(2); EXPECT_CALL(delegate, OnDeviceSelectorViewSizeChanged).Times(2);
view_ = std::make_unique<MediaNotificationDeviceSelectorView>( view_ = std::make_unique<MediaNotificationDeviceSelectorView>(
&delegate, /* CastDialogController */ nullptr, &delegate, std::make_unique<MockCastDialogController>(),
media::AudioDeviceDescription::kDefaultDeviceId, gfx::kPlaceholderColor, media::AudioDeviceDescription::kDefaultDeviceId, gfx::kPlaceholderColor,
gfx::kPlaceholderColor); gfx::kPlaceholderColor);
EXPECT_FALSE(view_->GetVisible()); EXPECT_FALSE(view_->GetVisible());
...@@ -339,16 +358,14 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, VisibilityChanges) { ...@@ -339,16 +358,14 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, VisibilityChanges) {
testing::Mock::VerifyAndClearExpectations(&delegate); testing::Mock::VerifyAndClearExpectations(&delegate);
} }
TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceChangeIsNotSupported) { TEST_F(MediaNotificationDeviceSelectorViewTest,
AudioDeviceChangeIsNotSupported) {
MockMediaNotificationDeviceSelectorViewDelegate delegate; MockMediaNotificationDeviceSelectorViewDelegate delegate;
auto* provider = delegate.GetProvider(); AddAudioDevices(delegate);
provider->AddDevice("Speaker", "1");
provider->AddDevice("Headphones", "2");
provider->AddDevice("Earbuds", "3");
delegate.supports_switching = false; delegate.supports_switching = false;
view_ = std::make_unique<MediaNotificationDeviceSelectorView>( view_ = std::make_unique<MediaNotificationDeviceSelectorView>(
&delegate, /* CastDialogController */ nullptr, &delegate, std::make_unique<MockCastDialogController>(),
media::AudioDeviceDescription::kDefaultDeviceId, gfx::kPlaceholderColor, media::AudioDeviceDescription::kDefaultDeviceId, gfx::kPlaceholderColor,
gfx::kPlaceholderColor); gfx::kPlaceholderColor);
EXPECT_FALSE(view_->GetVisible()); EXPECT_FALSE(view_->GetVisible());
...@@ -361,10 +378,7 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceChangeIsNotSupported) { ...@@ -361,10 +378,7 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceChangeIsNotSupported) {
TEST_F(MediaNotificationDeviceSelectorViewTest, TEST_F(MediaNotificationDeviceSelectorViewTest,
AudioDevicesCountHistogramRecorded) { AudioDevicesCountHistogramRecorded) {
MockMediaNotificationDeviceSelectorViewDelegate delegate; MockMediaNotificationDeviceSelectorViewDelegate delegate;
auto* provider = delegate.GetProvider(); AddAudioDevices(delegate);
provider->AddDevice("Speaker", "1");
provider->AddDevice("Headphones", "2");
provider->AddDevice("Earbuds", "3");
histogram_tester_.ExpectTotalCount(kAudioDevicesCountHistogramName, 0); histogram_tester_.ExpectTotalCount(kAudioDevicesCountHistogramName, 0);
...@@ -376,6 +390,7 @@ TEST_F(MediaNotificationDeviceSelectorViewTest, ...@@ -376,6 +390,7 @@ TEST_F(MediaNotificationDeviceSelectorViewTest,
histogram_tester_.ExpectTotalCount(kAudioDevicesCountHistogramName, 1); histogram_tester_.ExpectTotalCount(kAudioDevicesCountHistogramName, 1);
histogram_tester_.ExpectBucketCount(kAudioDevicesCountHistogramName, 3, 1); histogram_tester_.ExpectBucketCount(kAudioDevicesCountHistogramName, 3, 1);
auto* provider = delegate.GetProvider();
provider->AddDevice("Monitor", "4"); provider->AddDevice("Monitor", "4");
provider->RunUICallback(); provider->RunUICallback();
......
...@@ -36,38 +36,9 @@ namespace media_router { ...@@ -36,38 +36,9 @@ namespace media_router {
namespace { namespace {
gfx::ImageSkia CreateSinkIcon(SinkIconType icon_type, bool enabled = true) { gfx::ImageSkia CreateSinkIcon(SinkIconType icon_type, bool enabled = true) {
const gfx::VectorIcon* vector_icon;
switch (icon_type) {
case SinkIconType::CAST_AUDIO_GROUP:
vector_icon = &kSpeakerGroupIcon;
break;
case SinkIconType::CAST_AUDIO:
vector_icon = &kSpeakerIcon;
break;
case SinkIconType::EDUCATION:
vector_icon = &kCastForEducationIcon;
break;
case SinkIconType::WIRED_DISPLAY:
vector_icon = &kInputIcon;
break;
// Use proprietary icons only in Chrome builds. The default TV icon is used
// instead for these sink types in Chromium builds.
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
case SinkIconType::MEETING:
vector_icon = &vector_icons::kMeetIcon;
break;
case SinkIconType::HANGOUT:
vector_icon = &vector_icons::kHangoutIcon;
break;
#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
case SinkIconType::CAST:
case SinkIconType::GENERIC:
default:
vector_icon = &kTvIcon;
break;
}
SkColor icon_color = enabled ? gfx::kChromeIconGrey : gfx::kGoogleGrey500; SkColor icon_color = enabled ? gfx::kChromeIconGrey : gfx::kGoogleGrey500;
return gfx::CreateVectorIcon(*vector_icon, kPrimaryIconSize, icon_color); return gfx::CreateVectorIcon(*CastDialogSinkButton::GetVectorIcon(icon_type),
kPrimaryIconSize, icon_color);
} }
gfx::ImageSkia CreateDisabledSinkIcon(SinkIconType icon_type) { gfx::ImageSkia CreateDisabledSinkIcon(SinkIconType icon_type) {
...@@ -82,11 +53,7 @@ std::unique_ptr<views::ImageView> CreatePrimaryIconView( ...@@ -82,11 +53,7 @@ std::unique_ptr<views::ImageView> CreatePrimaryIconView(
return icon_view; return icon_view;
} }
std::unique_ptr<views::View> CreatePrimaryIconForSink( std::unique_ptr<views::View> CreatePrimaryIconForSink(const UIMediaSink& sink) {
CastDialogSinkButton* sink_button,
views::ButtonListener* button_listener,
const UIMediaSink& sink,
int button_tag) {
// The stop button has the highest priority, and the issue icon comes second. // The stop button has the highest priority, and the issue icon comes second.
if (sink.state == UIMediaSinkState::CONNECTED) { if (sink.state == UIMediaSinkState::CONNECTED) {
return CreatePrimaryIconView(gfx::CreateVectorIcon( return CreatePrimaryIconView(gfx::CreateVectorIcon(
...@@ -128,12 +95,11 @@ CastDialogSinkButton::CastDialogSinkButton( ...@@ -128,12 +95,11 @@ CastDialogSinkButton::CastDialogSinkButton(
views::ButtonListener* button_listener, views::ButtonListener* button_listener,
const UIMediaSink& sink, const UIMediaSink& sink,
int button_tag) int button_tag)
: HoverButton( : HoverButton(button_listener,
button_listener, CreatePrimaryIconForSink(sink),
CreatePrimaryIconForSink(this, button_listener, sink, button_tag), sink.friendly_name,
sink.friendly_name, GetStatusTextForSink(sink),
GetStatusTextForSink(sink), /** secondary_icon_view */ nullptr),
/** secondary_icon_view */ nullptr),
sink_(sink) { sink_(sink) {
set_tag(button_tag); set_tag(button_tag);
SetEnabled(sink.state == UIMediaSinkState::AVAILABLE || SetEnabled(sink.state == UIMediaSinkState::AVAILABLE ||
...@@ -232,4 +198,40 @@ void CastDialogSinkButton::OnBlur() { ...@@ -232,4 +198,40 @@ void CastDialogSinkButton::OnBlur() {
RestoreStatusText(); RestoreStatusText();
} }
// static
const gfx::VectorIcon* CastDialogSinkButton::GetVectorIcon(
SinkIconType icon_type) {
const gfx::VectorIcon* vector_icon;
switch (icon_type) {
case SinkIconType::CAST_AUDIO_GROUP:
vector_icon = &kSpeakerGroupIcon;
break;
case SinkIconType::CAST_AUDIO:
vector_icon = &kSpeakerIcon;
break;
case SinkIconType::EDUCATION:
vector_icon = &kCastForEducationIcon;
break;
case SinkIconType::WIRED_DISPLAY:
vector_icon = &kInputIcon;
break;
// Use proprietary icons only in Chrome builds. The default TV icon is used
// instead for these sink types in Chromium builds.
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
case SinkIconType::MEETING:
vector_icon = &vector_icons::kMeetIcon;
break;
case SinkIconType::HANGOUT:
vector_icon = &vector_icons::kHangoutIcon;
break;
#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
case SinkIconType::CAST:
case SinkIconType::GENERIC:
default:
vector_icon = &kTvIcon;
break;
}
return vector_icon;
}
} // namespace media_router } // namespace media_router
...@@ -36,6 +36,8 @@ class CastDialogSinkButton : public HoverButton { ...@@ -36,6 +36,8 @@ class CastDialogSinkButton : public HoverButton {
const UIMediaSink& sink() const { return sink_; } const UIMediaSink& sink() const { return sink_; }
static const gfx::VectorIcon* GetVectorIcon(SinkIconType icon_type);
private: private:
friend class MediaRouterUiForTest; friend class MediaRouterUiForTest;
FRIEND_TEST_ALL_PREFIXES(CastDialogSinkButtonTest, OverrideStatusText); FRIEND_TEST_ALL_PREFIXES(CastDialogSinkButtonTest, OverrideStatusText);
......
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