blob: 7af8468c95a6cafe145d26cba250626eaf981053 [file] [log] [blame]
// Copyright 2016 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/desktop_capture/desktop_media_source_view.h"
#include "chrome/browser/media/webrtc/desktop_media_list.h"
#include "chrome/browser/ui/views/desktop_capture/desktop_media_list_view.h"
#include "chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/gfx/canvas.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/border.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
using content::DesktopMediaID;
DesktopMediaSourceViewStyle::DesktopMediaSourceViewStyle(
const DesktopMediaSourceViewStyle& style) = default;
DesktopMediaSourceViewStyle::DesktopMediaSourceViewStyle(
int columns,
const gfx::Size& item_size,
const gfx::Rect& icon_rect,
const gfx::Rect& label_rect,
gfx::HorizontalAlignment text_alignment,
const gfx::Rect& image_rect,
int selection_border_thickness,
int focus_rectangle_inset)
: columns(columns),
item_size(item_size),
icon_rect(icon_rect),
label_rect(label_rect),
text_alignment(text_alignment),
image_rect(image_rect),
selection_border_thickness(selection_border_thickness),
focus_rectangle_inset(focus_rectangle_inset) {}
DesktopMediaSourceView::DesktopMediaSourceView(
DesktopMediaListView* parent,
DesktopMediaID source_id,
DesktopMediaSourceViewStyle style)
: parent_(parent),
source_id_(source_id),
style_(style),
icon_view_(new views::ImageView()),
image_view_(new views::ImageView()),
label_(new views::Label()),
selected_(false) {
AddChildView(icon_view_);
AddChildView(image_view_);
AddChildView(label_);
icon_view_->set_can_process_events_within_subtree(false);
image_view_->set_can_process_events_within_subtree(false);
SetFocusBehavior(FocusBehavior::ALWAYS);
SetStyle(style_);
}
DesktopMediaSourceView::~DesktopMediaSourceView() {}
const char DesktopMediaSourceView::kDesktopMediaSourceViewClassName[] =
"DesktopMediaPicker_DesktopMediaSourceView";
void DesktopMediaSourceView::SetName(const base::string16& name) {
label_->SetText(name);
}
void DesktopMediaSourceView::SetThumbnail(const gfx::ImageSkia& thumbnail) {
image_view_->SetImage(thumbnail);
}
void DesktopMediaSourceView::SetIcon(const gfx::ImageSkia& icon) {
icon_view_->SetImage(icon);
}
void DesktopMediaSourceView::SetSelected(bool selected) {
if (selected == selected_)
return;
selected_ = selected;
if (selected) {
// Unselect all other sources.
Views neighbours;
parent()->GetViewsInGroup(GetGroup(), &neighbours);
for (auto i(neighbours.begin()); i != neighbours.end(); ++i) {
if (*i != this) {
DCHECK_EQ((*i)->GetClassName(),
DesktopMediaSourceView::kDesktopMediaSourceViewClassName);
DesktopMediaSourceView* source_view =
static_cast<DesktopMediaSourceView*>(*i);
source_view->SetSelected(false);
}
}
const SkColor border_color = GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_FocusedBorderColor);
image_view_->SetBorder(views::CreateSolidBorder(
style_.selection_border_thickness, border_color));
label_->SetFontList(label_->font_list().Derive(0, gfx::Font::NORMAL,
gfx::Font::Weight::BOLD));
parent_->OnSelectionChanged();
} else {
image_view_->SetBorder(views::NullBorder());
label_->SetFontList(label_->font_list().Derive(0, gfx::Font::NORMAL,
gfx::Font::Weight::NORMAL));
}
SchedulePaint();
}
const char* DesktopMediaSourceView::GetClassName() const {
return DesktopMediaSourceView::kDesktopMediaSourceViewClassName;
}
void DesktopMediaSourceView::SetStyle(DesktopMediaSourceViewStyle style) {
style_ = style;
image_view_->SetBoundsRect(style_.image_rect);
if (selected_) {
const SkColor border_color = GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_FocusedBorderColor);
image_view_->SetBorder(views::CreateSolidBorder(
style_.selection_border_thickness, border_color));
}
icon_view_->SetBoundsRect(style_.icon_rect);
icon_view_->SetImageSize(style_.icon_rect.size());
label_->SetBoundsRect(style_.label_rect);
label_->SetHorizontalAlignment(style_.text_alignment);
}
views::View* DesktopMediaSourceView::GetSelectedViewForGroup(int group) {
Views neighbours;
parent()->GetViewsInGroup(group, &neighbours);
if (neighbours.empty())
return nullptr;
for (auto i(neighbours.begin()); i != neighbours.end(); ++i) {
DCHECK_EQ((*i)->GetClassName(),
DesktopMediaSourceView::kDesktopMediaSourceViewClassName);
DesktopMediaSourceView* source_view =
static_cast<DesktopMediaSourceView*>(*i);
if (source_view->selected_)
return source_view;
}
return nullptr;
}
bool DesktopMediaSourceView::IsGroupFocusTraversable() const {
return false;
}
void DesktopMediaSourceView::OnPaint(gfx::Canvas* canvas) {
View::OnPaint(canvas);
if (HasFocus()) {
gfx::Rect bounds(GetLocalBounds());
bounds.Inset(style_.focus_rectangle_inset, style_.focus_rectangle_inset);
canvas->DrawFocusRect(bounds);
}
}
void DesktopMediaSourceView::OnFocus() {
View::OnFocus();
SetSelected(true);
ScrollRectToVisible(gfx::Rect(size()));
// We paint differently when focused.
SchedulePaint();
}
void DesktopMediaSourceView::OnBlur() {
View::OnBlur();
// We paint differently when focused.
SchedulePaint();
}
bool DesktopMediaSourceView::OnMousePressed(const ui::MouseEvent& event) {
if (event.GetClickCount() == 1) {
RequestFocus();
} else if (event.GetClickCount() == 2) {
RequestFocus();
parent_->OnDoubleClick();
}
return true;
}
void DesktopMediaSourceView::OnGestureEvent(ui::GestureEvent* event) {
if (event->type() == ui::ET_GESTURE_TAP &&
event->details().tap_count() == 2) {
RequestFocus();
parent_->OnDoubleClick();
event->SetHandled();
return;
}
// Detect tap gesture using ET_GESTURE_TAP_DOWN so the view also gets focused
// on the long tap (when the tap gesture starts).
if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
RequestFocus();
event->SetHandled();
}
}
void DesktopMediaSourceView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->role = ax::mojom::Role::kButton;
node_data->SetName(label_->text());
}