[go: nahoru, domu]

blob: b6b725d52bad745c82aeb3c5005229679ad29a81 [file] [log] [blame]
// Copyright 2018 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 "ash/app_list/views/search_result_suggestion_chip_view.h"
#include <algorithm>
#include <utility>
#include "ash/app_list/app_list_metrics.h"
#include "ash/app_list/app_list_view_delegate.h"
#include "ash/app_list/model/search/search_result.h"
#include "ash/public/cpp/app_list/app_list_color_provider.h"
#include "ash/public/cpp/app_list/app_list_config.h"
#include "ash/public/cpp/app_list/app_list_types.h"
#include "ash/public/cpp/app_list/internal_app_id_constants.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
#include "ui/views/animation/ink_drop_impl.h"
#include "ui/views/controls/highlight_path_generator.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
namespace ash {
namespace {
constexpr int kMaxTextWidth = 192;
constexpr int kBlurRadius = 5;
constexpr int kIconMarginDip = 8;
constexpr int kPaddingDip = 16;
constexpr int kPreferredHeightDip = 32;
// Records an app being launched.
void LogAppLaunch(int index_in_container) {
DCHECK_GE(index_in_container, 0);
base::UmaHistogramSparse("Apps.AppListSuggestedChipLaunched",
index_in_container);
base::RecordAction(base::UserMetricsAction("AppList_OpenSuggestedApp"));
}
} // namespace
SearchResultSuggestionChipView::SearchResultSuggestionChipView(
AppListViewDelegate* view_delegate)
: view_delegate_(view_delegate) {
SetFocusBehavior(FocusBehavior::ALWAYS);
SetCallback(
base::BindRepeating(&SearchResultSuggestionChipView::OnButtonPressed,
base::Unretained(this)));
SetInstallFocusRingOnFocus(true);
focus_ring()->SetColor(AppListColorProvider::Get()->GetFocusRingColor());
SetInkDropMode(InkDropMode::ON);
views::InstallPillHighlightPathGenerator(this);
InitLayout();
}
SearchResultSuggestionChipView::~SearchResultSuggestionChipView() = default;
void SearchResultSuggestionChipView::SetBackgroundBlurEnabled(bool enabled) {
// Background blur is enabled if and only if layer exists.
if (!!layer() == enabled)
return;
if (!enabled) {
DestroyLayer();
return;
}
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
layer()->SetBackgroundBlur(kBlurRadius);
layer()->SetName("launcher/SearchResultSuggestionChip");
SetRoundedCornersForLayer(kPreferredHeightDip / 2);
}
void SearchResultSuggestionChipView::OnResultChanged() {
SetVisible(!!result());
UpdateSuggestionChipView();
}
void SearchResultSuggestionChipView::OnMetadataChanged() {
UpdateSuggestionChipView();
}
const char* SearchResultSuggestionChipView::GetClassName() const {
return "SearchResultSuggestionChipView";
}
void SearchResultSuggestionChipView::ChildVisibilityChanged(
views::View* child) {
// When icon visibility is modified we need to update layout padding.
if (child == icon_view_) {
const int padding_left_dip =
icon_view_->GetVisible() ? kIconMarginDip : kPaddingDip;
layout_manager_->set_inside_border_insets(
gfx::Insets(0, padding_left_dip, 0, kPaddingDip));
}
PreferredSizeChanged();
}
void SearchResultSuggestionChipView::OnPaintBackground(gfx::Canvas* canvas) {
cc::PaintFlags flags;
flags.setAntiAlias(true);
gfx::Rect bounds = GetContentsBounds();
// Background.
flags.setColor(
AppListColorProvider::Get()->GetSuggestionChipBackgroundColor());
canvas->DrawRoundRect(bounds, height() / 2, flags);
// Focus Ring should only be visible when keyboard traversal is occurring.
if (view_delegate_->KeyboardTraversalEngaged())
focus_ring()->SetColor(AppListColorProvider::Get()->GetFocusRingColor());
else
focus_ring()->SetColor(
SkColorSetA(AppListColorProvider::Get()->GetFocusRingColor(), 0));
}
void SearchResultSuggestionChipView::OnFocus() {
SchedulePaint();
NotifyAccessibilityEvent(ax::mojom::Event::kFocus, true);
}
void SearchResultSuggestionChipView::OnBlur() {
SchedulePaint();
}
bool SearchResultSuggestionChipView::OnKeyPressed(const ui::KeyEvent& event) {
if (event.key_code() == ui::VKEY_SPACE)
return false;
return Button::OnKeyPressed(event);
}
void SearchResultSuggestionChipView::OnThemeChanged() {
views::View::OnThemeChanged();
text_view_->SetEnabledColor(
AppListColorProvider::Get()->GetSuggestionChipTextColor());
SchedulePaint();
}
std::unique_ptr<views::InkDrop>
SearchResultSuggestionChipView::CreateInkDrop() {
std::unique_ptr<views::InkDropImpl> ink_drop =
Button::CreateDefaultInkDropImpl();
ink_drop->SetShowHighlightOnHover(false);
ink_drop->SetShowHighlightOnFocus(false);
ink_drop->SetAutoHighlightMode(views::InkDropImpl::AutoHighlightMode::NONE);
return std::move(ink_drop);
}
std::unique_ptr<views::InkDropRipple>
SearchResultSuggestionChipView::CreateInkDropRipple() const {
const gfx::Point center = GetLocalBounds().CenterPoint();
const int ripple_radius = width() / 2;
gfx::Rect bounds(center.x() - ripple_radius, center.y() - ripple_radius,
2 * ripple_radius, 2 * ripple_radius);
const AppListColorProvider* color_provider = AppListColorProvider::Get();
const SkColor bg_color = color_provider->GetSearchBoxBackgroundColor();
return std::make_unique<views::FloodFillInkDropRipple>(
size(), GetLocalBounds().InsetsFrom(bounds),
GetInkDropCenterBasedOnLastEvent(),
color_provider->GetRippleAttributesBaseColor(bg_color),
color_provider->GetRippleAttributesInkDropOpacity(bg_color));
}
std::unique_ptr<ui::Layer> SearchResultSuggestionChipView::RecreateLayer() {
std::unique_ptr<ui::Layer> old_layer = views::View::RecreateLayer();
if (layer())
SetRoundedCornersForLayer(kPreferredHeightDip / 2);
return old_layer;
}
void SearchResultSuggestionChipView::SetIcon(const gfx::ImageSkia& icon) {
icon_view_->SetImage(icon);
icon_view_->SetVisible(true);
}
void SearchResultSuggestionChipView::SetText(const std::u16string& text) {
text_view_->SetText(text);
gfx::Size size = text_view_->CalculatePreferredSize();
size.set_width(std::min(kMaxTextWidth, size.width()));
text_view_->SetPreferredSize(size);
}
const std::u16string& SearchResultSuggestionChipView::GetText() const {
return text_view_->GetText();
}
void SearchResultSuggestionChipView::UpdateSuggestionChipView() {
if (!result()) {
SetIcon(gfx::ImageSkia());
SetText(std::u16string());
SetAccessibleName(std::u16string());
return;
}
SetIcon(result()->chip_icon());
SetText(result()->title());
std::u16string accessible_name = result()->title();
if (result()->id() == kInternalAppIdContinueReading) {
accessible_name = l10n_util::GetStringFUTF16(
IDS_APP_LIST_CONTINUE_READING_ACCESSIBILE_NAME, accessible_name);
}
SetAccessibleName(accessible_name);
}
void SearchResultSuggestionChipView::InitLayout() {
layout_manager_ = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal,
gfx::Insets(0, kPaddingDip, 0, kPaddingDip), kIconMarginDip));
layout_manager_->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter);
// Icon.
const int icon_size =
AppListConfig::instance().suggestion_chip_icon_dimension();
icon_view_ = AddChildView(std::make_unique<views::ImageView>());
icon_view_->SetImageSize(gfx::Size(icon_size, icon_size));
icon_view_->SetPreferredSize(gfx::Size(icon_size, icon_size));
icon_view_->SetVisible(false);
// Text.
text_view_ = AddChildView(std::make_unique<views::Label>());
text_view_->SetAutoColorReadabilityEnabled(false);
text_view_->SetSubpixelRenderingEnabled(false);
text_view_->SetFontList(AppListConfig::instance().app_title_font());
SetText(std::u16string());
text_view_->SetEnabledColor(
AppListColorProvider::Get()->GetSuggestionChipTextColor());
}
void SearchResultSuggestionChipView::OnButtonPressed(const ui::Event& event) {
DCHECK(result());
LogAppLaunch(index_in_container());
RecordSearchResultOpenSource(result(), view_delegate_->GetModel(),
view_delegate_->GetSearchModel());
view_delegate_->OpenSearchResult(
result()->id(), event.flags(),
AppListLaunchedFrom::kLaunchedFromSuggestionChip,
AppListLaunchType::kAppSearchResult, index_in_container(),
false /* launch_as_default */);
}
void SearchResultSuggestionChipView::SetRoundedCornersForLayer(
int corner_radius) {
layer()->SetRoundedCornerRadius(
{corner_radius, corner_radius, corner_radius, corner_radius});
layer()->SetIsFastRoundedCorner(true);
}
} // namespace ash