Commit 7ffd284f authored by David Black's avatar David Black Committed by Commit Bot

Download icons for suggestion chips.

The basic strategy is as follows:
- Assistant UI creates suggestion chip w/ icon placeholder.
- Assistant UI requests icon download from AssistantController.
- AssistantController requests download from AssistantImageDownloader.
- AssistantImageDownloader downloads image using BitmapFetcher.
- On success, AssistantImageDownloader runs callback to Assistant UI.
- Assistant UI updates icon for suggestion chip view.

This is a similar flow to what is currently done for rendering
Assistant cards. The BitmapFetcher logic is modeled on what is
currently done by AccountAvatarFetcher.

See bug for demo.

Bug: b:79599200
Change-Id: I9ee09a2458ce955a5e4926fcef43864a05e4454e
Reviewed-on: https://chromium-review.googlesource.com/1066179Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: David Black <dmblack@google.com>
Cr-Commit-Position: refs/heads/master@{#561724}
parent 29b93df1
......@@ -77,6 +77,11 @@ void AssistantController::SetAssistantCardRenderer(
assistant_card_renderer_ = std::move(assistant_card_renderer);
}
void AssistantController::SetAssistantImageDownloader(
mojom::AssistantImageDownloaderPtr assistant_image_downloader) {
assistant_image_downloader_ = std::move(assistant_image_downloader);
}
void AssistantController::RequestScreenshot(
const gfx::Rect& rect,
RequestScreenshotCallback callback) {
......@@ -110,7 +115,6 @@ void AssistantController::RenderCard(
}
AccountId account_id = user_session->user_info->account_id;
assistant_card_renderer_->Render(account_id, id_token, std::move(params),
std::move(callback));
}
......@@ -126,6 +130,23 @@ void AssistantController::ReleaseCards(
assistant_card_renderer_->ReleaseAll(id_tokens);
}
void AssistantController::DownloadImage(
const GURL& url,
mojom::AssistantImageDownloader::DownloadCallback callback) {
DCHECK(assistant_image_downloader_);
const mojom::UserSession* user_session =
Shell::Get()->session_controller()->GetUserSession(0);
if (!user_session) {
LOG(WARNING) << "Unable to retrieve active user session.";
return;
}
AccountId account_id = user_session->user_info->account_id;
assistant_image_downloader_->Download(account_id, url, std::move(callback));
}
void AssistantController::AddInteractionModelObserver(
AssistantInteractionModelObserver* observer) {
assistant_interaction_model_.AddObserver(observer);
......
......@@ -14,6 +14,7 @@
#include "ash/highlighter/highlighter_controller.h"
#include "ash/public/interfaces/assistant_card_renderer.mojom.h"
#include "ash/public/interfaces/assistant_controller.mojom.h"
#include "ash/public/interfaces/assistant_image_downloader.mojom.h"
#include "base/macros.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
......@@ -73,6 +74,13 @@ class AssistantController
// Releases resources for any card uniquely identified in |id_token_list|.
void ReleaseCards(const std::vector<base::UnguessableToken>& id_tokens);
// Downloads the image found at the specified |url|. On completion, the
// supplied |callback| will be run with the downloaded image. If the download
// attempt is unsuccessful, a NULL image is returned.
void DownloadImage(
const GURL& url,
mojom::AssistantImageDownloader::DownloadCallback callback);
// Invoke to modify the Assistant interaction state.
void StartInteraction();
void StopInteraction();
......@@ -119,6 +127,8 @@ class AssistantController
chromeos::assistant::mojom::AssistantPtr assistant) override;
void SetAssistantCardRenderer(
mojom::AssistantCardRendererPtr assistant_card_renderer) override;
void SetAssistantImageDownloader(
mojom::AssistantImageDownloaderPtr assistant_image_downloader) override;
void RequestScreenshot(const gfx::Rect& rect,
RequestScreenshotCallback callback) override;
void OnCardPressed(const GURL& url) override;
......@@ -131,6 +141,7 @@ class AssistantController
chromeos::assistant::mojom::AssistantPtr assistant_;
mojom::AssistantCardRendererPtr assistant_card_renderer_;
mojom::AssistantImageDownloaderPtr assistant_image_downloader_;
std::unique_ptr<AssistantBubble> assistant_bubble_;
......
......@@ -7,10 +7,7 @@
#include <memory>
#include "ash/assistant/assistant_controller.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
#include "ui/views/layout/box_layout.h"
......@@ -47,7 +44,8 @@ class InvisibleScrollBar : public views::OverlayScrollBar {
SuggestionContainerView::SuggestionContainerView(
AssistantController* assistant_controller)
: assistant_controller_(assistant_controller),
contents_view_(new views::View()) {
contents_view_(new views::View()),
download_request_weak_factory_(this) {
InitLayout();
// The Assistant controller indirectly owns the view hierarchy to which
......@@ -87,23 +85,38 @@ void SuggestionContainerView::InitLayout() {
void SuggestionContainerView::OnSuggestionsAdded(
const std::map<int, AssistantSuggestion*>& suggestions) {
for (const std::pair<int, AssistantSuggestion*>& suggestion : suggestions) {
// We will use the same identifier by which the Assistant interaction model
// uniquely identifies a suggestion to uniquely identify its corresponding
// suggestion chip view.
const int id = suggestion.first;
app_list::SuggestionChipView::Params params;
params.text = base::UTF8ToUTF16(suggestion.second->text);
// TODO(dmblack): Here we are using a placeholder image for the suggestion
// chip icon but we need to handle the actual icon URL.
if (!suggestion.second->icon_url.is_empty())
params.icon = gfx::CreateVectorIcon(
kCircleIcon, app_list::SuggestionChipView::kIconSizeDip,
gfx::kGoogleGrey300);
views::View* suggestion_chip_view =
if (!suggestion.second->icon_url.is_empty()) {
// Initiate a request to download the image for the suggestion chip icon.
// Note that the request is identified by the suggestion id.
assistant_controller_->DownloadImage(
suggestion.second->icon_url,
base::BindOnce(
&SuggestionContainerView::OnSuggestionChipIconDownloaded,
download_request_weak_factory_.GetWeakPtr(), id));
// To reserve layout space until the actual icon can be downloaded, we
// supply an empty placeholder image to the suggestion chip view.
params.icon = gfx::ImageSkia();
}
app_list::SuggestionChipView* suggestion_chip_view =
new app_list::SuggestionChipView(params, /*listener=*/this);
// When adding a SuggestionChipView, we give the view the same id by which
// the interaction model identifies the corresponding suggestion. This
// allows us to look up the suggestion for the view during event handling.
suggestion_chip_view->set_id(suggestion.first);
// Given a suggestion chip view, we need to be able to look up the id of
// the underlying suggestion. This is used for handling press events.
suggestion_chip_view->set_id(id);
// Given an id, we also want to be able to look up the corresponding
// suggestion chip view. This is used for handling icon download events.
suggestion_chip_views_[id] = suggestion_chip_view;
contents_view_->AddChildView(suggestion_chip_view);
}
......@@ -112,11 +125,25 @@ void SuggestionContainerView::OnSuggestionsAdded(
}
void SuggestionContainerView::OnSuggestionsCleared() {
// Abort any download requests in progress.
download_request_weak_factory_.InvalidateWeakPtrs();
SetVisible(false);
// When modifying the view hierarchy, make sure we keep our view cache synced.
contents_view_->RemoveAllChildViews(/*delete_children=*/true);
suggestion_chip_views_.clear();
UpdateContentsBounds();
}
void SuggestionContainerView::OnSuggestionChipIconDownloaded(
int id,
const gfx::ImageSkia& icon) {
if (!icon.isNull())
suggestion_chip_views_[id]->SetIcon(icon);
}
void SuggestionContainerView::OnSuggestionChipPressed(
app_list::SuggestionChipView* suggestion_chip_view) {
assistant_controller_->OnSuggestionChipPressed(suggestion_chip_view->id());
......
......@@ -5,6 +5,8 @@
#ifndef ASH_ASSISTANT_UI_SUGGESTION_CONTAINER_VIEW_H_
#define ASH_ASSISTANT_UI_SUGGESTION_CONTAINER_VIEW_H_
#include <map>
#include "ash/assistant/model/assistant_interaction_model_observer.h"
#include "base/macros.h"
#include "ui/app_list/views/suggestion_chip_view.h"
......@@ -40,9 +42,20 @@ class SuggestionContainerView : public views::ScrollView,
void InitLayout();
void UpdateContentsBounds();
// Invoked on suggestion chip icon downloaded event.
void OnSuggestionChipIconDownloaded(int id, const gfx::ImageSkia& icon);
AssistantController* const assistant_controller_; // Owned by Shell.
views::View* contents_view_; // Owned by view hierarchy.
// Cache of suggestion chip views owned by the view hierarchy. The key for the
// map is the unique identifier by which the Assistant interaction model
// identifies the view's underlying suggestion.
std::map<int, app_list::SuggestionChipView*> suggestion_chip_views_;
// Weak pointer factory used for image downloading requests.
base::WeakPtrFactory<SuggestionContainerView> download_request_weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SuggestionContainerView);
};
......
......@@ -20,6 +20,7 @@ mojom("interfaces_internal") {
"ash_message_center_controller.mojom",
"assistant_card_renderer.mojom",
"assistant_controller.mojom",
"assistant_image_downloader.mojom",
"cast_config.mojom",
"constants.mojom",
"cros_display_config.mojom",
......
......@@ -5,12 +5,12 @@
module ash.mojom;
import "ash/public/interfaces/assistant_card_renderer.mojom";
import "ash/public/interfaces/assistant_image_downloader.mojom";
import "chromeos/services/assistant/public/mojom/assistant.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
import "url/mojom/url.mojom";
// Interface for AssistantManagerService to communicate with
// AssistantController.
// Interface to AssistantController which is owned by Shell in Ash.
interface AssistantController {
// Provides a reference to the underlying |assistant| service.
SetAssistant(chromeos.assistant.mojom.Assistant assistant);
......@@ -19,6 +19,11 @@ interface AssistantController {
// AssistantClient.
SetAssistantCardRenderer(AssistantCardRenderer assistant_card_renderer);
// Provides an interface to the |assistant_image_downloader| owned by
// AssistantClient.
SetAssistantImageDownloader(
AssistantImageDownloader assistant_image_downloader);
// Requests screenshot of specified |rect| region and returns the screenshot
// encoded in JPEG format. If |rect| is empty, it returns fullscreen
// screenshot.
......
// 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.
module ash.mojom;
import "components/account_id/interfaces/account_id.mojom";
import "ui/gfx/image/mojo/image.mojom";
import "url/mojom/url.mojom";
// Interface for a class which is responsible for downloading images on behalf
// of the Assistant UI in ash.
interface AssistantImageDownloader {
// Downloads the image found at |url| for the profile associated with
// |account_id|. On completion, the supplied callback is run with the
// downloaded |image|. In the event that the download attempt fails, a NULL
// image will be returned.
Download(signin.mojom.AccountId account_id, url.mojom.Url url)
=> (gfx.mojom.ImageSkia image);
};
......@@ -12,7 +12,6 @@ aggregate_vector_icons("ash_vector_icons") {
"assistant.icon",
"captive_portal.icon",
"check_circle.icon",
"circle.icon",
"dictation_off.icon",
"dictation_on.icon",
"ime_menu_emoticon.icon",
......
// 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.
CANVAS_DIMENSIONS, 24,
CIRCLE, 12, 12, 12
......@@ -299,6 +299,18 @@ void ProfileHelper::ClearSigninProfile(const base::Closure& on_clear_callback) {
->CloseCurrentSigninSession(on_clear_profile_stage_finished_);
}
Profile* ProfileHelper::GetProfileByAccountId(const AccountId& account_id) {
const user_manager::User* user =
user_manager::UserManager::Get()->FindUser(account_id);
if (!user) {
LOG(WARNING) << "Unable to retrieve user for account_id.";
return nullptr;
}
return GetProfileByUser(user);
}
Profile* ProfileHelper::GetProfileByUser(const user_manager::User* user) {
// This map is non-empty only in tests.
if (!user_to_profile_for_testing_.empty()) {
......
......@@ -148,6 +148,10 @@ class ProfileHelper
// Callback can be empty. Not thread-safe.
void ClearSigninProfile(const base::Closure& on_clear_callback);
// Returns profile of the user associated with |account_id| if it is created
// and fully initialized. Otherwise, returns NULL.
Profile* GetProfileByAccountId(const AccountId& account_id);
// Returns profile of the |user| if it is created and fully initialized.
// Otherwise, returns NULL.
Profile* GetProfileByUser(const user_manager::User* user);
......
......@@ -3715,6 +3715,8 @@ split_static_library("ui") {
"ash/assistant/assistant_context.h",
"ash/assistant/assistant_context_util.cc",
"ash/assistant/assistant_context_util.h",
"ash/assistant/assistant_image_downloader.cc",
"ash/assistant/assistant_image_downloader.h",
"ash/assistant/platform_audio_input_host.cc",
"ash/assistant/platform_audio_input_host.h",
]
......
......@@ -11,7 +11,6 @@
#include "ash/public/interfaces/constants.mojom.h"
#include "base/optional.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
......@@ -37,18 +36,11 @@ class AssistantCard : public content::WebContentsDelegate,
ash::mojom::AssistantCardParamsPtr params,
ash::mojom::AssistantCardRenderer::RenderCallback callback)
: assistant_card_renderer_(assistant_card_renderer) {
const user_manager::User* user =
user_manager::UserManager::Get()->FindUser(account_id);
if (!user) {
LOG(WARNING) << "Unable to retrieve user for account_id.";
return;
}
Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(user);
Profile* profile =
chromeos::ProfileHelper::Get()->GetProfileByAccountId(account_id);
if (!profile) {
LOG(WARNING) << "Unable to retrieve profile for user.";
LOG(WARNING) << "Unable to retrieve profile for account_id.";
return;
}
......
......@@ -9,6 +9,7 @@
#include "ash/public/interfaces/voice_interaction_controller.mojom.h"
#include "chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h"
#include "chrome/browser/ui/ash/assistant/assistant_card_renderer.h"
#include "chrome/browser/ui/ash/assistant/assistant_image_downloader.h"
#include "chromeos/services/assistant/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
......@@ -40,6 +41,7 @@ AssistantClient::~AssistantClient() {
void AssistantClient::MaybeInit(service_manager::Connector* connector) {
if (initialized_)
return;
initialized_ = true;
connector->BindInterface(chromeos::assistant::mojom::kServiceName,
&assistant_connection_);
......@@ -55,7 +57,9 @@ void AssistantClient::MaybeInit(service_manager::Connector* connector) {
assistant_connection_->Init(std::move(client_ptr), std::move(context_ptr),
std::move(audio_input_ptr));
assistant_card_renderer_.reset(new AssistantCardRenderer(connector));
assistant_card_renderer_ = std::make_unique<AssistantCardRenderer>(connector);
assistant_image_downloader_ =
std::make_unique<AssistantImageDownloader>(connector);
}
void AssistantClient::OnAssistantStatusChanged(bool running) {
......
......@@ -18,6 +18,7 @@ class Connector;
} // namespace service_manager
class AssistantCardRenderer;
class AssistantImageDownloader;
// Class to handle all assistant in-browser-process functionalities.
class AssistantClient : chromeos::assistant::mojom::Client {
......@@ -45,6 +46,7 @@ class AssistantClient : chromeos::assistant::mojom::Client {
AssistantContext context_;
std::unique_ptr<AssistantCardRenderer> assistant_card_renderer_;
std::unique_ptr<AssistantImageDownloader> assistant_image_downloader_;
bool initialized_ = false;
......
// 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 "chrome/browser/ui/ash/assistant/assistant_image_downloader.h"
#include "ash/public/interfaces/assistant_controller.mojom.h"
#include "ash/public/interfaces/constants.mojom.h"
#include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_delegate.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/load_flags.h"
#include "services/service_manager/public/cpp/connector.h"
namespace {
constexpr net::NetworkTrafficAnnotationTag kNetworkTrafficAnnotationTag =
net::DefineNetworkTrafficAnnotation("assistant_image_downloader", R"(
"semantics: {
sender: "Google Assistant"
description:
"The Google Assistant requires dynamic loading of images to "
"provide a media rich user experience. Images are downloaded on "
"an as needed basis."
trigger:
"Generally triggered in direct response to a user issued query. "
"A single query may necessitate the downloading of multiple "
"images."
destination: GOOGLE_OWNED_SERVICE
}
"policy": {
cookies_allowed: NO
setting:
"The Google Assistant can be enabled/disabled in Chrome Settings "
"and is subject to eligibility requirements."
})");
// DownloadTask ----------------------------------------------------------------
class DownloadTask : public BitmapFetcherDelegate {
public:
DownloadTask(Profile* profile,
const GURL& url,
ash::mojom::AssistantImageDownloader::DownloadCallback callback)
: callback_(std::move(callback)) {
StartTask(profile, url);
}
~DownloadTask() override = default;
// BitmapFetcherDelegate:
void OnFetchComplete(const GURL& url, const SkBitmap* bitmap) override {
std::move(callback_).Run(bitmap
? gfx::ImageSkia::CreateFrom1xBitmap(*bitmap)
: gfx::ImageSkia());
delete this;
}
private:
void StartTask(Profile* profile, const GURL& url) {
bitmap_fetcher_ = std::make_unique<BitmapFetcher>(
url, this, kNetworkTrafficAnnotationTag);
bitmap_fetcher_->Init(
/*referrer=*/std::string(), net::URLRequest::NEVER_CLEAR_REFERRER,
net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DO_NOT_SEND_AUTH_DATA | net::LOAD_MAYBE_USER_GESTURE);
bitmap_fetcher_->Start(
content::BrowserContext::GetDefaultStoragePartition(profile)
->GetURLLoaderFactoryForBrowserProcess()
.get());
}
ash::mojom::AssistantImageDownloader::DownloadCallback callback_;
std::unique_ptr<BitmapFetcher> bitmap_fetcher_;
DISALLOW_COPY_AND_ASSIGN(DownloadTask);
};
} // namespace
// AssistantImageDownloader ----------------------------------------------------
AssistantImageDownloader::AssistantImageDownloader(
service_manager::Connector* connector)
: binding_(this) {
// Bind to the Assistant controller in ash.
ash::mojom::AssistantControllerPtr assistant_controller;
connector->BindInterface(ash::mojom::kServiceName, &assistant_controller);
ash::mojom::AssistantImageDownloaderPtr ptr;
binding_.Bind(mojo::MakeRequest(&ptr));
assistant_controller->SetAssistantImageDownloader(std::move(ptr));
}
AssistantImageDownloader::~AssistantImageDownloader() = default;
void AssistantImageDownloader::Download(
const AccountId& account_id,
const GURL& url,
ash::mojom::AssistantImageDownloader::DownloadCallback callback) {
Profile* profile =
chromeos::ProfileHelper::Get()->GetProfileByAccountId(account_id);
if (!profile) {
LOG(WARNING) << "Unable to retrieve profile for account_id.";
std::move(callback).Run(gfx::ImageSkia());
return;
}
// The download task will delete itself upon task completion.
new DownloadTask(profile, url, std::move(callback));
}
// 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.
#ifndef CHROME_BROWSER_UI_ASH_ASSISTANT_ASSISTANT_IMAGE_DOWNLOADER_H_
#define CHROME_BROWSER_UI_ASH_ASSISTANT_ASSISTANT_IMAGE_DOWNLOADER_H_
#include "ash/public/interfaces/assistant_image_downloader.mojom.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
class AccountId;
namespace service_manager {
class Connector;
} // namespace service_manager
// AssistantImageDownloader is the class responsible for downloading images on
// behalf of Assistant UI in ash.
class AssistantImageDownloader : public ash::mojom::AssistantImageDownloader {
public:
explicit AssistantImageDownloader(service_manager::Connector* connector);
~AssistantImageDownloader() override;
// ash::mojom::AssistantImageDownloader:
void Download(
const AccountId& account_id,
const GURL& url,
ash::mojom::AssistantImageDownloader::DownloadCallback callback) override;
private:
mojo::Binding<ash::mojom::AssistantImageDownloader> binding_;
DISALLOW_COPY_AND_ASSIGN(AssistantImageDownloader);
};
#endif // CHROME_BROWSER_UI_ASH_ASSISTANT_ASSISTANT_IMAGE_DOWNLOADER_H_
......@@ -54,16 +54,26 @@ int SuggestionChipView::GetHeightForWidth(int width) const {
return kPreferredHeightDip;
}
void SuggestionChipView::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_->visible() ? kIconMarginDip : kPaddingDip;
layout_manager_->set_inside_border_insets(
gfx::Insets(0, padding_left_dip, 0, kPaddingDip));
}
PreferredSizeChanged();
}
void SuggestionChipView::InitLayout(const Params& params) {
// Layout padding differs depending on icon visibility.
const int padding_left_dip = params.icon ? kIconMarginDip : kPaddingDip;
views::BoxLayout* layout_manager =
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal,
gfx::Insets(0, padding_left_dip, 0, kPaddingDip), kIconMarginDip));
layout_manager_ = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal,
gfx::Insets(0, padding_left_dip, 0, kPaddingDip), kIconMarginDip));
layout_manager->set_cross_axis_alignment(
layout_manager_->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER);
// Icon.
......@@ -119,6 +129,11 @@ bool SuggestionChipView::OnMousePressed(const ui::MouseEvent& event) {
return true;
}
void SuggestionChipView::SetIcon(const gfx::ImageSkia& icon) {
icon_view_->SetImage(icon);
icon_view_->SetVisible(true);
}
const base::string16& SuggestionChipView::GetText() const {
return text_view_->text();
}
......
......@@ -11,6 +11,7 @@
#include "ui/views/view.h"
namespace views {
class BoxLayout;
class ImageView;
class Label;
} // namespace views
......@@ -32,7 +33,7 @@ class APP_LIST_EXPORT SuggestionChipListener {
// View representing a suggestion chip.
class APP_LIST_EXPORT SuggestionChipView : public views::View {
public:
static constexpr int kIconSizeDip = 20;
static constexpr int kIconSizeDip = 16;
// Initialization parameters.
struct Params {
......@@ -51,11 +52,14 @@ class APP_LIST_EXPORT SuggestionChipView : public views::View {
// views::View:
gfx::Size CalculatePreferredSize() const override;
void ChildVisibilityChanged(views::View* child) override;
int GetHeightForWidth(int width) const override;
void OnGestureEvent(ui::GestureEvent* event) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
void OnPaintBackground(gfx::Canvas* canvas) override;
void SetIcon(const gfx::ImageSkia& icon);
const base::string16& GetText() const;
private:
......@@ -65,6 +69,8 @@ class APP_LIST_EXPORT SuggestionChipView : public views::View {
views::Label* text_view_; // Owned by view hierarchy.
SuggestionChipListener* listener_;
views::BoxLayout* layout_manager_; // Owned by view hierarchy.
DISALLOW_COPY_AND_ASSIGN(SuggestionChipView);
};
......
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