Commit 82f9f266 authored by David Black's avatar David Black Committed by Commit Bot

Make UiElementContainerView scrollable.

Previously, answers were not scrollable. Now they are. To accomplish
this, we've:

- Created an abstract AssistantScrollView class to share logic between
  UiElementContainerView and SuggestionContainerView which both have
  the need to scroll.

- Moved AssistantHeaderView out of UiElementContainerView because it
  should not participate in the scroll.

Known issue: We still have not addressed the WebView event processing
issue, so it is only possible to scroll UiElementContainerView via
mouse/touch events that do not involve the WebView. This will be
addressed in a follow up CL. Temporary workaround: initiate scroll
events from the margins beside the cards, not over the cards themselves.

Known issue: If the user scrolls the content and then issues another
query, we fade out the current answer and show our thinking dots. But if
the content has been scrolled, the thinking dots collide with other views.
To address this, I force scroll the content back to the top and disallow
events while waiting for the next answer to come in. Need UX guidance on
what might be a better approach.

See bug for demo.

Bug: b:110039692
Change-Id: I20dbca681b92981857c4266ef1882642503eb0da
Reviewed-on: https://chromium-review.googlesource.com/1172144
Commit-Queue: David Black <dmblack@google.com>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#582650}
parent 7b8282b8
...@@ -86,6 +86,7 @@ component("ash") { ...@@ -86,6 +86,7 @@ component("ash") {
"assistant/ui/assistant_container_view.h", "assistant/ui/assistant_container_view.h",
"assistant/ui/assistant_main_view.h", "assistant/ui/assistant_main_view.h",
"assistant/ui/assistant_mini_view.h", "assistant/ui/assistant_mini_view.h",
"assistant/ui/assistant_scroll_view.h",
"assistant/ui/assistant_web_view.h", "assistant/ui/assistant_web_view.h",
"assistant/ui/caption_bar.h", "assistant/ui/caption_bar.h",
"assistant/ui/dialog_plate/action_view.h", "assistant/ui/dialog_plate/action_view.h",
...@@ -748,6 +749,7 @@ component("ash") { ...@@ -748,6 +749,7 @@ component("ash") {
"assistant/ui/assistant_container_view.cc", "assistant/ui/assistant_container_view.cc",
"assistant/ui/assistant_main_view.cc", "assistant/ui/assistant_main_view.cc",
"assistant/ui/assistant_mini_view.cc", "assistant/ui/assistant_mini_view.cc",
"assistant/ui/assistant_scroll_view.cc",
"assistant/ui/assistant_web_view.cc", "assistant/ui/assistant_web_view.cc",
"assistant/ui/caption_bar.cc", "assistant/ui/caption_bar.cc",
"assistant/ui/dialog_plate/action_view.cc", "assistant/ui/dialog_plate/action_view.cc",
......
// 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/assistant/ui/assistant_scroll_view.h"
#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
namespace ash {
namespace {
// ContentView ----------------------------------------------------------------
class ContentView : public views::View, views::ViewObserver {
public:
ContentView() { AddObserver(this); }
~ContentView() override { RemoveObserver(this); }
// views::View:
void ChildPreferredSizeChanged(views::View* child) override {
PreferredSizeChanged();
}
void ChildVisibilityChanged(views::View* child) override {
PreferredSizeChanged();
}
// views::ViewObserver:
void OnChildViewAdded(views::View* view, views::View* child) override {
PreferredSizeChanged();
}
void OnChildViewRemoved(views::View* view, views::View* child) override {
PreferredSizeChanged();
}
private:
DISALLOW_COPY_AND_ASSIGN(ContentView);
};
// InvisibleScrollBar ----------------------------------------------------------
class InvisibleScrollBar : public views::OverlayScrollBar {
public:
InvisibleScrollBar(bool horizontal) : views::OverlayScrollBar(horizontal) {}
~InvisibleScrollBar() override = default;
// views::OverlayScrollBar:
int GetThickness() const override { return 0; }
private:
DISALLOW_COPY_AND_ASSIGN(InvisibleScrollBar);
};
} // namespace
// AssistantScrollView ---------------------------------------------------------
AssistantScrollView::AssistantScrollView() {
InitLayout();
}
AssistantScrollView::~AssistantScrollView() = default;
void AssistantScrollView::OnViewPreferredSizeChanged(views::View* view) {
OnContentsPreferredSizeChanged(content_view_);
PreferredSizeChanged();
}
void AssistantScrollView::InitLayout() {
SetBackgroundColor(SK_ColorTRANSPARENT);
set_draw_overflow_indicator(false);
// Content view.
content_view_ = new ContentView();
content_view_->AddObserver(this);
SetContents(content_view_);
// Scroll bars.
horizontal_scroll_bar_ = new InvisibleScrollBar(/*horizontal=*/true);
SetHorizontalScrollBar(horizontal_scroll_bar_);
vertical_scroll_bar_ = new InvisibleScrollBar(/*horizontal=*/false);
SetVerticalScrollBar(vertical_scroll_bar_);
}
} // namespace ash
// 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 ASH_ASSISTANT_UI_ASSISTANT_SCROLL_VIEW_H_
#define ASH_ASSISTANT_UI_ASSISTANT_SCROLL_VIEW_H_
#include "base/macros.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/view_observer.h"
namespace ash {
class AssistantScrollView : public views::ScrollView, views::ViewObserver {
public:
AssistantScrollView();
~AssistantScrollView() override;
// views::ViewObserver:
void OnViewPreferredSizeChanged(views::View* view) override;
virtual void OnContentsPreferredSizeChanged(views::View* content_view) = 0;
protected:
views::View* content_view() { return content_view_; }
const views::View* content_view() const { return content_view_; }
views::ScrollBar* horizontal_scroll_bar() { return horizontal_scroll_bar_; }
views::ScrollBar* vertical_scroll_bar() { return vertical_scroll_bar_; }
private:
void InitLayout();
views::View* content_view_; // Owned by view hierarchy.
views::ScrollBar* horizontal_scroll_bar_; // Owned by view hierarchy.
views::ScrollBar* vertical_scroll_bar_; // Owned by view hierarchy.
DISALLOW_COPY_AND_ASSIGN(AssistantScrollView);
};
} // namespace ash
#endif // ASH_ASSISTANT_UI_ASSISTANT_SCROLL_VIEW_H_
...@@ -25,6 +25,7 @@ namespace { ...@@ -25,6 +25,7 @@ namespace {
// Appearance. // Appearance.
constexpr int kIconSizeDip = 24; constexpr int kIconSizeDip = 24;
constexpr int kPaddingHorizontalDip = 32;
// Appear animation. // Appear animation.
constexpr base::TimeDelta kAppearAnimationFadeInDelay = constexpr base::TimeDelta kAppearAnimationFadeInDelay =
...@@ -75,7 +76,8 @@ void AssistantHeaderView::ChildVisibilityChanged(views::View* child) { ...@@ -75,7 +76,8 @@ void AssistantHeaderView::ChildVisibilityChanged(views::View* child) {
void AssistantHeaderView::InitLayout() { void AssistantHeaderView::InitLayout() {
layout_manager_ = SetLayoutManager(std::make_unique<views::BoxLayout>( layout_manager_ = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical)); views::BoxLayout::Orientation::kVertical,
gfx::Insets(0, 0, kSpacingDip, 0)));
layout_manager_->set_cross_axis_alignment( layout_manager_->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER); views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER);
...@@ -121,7 +123,8 @@ void AssistantHeaderView::OnResponseChanged(const AssistantResponse& response) { ...@@ -121,7 +123,8 @@ void AssistantHeaderView::OnResponseChanged(const AssistantResponse& response) {
// The molecule icon will be animated from the center of its parent, to the // The molecule icon will be animated from the center of its parent, to the
// left hand side. // left hand side.
gfx::Transform transform; gfx::Transform transform;
transform.Translate(-(width() - molecule_icon_->width()) / 2, 0); transform.Translate(
-(width() - molecule_icon_->width()) / 2 + kPaddingHorizontalDip, 0);
// Animate the molecule icon. // Animate the molecule icon.
molecule_icon_->layer()->GetAnimator()->StartTogether( molecule_icon_->layer()->GetAnimator()->StartTogether(
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "ash/assistant/assistant_ui_controller.h" #include "ash/assistant/assistant_ui_controller.h"
#include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/assistant_ui_constants.h"
#include "ash/assistant/ui/main_stage/assistant_footer_view.h" #include "ash/assistant/ui/main_stage/assistant_footer_view.h"
#include "ash/assistant/ui/main_stage/assistant_header_view.h"
#include "ash/assistant/ui/main_stage/assistant_progress_indicator.h" #include "ash/assistant/ui/main_stage/assistant_progress_indicator.h"
#include "ash/assistant/ui/main_stage/assistant_query_view.h" #include "ash/assistant/ui/main_stage/assistant_query_view.h"
#include "ash/assistant/ui/main_stage/ui_element_container_view.h" #include "ash/assistant/ui/main_stage/ui_element_container_view.h"
...@@ -166,7 +167,7 @@ AssistantMainStage::AssistantMainStage( ...@@ -166,7 +167,7 @@ AssistantMainStage::AssistantMainStage(
/*animation_ended_callback=*/base::BindRepeating( /*animation_ended_callback=*/base::BindRepeating(
&AssistantMainStage::OnFooterAnimationEnded, &AssistantMainStage::OnFooterAnimationEnded,
base::Unretained(this)))) { base::Unretained(this)))) {
InitLayout(assistant_controller); InitLayout();
// The view hierarchy will be destructed before Shell, which owns // The view hierarchy will be destructed before Shell, which owns
// AssistantController, so AssistantController is guaranteed to outlive the // AssistantController, so AssistantController is guaranteed to outlive the
...@@ -211,7 +212,7 @@ void AssistantMainStage::OnViewVisibilityChanged(views::View* view) { ...@@ -211,7 +212,7 @@ void AssistantMainStage::OnViewVisibilityChanged(views::View* view) {
PreferredSizeChanged(); PreferredSizeChanged();
} }
void AssistantMainStage::InitLayout(AssistantController* assistant_controller) { void AssistantMainStage::InitLayout() {
SetLayoutManager(std::make_unique<views::FillLayout>()); SetLayoutManager(std::make_unique<views::FillLayout>());
// The children of AssistantMainStage will be animated on their own layers and // The children of AssistantMainStage will be animated on their own layers and
...@@ -220,13 +221,12 @@ void AssistantMainStage::InitLayout(AssistantController* assistant_controller) { ...@@ -220,13 +221,12 @@ void AssistantMainStage::InitLayout(AssistantController* assistant_controller) {
layer()->SetFillsBoundsOpaquely(false); layer()->SetFillsBoundsOpaquely(false);
layer()->SetMasksToBounds(true); layer()->SetMasksToBounds(true);
InitContentLayoutContainer(assistant_controller); InitContentLayoutContainer();
InitQueryLayoutContainer(assistant_controller); InitQueryLayoutContainer();
InitOverlayLayoutContainer(); InitOverlayLayoutContainer();
} }
void AssistantMainStage::InitContentLayoutContainer( void AssistantMainStage::InitContentLayoutContainer() {
AssistantController* assistant_controller) {
// Note that we will observe children of |content_layout_container_| to handle // Note that we will observe children of |content_layout_container_| to handle
// preferred size and visibility change events in AssistantMainStage. This is // preferred size and visibility change events in AssistantMainStage. This is
// necessary because |content_layout_container_| may not change size in // necessary because |content_layout_container_| may not change size in
...@@ -238,15 +238,19 @@ void AssistantMainStage::InitContentLayoutContainer( ...@@ -238,15 +238,19 @@ void AssistantMainStage::InitContentLayoutContainer(
std::make_unique<views::BoxLayout>( std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical)); views::BoxLayout::Orientation::kVertical));
// Header.
header_ = new AssistantHeaderView(assistant_controller_);
content_layout_container_->AddChildView(header_);
// UI element container. // UI element container.
ui_element_container_ = new UiElementContainerView(assistant_controller); ui_element_container_ = new UiElementContainerView(assistant_controller_);
ui_element_container_->AddObserver(this); ui_element_container_->AddObserver(this);
content_layout_container_->AddChildView(ui_element_container_); content_layout_container_->AddChildView(ui_element_container_);
layout_manager->SetFlexForView(ui_element_container_, 1); layout_manager->SetFlexForView(ui_element_container_, 1);
// Footer. // Footer.
footer_ = new AssistantFooterView(assistant_controller); footer_ = new AssistantFooterView(assistant_controller_);
footer_->AddObserver(this); footer_->AddObserver(this);
// The footer will be animated on its own layer. // The footer will be animated on its own layer.
...@@ -258,8 +262,7 @@ void AssistantMainStage::InitContentLayoutContainer( ...@@ -258,8 +262,7 @@ void AssistantMainStage::InitContentLayoutContainer(
AddChildView(content_layout_container_); AddChildView(content_layout_container_);
} }
void AssistantMainStage::InitQueryLayoutContainer( void AssistantMainStage::InitQueryLayoutContainer() {
AssistantController* assistant_controller) {
// Note that we will observe children of |query_layout_container_| to handle // Note that we will observe children of |query_layout_container_| to handle
// preferred size and visibility change events in AssistantMainStage. This is // preferred size and visibility change events in AssistantMainStage. This is
// necessary because |query_layout_container_| may not change size in response // necessary because |query_layout_container_| may not change size in response
...@@ -612,13 +615,12 @@ void AssistantMainStage::UpdateTopPadding() { ...@@ -612,13 +615,12 @@ void AssistantMainStage::UpdateTopPadding() {
const int top_padding = active_query_view_ ? active_query_view_->height() : 0; const int top_padding = active_query_view_ ? active_query_view_->height() : 0;
// Apply top padding to the content layout container by applying an empty // Apply top padding to the content layout container by applying an empty
// border to the UI element container, its first child. // border to the header, its first child.
ui_element_container_->SetBorder( header_->SetBorder(views::CreateEmptyBorder(top_padding, 0, 0, 0));
views::CreateEmptyBorder(top_padding, 0, 0, 0));
// Force a layout/paint pass. // Force a layout/paint pass.
ui_element_container_->Layout(); content_layout_container_->Layout();
ui_element_container_->SchedulePaint(); content_layout_container_->SchedulePaint();
// Apply top padding to the overlay layout container by applying an empty // Apply top padding to the overlay layout container by applying an empty
// border to its children. // border to its children.
......
...@@ -25,6 +25,7 @@ namespace ash { ...@@ -25,6 +25,7 @@ namespace ash {
class AssistantController; class AssistantController;
class AssistantFooterView; class AssistantFooterView;
class AssistantHeaderView;
class AssistantProgressIndicator; class AssistantProgressIndicator;
class AssistantQueryView; class AssistantQueryView;
class UiElementContainerView; class UiElementContainerView;
...@@ -59,9 +60,9 @@ class AssistantMainStage : public views::View, ...@@ -59,9 +60,9 @@ class AssistantMainStage : public views::View,
void OnUiVisibilityChanged(bool visible, AssistantSource source) override; void OnUiVisibilityChanged(bool visible, AssistantSource source) override;
private: private:
void InitLayout(AssistantController* assistant_controller); void InitLayout();
void InitContentLayoutContainer(AssistantController* assistant_controller); void InitContentLayoutContainer();
void InitQueryLayoutContainer(AssistantController* assistant_controller); void InitQueryLayoutContainer();
void InitOverlayLayoutContainer(); void InitOverlayLayoutContainer();
void UpdateTopPadding(); void UpdateTopPadding();
...@@ -81,6 +82,7 @@ class AssistantMainStage : public views::View, ...@@ -81,6 +82,7 @@ class AssistantMainStage : public views::View,
AssistantController* const assistant_controller_; // Owned by Shell. AssistantController* const assistant_controller_; // Owned by Shell.
// Content layout container and children. Owned by view hierarchy. // Content layout container and children. Owned by view hierarchy.
AssistantHeaderView* header_;
views::View* content_layout_container_; views::View* content_layout_container_;
UiElementContainerView* ui_element_container_; UiElementContainerView* ui_element_container_;
AssistantFooterView* footer_; AssistantFooterView* footer_;
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "ash/assistant/model/assistant_response.h" #include "ash/assistant/model/assistant_response.h"
#include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/assistant_ui_constants.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
namespace ash { namespace ash {
...@@ -21,22 +20,6 @@ namespace { ...@@ -21,22 +20,6 @@ namespace {
// Appearance. // Appearance.
constexpr int kPreferredHeightDip = 48; constexpr int kPreferredHeightDip = 48;
// InvisibleScrollBar ----------------------------------------------------------
class InvisibleScrollBar : public views::OverlayScrollBar {
public:
explicit InvisibleScrollBar(bool horizontal)
: views::OverlayScrollBar(horizontal) {}
~InvisibleScrollBar() override = default;
// views::OverlayScrollBar:
int GetThickness() const override { return 0; }
private:
DISALLOW_COPY_AND_ASSIGN(InvisibleScrollBar);
};
} // namespace } // namespace
// SuggestionContainerView ----------------------------------------------------- // SuggestionContainerView -----------------------------------------------------
...@@ -44,7 +27,6 @@ class InvisibleScrollBar : public views::OverlayScrollBar { ...@@ -44,7 +27,6 @@ class InvisibleScrollBar : public views::OverlayScrollBar {
SuggestionContainerView::SuggestionContainerView( SuggestionContainerView::SuggestionContainerView(
AssistantController* assistant_controller) AssistantController* assistant_controller)
: assistant_controller_(assistant_controller), : assistant_controller_(assistant_controller),
contents_view_(new views::View()),
download_request_weak_factory_(this) { download_request_weak_factory_(this) {
InitLayout(); InitLayout();
...@@ -65,21 +47,20 @@ int SuggestionContainerView::GetHeightForWidth(int width) const { ...@@ -65,21 +47,20 @@ int SuggestionContainerView::GetHeightForWidth(int width) const {
return kPreferredHeightDip; return kPreferredHeightDip;
} }
void SuggestionContainerView::OnContentsPreferredSizeChanged(
views::View* content_view) {
const int preferred_width = content_view->GetPreferredSize().width();
content_view->SetSize(gfx::Size(preferred_width, kPreferredHeightDip));
}
void SuggestionContainerView::InitLayout() { void SuggestionContainerView::InitLayout() {
// Contents.
views::BoxLayout* layout_manager = views::BoxLayout* layout_manager =
contents_view_->SetLayoutManager(std::make_unique<views::BoxLayout>( content_view()->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, views::BoxLayout::Orientation::kHorizontal,
gfx::Insets(0, kPaddingDip), kSpacingDip)); gfx::Insets(0, kPaddingDip), kSpacingDip));
layout_manager->set_cross_axis_alignment( layout_manager->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_END); views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_END);
// ScrollView.
SetBackgroundColor(SK_ColorTRANSPARENT);
SetContents(contents_view_);
SetHorizontalScrollBar(new InvisibleScrollBar(/*horizontal=*/true));
SetVerticalScrollBar(new InvisibleScrollBar(/*horizontal=*/false));
} }
void SuggestionContainerView::OnResponseChanged( void SuggestionContainerView::OnResponseChanged(
...@@ -123,10 +104,8 @@ void SuggestionContainerView::OnResponseChanged( ...@@ -123,10 +104,8 @@ void SuggestionContainerView::OnResponseChanged(
// suggestion chip view. This is used for handling icon download events. // suggestion chip view. This is used for handling icon download events.
suggestion_chip_views_[id] = suggestion_chip_view; suggestion_chip_views_[id] = suggestion_chip_view;
contents_view_->AddChildView(suggestion_chip_view); content_view()->AddChildView(suggestion_chip_view);
} }
UpdateContentsBounds();
} }
void SuggestionContainerView::OnResponseCleared() { void SuggestionContainerView::OnResponseCleared() {
...@@ -134,10 +113,8 @@ void SuggestionContainerView::OnResponseCleared() { ...@@ -134,10 +113,8 @@ void SuggestionContainerView::OnResponseCleared() {
download_request_weak_factory_.InvalidateWeakPtrs(); download_request_weak_factory_.InvalidateWeakPtrs();
// When modifying the view hierarchy, make sure we keep our view cache synced. // When modifying the view hierarchy, make sure we keep our view cache synced.
contents_view_->RemoveAllChildViews(/*delete_children=*/true); content_view()->RemoveAllChildViews(/*delete_children=*/true);
suggestion_chip_views_.clear(); suggestion_chip_views_.clear();
UpdateContentsBounds();
} }
void SuggestionContainerView::OnSuggestionChipIconDownloaded( void SuggestionContainerView::OnSuggestionChipIconDownloaded(
...@@ -153,9 +130,4 @@ void SuggestionContainerView::ButtonPressed(views::Button* sender, ...@@ -153,9 +130,4 @@ void SuggestionContainerView::ButtonPressed(views::Button* sender,
static_cast<app_list::SuggestionChipView*>(sender)->id()); static_cast<app_list::SuggestionChipView*>(sender)->id());
} }
void SuggestionContainerView::UpdateContentsBounds() {
contents_view_->SetBounds(0, 0, contents_view_->GetPreferredSize().width(),
kPreferredHeightDip);
}
} // namespace ash } // namespace ash
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "ash/app_list/views/suggestion_chip_view.h" #include "ash/app_list/views/suggestion_chip_view.h"
#include "ash/assistant/model/assistant_interaction_model_observer.h" #include "ash/assistant/model/assistant_interaction_model_observer.h"
#include "ash/assistant/ui/assistant_scroll_view.h"
#include "base/macros.h" #include "base/macros.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom.h" #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
#include "ui/views/controls/scroll_view.h" #include "ui/views/controls/scroll_view.h"
...@@ -20,7 +21,7 @@ class AssistantController; ...@@ -20,7 +21,7 @@ class AssistantController;
// SuggestionContainerView is the child of AssistantMainView concerned with // SuggestionContainerView is the child of AssistantMainView concerned with
// laying out SuggestionChipViews in response to Assistant interaction model // laying out SuggestionChipViews in response to Assistant interaction model
// suggestion events. // suggestion events.
class SuggestionContainerView : public views::ScrollView, class SuggestionContainerView : public AssistantScrollView,
public AssistantInteractionModelObserver, public AssistantInteractionModelObserver,
public views::ButtonListener { public views::ButtonListener {
public: public:
...@@ -29,9 +30,10 @@ class SuggestionContainerView : public views::ScrollView, ...@@ -29,9 +30,10 @@ class SuggestionContainerView : public views::ScrollView,
explicit SuggestionContainerView(AssistantController* assistant_controller); explicit SuggestionContainerView(AssistantController* assistant_controller);
~SuggestionContainerView() override; ~SuggestionContainerView() override;
// views::View: // AssistantScrollView:
gfx::Size CalculatePreferredSize() const override; gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int width) const override; int GetHeightForWidth(int width) const override;
void OnContentsPreferredSizeChanged(views::View* content_view) override;
// AssistantInteractionModelObserver: // AssistantInteractionModelObserver:
void OnResponseChanged(const AssistantResponse& response) override; void OnResponseChanged(const AssistantResponse& response) override;
...@@ -42,13 +44,11 @@ class SuggestionContainerView : public views::ScrollView, ...@@ -42,13 +44,11 @@ class SuggestionContainerView : public views::ScrollView,
private: private:
void InitLayout(); void InitLayout();
void UpdateContentsBounds();
// Invoked on suggestion chip icon downloaded event. // Invoked on suggestion chip icon downloaded event.
void OnSuggestionChipIconDownloaded(int id, const gfx::ImageSkia& icon); void OnSuggestionChipIconDownloaded(int id, const gfx::ImageSkia& icon);
AssistantController* const assistant_controller_; // Owned by Shell. 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 // 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 // map is the unique identifier by which the Assistant interaction model
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "ash/assistant/model/assistant_response.h" #include "ash/assistant/model/assistant_response.h"
#include "ash/assistant/model/assistant_ui_element.h" #include "ash/assistant/model/assistant_ui_element.h"
#include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/assistant_ui_constants.h"
#include "ash/assistant/ui/main_stage/assistant_header_view.h"
#include "ash/assistant/ui/main_stage/assistant_text_element_view.h" #include "ash/assistant/ui/main_stage/assistant_text_element_view.h"
#include "ash/assistant/util/animation_util.h" #include "ash/assistant/util/animation_util.h"
#include "ash/public/cpp/app_list/answer_card_contents_registry.h" #include "ash/public/cpp/app_list/answer_card_contents_registry.h"
...@@ -24,7 +23,6 @@ ...@@ -24,7 +23,6 @@
#include "ui/views/controls/native/native_view_host.h" #include "ui/views/controls/native/native_view_host.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h" #include "ui/views/layout/fill_layout.h"
#include "ui/views/view_observer.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_delegate.h"
...@@ -131,28 +129,38 @@ UiElementContainerView::~UiElementContainerView() { ...@@ -131,28 +129,38 @@ UiElementContainerView::~UiElementContainerView() {
ReleaseAllCards(); ReleaseAllCards();
} }
void UiElementContainerView::ChildPreferredSizeChanged(views::View* child) { gfx::Size UiElementContainerView::CalculatePreferredSize() const {
PreferredSizeChanged(); return gfx::Size(INT_MAX, GetHeightForWidth(INT_MAX));
}
int UiElementContainerView::GetHeightForWidth(int width) const {
return content_view()->GetHeightForWidth(width);
}
void UiElementContainerView::OnContentsPreferredSizeChanged(
views::View* content_view) {
const int preferred_height = content_view->GetHeightForWidth(width());
content_view->SetSize(gfx::Size(width(), preferred_height));
} }
void UiElementContainerView::InitLayout() { void UiElementContainerView::InitLayout() {
views::BoxLayout* layout_manager = views::BoxLayout* layout_manager =
SetLayoutManager(std::make_unique<views::BoxLayout>( content_view()->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, views::BoxLayout::Orientation::kVertical,
gfx::Insets(0, kPaddingHorizontalDip), kSpacingDip)); gfx::Insets(0, kPaddingHorizontalDip), kSpacingDip));
layout_manager->set_cross_axis_alignment( layout_manager->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_START); views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_START);
// Header.
assistant_header_view_ =
std::make_unique<AssistantHeaderView>(assistant_controller_);
assistant_header_view_->set_owned_by_client();
AddChildView(assistant_header_view_.get());
} }
void UiElementContainerView::OnCommittedQueryChanged( void UiElementContainerView::OnCommittedQueryChanged(
const AssistantQuery& query) { const AssistantQuery& query) {
// We don't allow processing of events while waiting for the next query
// response. The contents will be faded out, so it should not be interactive.
// We also scroll to the top to play nice with the transition animation.
set_can_process_events_within_subtree(false);
ScrollToPosition(vertical_scroll_bar(), 0);
if (!assistant::ui::kIsMotionSpecEnabled) if (!assistant::ui::kIsMotionSpecEnabled)
return; return;
...@@ -206,13 +214,9 @@ void UiElementContainerView::OnResponseCleared() { ...@@ -206,13 +214,9 @@ void UiElementContainerView::OnResponseCleared() {
// Prevent any in-flight card rendering requests from returning. // Prevent any in-flight card rendering requests from returning.
render_request_weak_factory_.InvalidateWeakPtrs(); render_request_weak_factory_.InvalidateWeakPtrs();
RemoveAllChildViews(/*delete_children=*/true); content_view()->RemoveAllChildViews(/*delete_children=*/true);
ui_element_layers_.clear(); ui_element_layers_.clear();
AddChildView(assistant_header_view_.get());
PreferredSizeChanged();
ReleaseAllCards(); ReleaseAllCards();
// We can clear any pending UI elements as they are no longer relevant. // We can clear any pending UI elements as they are no longer relevant.
...@@ -242,6 +246,10 @@ void UiElementContainerView::OnResponseAdded( ...@@ -242,6 +246,10 @@ void UiElementContainerView::OnResponseAdded(
void UiElementContainerView::OnAllUiElementsAdded() { void UiElementContainerView::OnAllUiElementsAdded() {
DCHECK(!is_processing_ui_element_); DCHECK(!is_processing_ui_element_);
// Now that the response for the current query has been added to the view
// hierarchy, we can re-enable processing of events.
set_can_process_events_within_subtree(true);
// If the motion spec is disabled, there's nothing to do because the views // If the motion spec is disabled, there's nothing to do because the views
// do not need to be animated in. // do not need to be animated in.
if (!assistant::ui::kIsMotionSpecEnabled) if (!assistant::ui::kIsMotionSpecEnabled)
...@@ -347,7 +355,7 @@ void UiElementContainerView::OnCardReady( ...@@ -347,7 +355,7 @@ void UiElementContainerView::OnCardReady(
app_list::AnswerCardContentsRegistry::Get()->GetView( app_list::AnswerCardContentsRegistry::Get()->GetView(
embed_token.value())); embed_token.value()));
AddChildView(view_holder); content_view()->AddChildView(view_holder);
view_holder->Attach(); view_holder->Attach();
if (assistant::ui::kIsMotionSpecEnabled) { if (assistant::ui::kIsMotionSpecEnabled) {
...@@ -366,8 +374,6 @@ void UiElementContainerView::OnCardReady( ...@@ -366,8 +374,6 @@ void UiElementContainerView::OnCardReady(
} }
// TODO(dmblack): Handle Mash case. // TODO(dmblack): Handle Mash case.
PreferredSizeChanged();
// Once the card has been rendered and embedded, we can resume processing // Once the card has been rendered and embedded, we can resume processing
// any UI elements that are in the pending queue. // any UI elements that are in the pending queue.
SetProcessingUiElement(false); SetProcessingUiElement(false);
...@@ -393,8 +399,7 @@ void UiElementContainerView::OnTextElementAdded( ...@@ -393,8 +399,7 @@ void UiElementContainerView::OnTextElementAdded(
text_element_view->layer(), kTextElementAnimationFadeOutOpacity)); text_element_view->layer(), kTextElementAnimationFadeOutOpacity));
} }
AddChildView(text_element_view); content_view()->AddChildView(text_element_view);
PreferredSizeChanged();
} }
void UiElementContainerView::SetProcessingUiElement(bool is_processing) { void UiElementContainerView::SetProcessingUiElement(bool is_processing) {
......
...@@ -10,8 +10,9 @@ ...@@ -10,8 +10,9 @@
#include <vector> #include <vector>
#include "ash/assistant/model/assistant_interaction_model_observer.h" #include "ash/assistant/model/assistant_interaction_model_observer.h"
#include "ash/assistant/ui/assistant_scroll_view.h"
#include "base/macros.h" #include "base/macros.h"
#include "ui/views/view.h" #include "ui/views/view_observer.h"
namespace ui { namespace ui {
class CallbackLayerAnimationObserver; class CallbackLayerAnimationObserver;
...@@ -21,7 +22,6 @@ namespace ash { ...@@ -21,7 +22,6 @@ namespace ash {
class AssistantCardElement; class AssistantCardElement;
class AssistantController; class AssistantController;
class AssistantHeaderView;
class AssistantResponse; class AssistantResponse;
class AssistantTextElement; class AssistantTextElement;
class AssistantUiElement; class AssistantUiElement;
...@@ -30,14 +30,16 @@ enum class AssistantUiElementType; ...@@ -30,14 +30,16 @@ enum class AssistantUiElementType;
// UiElementContainerView is the child of AssistantMainView concerned with // UiElementContainerView is the child of AssistantMainView concerned with
// laying out text views and embedded card views in response to Assistant // laying out text views and embedded card views in response to Assistant
// interaction model UI element events. // interaction model UI element events.
class UiElementContainerView : public views::View, class UiElementContainerView : public AssistantScrollView,
public AssistantInteractionModelObserver { public AssistantInteractionModelObserver {
public: public:
explicit UiElementContainerView(AssistantController* assistant_controller); explicit UiElementContainerView(AssistantController* assistant_controller);
~UiElementContainerView() override; ~UiElementContainerView() override;
// views::View: // AssistantScrollView:
void ChildPreferredSizeChanged(views::View* child) override; gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int width) const override;
void OnContentsPreferredSizeChanged(views::View* content_view) override;
// AssistantInteractionModelObserver: // AssistantInteractionModelObserver:
void OnCommittedQueryChanged(const AssistantQuery& query) override; void OnCommittedQueryChanged(const AssistantQuery& query) override;
...@@ -68,8 +70,6 @@ class UiElementContainerView : public views::View, ...@@ -68,8 +70,6 @@ class UiElementContainerView : public views::View,
AssistantController* const assistant_controller_; // Owned by Shell. AssistantController* const assistant_controller_; // Owned by Shell.
std::unique_ptr<AssistantHeaderView> assistant_header_view_;
// Uniquely identifies cards owned by AssistantCardRenderer. // Uniquely identifies cards owned by AssistantCardRenderer.
std::vector<base::UnguessableToken> id_token_list_; std::vector<base::UnguessableToken> id_token_list_;
......
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