Commit 1e0704e6 authored by Nicolas Ouellet-Payeur's avatar Nicolas Ouellet-Payeur Committed by Commit Bot

Reland: Add footnote support to top-level menus

Adds a function to |MenuDelegate| that can be overloaded to create a
footnote View for a top-level menu.

The footnote view is rendered at the bottom of the menu, with a
different background color, similar to
|BubbleFrameView::SetFootnoteView()|.

Bug: 889229, 894193
Change-Id: Icb67740fddfe03a7a2d9bae7c70b383cfe6a9845
Reviewed-on: https://chromium-review.googlesource.com/c/1277573Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Commit-Queue: Nicolas Ouellet-Payeur <nicolaso@chromium.org>
Cr-Commit-Position: refs/heads/master@{#599881}
parent 09dcd00f
...@@ -288,6 +288,7 @@ jumbo_component("views") { ...@@ -288,6 +288,7 @@ jumbo_component("views") {
"bubble/bubble_border.cc", "bubble/bubble_border.cc",
"bubble/bubble_dialog_delegate_view.cc", "bubble/bubble_dialog_delegate_view.cc",
"bubble/bubble_frame_view.cc", "bubble/bubble_frame_view.cc",
"bubble/footnote_container_view.cc",
"bubble/info_bubble.cc", "bubble/info_bubble.cc",
"bubble/tooltip_icon.cc", "bubble/tooltip_icon.cc",
"button_drag_utils.cc", "button_drag_utils.cc",
...@@ -976,6 +977,7 @@ source_set("views_unittests_sources") { ...@@ -976,6 +977,7 @@ source_set("views_unittests_sources") {
"controls/image_view_unittest.cc", "controls/image_view_unittest.cc",
"controls/label_unittest.cc", "controls/label_unittest.cc",
"controls/menu/menu_controller_unittest.cc", "controls/menu/menu_controller_unittest.cc",
"controls/menu/menu_footnote_unittest.cc",
"controls/menu/menu_item_view_unittest.cc", "controls/menu/menu_item_view_unittest.cc",
"controls/menu/menu_model_adapter_unittest.cc", "controls/menu/menu_model_adapter_unittest.cc",
"controls/menu/menu_runner_cocoa_unittest.mm", "controls/menu/menu_runner_cocoa_unittest.mm",
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "ui/strings/grit/ui_strings.h" #include "ui/strings/grit/ui_strings.h"
#include "ui/views/bubble/bubble_border.h" #include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/bubble/footnote_container_view.h"
#include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/image_button_factory.h" #include "ui/views/controls/button/image_button_factory.h"
#include "ui/views/controls/image_view.h" #include "ui/views/controls/image_view.h"
...@@ -68,21 +69,6 @@ int GetOffScreenLength(const gfx::Rect& available_bounds, ...@@ -68,21 +69,6 @@ int GetOffScreenLength(const gfx::Rect& available_bounds,
} // namespace } // namespace
// A container that changes visibility with its contents.
class FootnoteContainerView : public View {
public:
FootnoteContainerView() {}
// View:
void ChildVisibilityChanged(View* child) override {
DCHECK_EQ(child_count(), 1);
SetVisible(child->visible());
}
private:
DISALLOW_COPY_AND_ASSIGN(FootnoteContainerView);
};
// static // static
const char BubbleFrameView::kViewClassName[] = "BubbleFrameView"; const char BubbleFrameView::kViewClassName[] = "BubbleFrameView";
...@@ -449,6 +435,10 @@ void BubbleFrameView::ButtonPressed(Button* sender, const ui::Event& event) { ...@@ -449,6 +435,10 @@ void BubbleFrameView::ButtonPressed(Button* sender, const ui::Event& event) {
void BubbleFrameView::SetBubbleBorder(std::unique_ptr<BubbleBorder> border) { void BubbleFrameView::SetBubbleBorder(std::unique_ptr<BubbleBorder> border) {
bubble_border_ = border.get(); bubble_border_ = border.get();
if (footnote_container_)
footnote_container_->SetCornerRadius(border->GetBorderCornerRadius());
SetBorder(std::move(border)); SetBorder(std::move(border));
// Update the background, which relies on the border. // Update the background, which relies on the border.
...@@ -460,15 +450,9 @@ void BubbleFrameView::SetFootnoteView(View* view) { ...@@ -460,15 +450,9 @@ void BubbleFrameView::SetFootnoteView(View* view) {
return; return;
DCHECK(!footnote_container_); DCHECK(!footnote_container_);
footnote_container_ = new FootnoteContainerView(); int radius = bubble_border_ ? bubble_border_->GetBorderCornerRadius() : 0;
footnote_container_->SetLayoutManager( footnote_container_ =
std::make_unique<BoxLayout>(BoxLayout::kVertical, footnote_margins_, 0)); new FootnoteContainerView(footnote_margins_, view, radius);
footnote_container_->SetBackground(
CreateSolidBackground(gfx::kGoogleGrey050));
footnote_container_->SetBorder(
CreateSolidSidedBorder(1, 0, 0, 0, gfx::kGoogleGrey200));
footnote_container_->AddChildView(view);
footnote_container_->SetVisible(view->visible());
AddChildView(footnote_container_); AddChildView(footnote_container_);
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
namespace views { namespace views {
class BubbleBorder; class BubbleBorder;
class FootnoteContainerView;
class ImageView; class ImageView;
// The non-client frame view of bubble-styled widgets. // The non-client frame view of bubble-styled widgets.
...@@ -183,7 +184,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView, ...@@ -183,7 +184,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
Button* close_; Button* close_;
// A view to contain the footnote view, if it exists. // A view to contain the footnote view, if it exists.
View* footnote_container_; FootnoteContainerView* footnote_container_;
// Whether the close button was clicked. // Whether the close button was clicked.
bool close_button_clicked_; bool close_button_clicked_;
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "ui/gfx/text_utils.h" #include "ui/gfx/text_utils.h"
#include "ui/views/bubble/bubble_border.h" #include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/bubble/footnote_container_view.h"
#include "ui/views/controls/button/label_button.h" #include "ui/views/controls/button/label_button.h"
#include "ui/views/metrics.h" #include "ui/views/metrics.h"
#include "ui/views/test/test_layout_provider.h" #include "ui/views/test/test_layout_provider.h"
......
// 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 "ui/views/bubble/footnote_container_view.h"
#include "cc/paint/paint_flags.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/layout/box_layout.h"
namespace views {
namespace {
// A solid color background where the bottom two corners are rounded.
class HalfRoundedRectBackground : public Background {
public:
explicit HalfRoundedRectBackground(SkColor color, float radius)
: radius_(radius) {
SetNativeControlColor(color);
}
~HalfRoundedRectBackground() override = default;
// Background:
void Paint(gfx::Canvas* canvas, View* view) const override {
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(get_color());
// Draw a rounded rect that spills outside of the clipping area, so that the
// rounded corners only show in the bottom 2 corners.
gfx::RectF spilling_rect(view->GetLocalBounds());
spilling_rect.set_y(spilling_rect.x() - radius_);
spilling_rect.set_height(spilling_rect.height() + radius_);
canvas->DrawRoundRect(spilling_rect, radius_, flags);
}
private:
float radius_;
DISALLOW_IMPLICIT_CONSTRUCTORS(HalfRoundedRectBackground);
};
} // namespace
FootnoteContainerView::FootnoteContainerView(const gfx::Insets& margins,
View* child_view,
float corner_radius) {
SetLayoutManager(
std::make_unique<BoxLayout>(BoxLayout::kVertical, margins, 0));
SetCornerRadius(corner_radius);
SetBorder(CreateSolidSidedBorder(1, 0, 0, 0, gfx::kGoogleGrey200));
AddChildView(child_view);
SetVisible(child_view->visible());
}
FootnoteContainerView::~FootnoteContainerView() = default;
void FootnoteContainerView::SetCornerRadius(float corner_radius) {
SetBackground(std::make_unique<HalfRoundedRectBackground>(gfx::kGoogleGrey050,
corner_radius));
}
void FootnoteContainerView::ChildVisibilityChanged(View* child) {
DCHECK_EQ(child_count(), 1);
SetVisible(child->visible());
}
} // namespace views
// 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 UI_VIEWS_BUBBLE_FOOTNOTE_CONTAINER_VIEW_H_
#define UI_VIEWS_BUBBLE_FOOTNOTE_CONTAINER_VIEW_H_
#include "ui/views/view.h"
namespace views {
// A container that changes visibility with its contents, and draws a solid
// background with rounded corners at the bottom.
class FootnoteContainerView : public View {
public:
FootnoteContainerView(const gfx::Insets& margins,
View* child_view,
float corner_radius);
~FootnoteContainerView() override;
void SetCornerRadius(float corner_radius);
// View:
void ChildVisibilityChanged(View* child) override;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FootnoteContainerView);
};
} // namespace views
#endif // UI_VIEWS_BUBBLE_FOOTNOTE_CONTAINER_VIEW_H_
...@@ -152,4 +152,8 @@ bool MenuDelegate::ShouldReserveSpaceForSubmenuIndicator() const { ...@@ -152,4 +152,8 @@ bool MenuDelegate::ShouldReserveSpaceForSubmenuIndicator() const {
return true; return true;
} }
View* MenuDelegate::CreateFootnoteView() {
return nullptr;
}
} // namespace views } // namespace views
...@@ -35,6 +35,7 @@ namespace views { ...@@ -35,6 +35,7 @@ namespace views {
class MenuButton; class MenuButton;
class MenuItemView; class MenuItemView;
class View;
// MenuDelegate -------------------------------------------------------------- // MenuDelegate --------------------------------------------------------------
...@@ -233,6 +234,11 @@ class VIEWS_EXPORT MenuDelegate { ...@@ -233,6 +234,11 @@ class VIEWS_EXPORT MenuDelegate {
// Returns true if the labels should reserve additional spacing for e.g. // Returns true if the labels should reserve additional spacing for e.g.
// submenu indicators at the end of the line. // submenu indicators at the end of the line.
virtual bool ShouldReserveSpaceForSubmenuIndicator() const; virtual bool ShouldReserveSpaceForSubmenuIndicator() const;
// Override this function to display a footnote view below the menu-items in a
// top-level menu. Overrides may construct the view; this will only be called
// once per menu.
virtual View* CreateFootnoteView();
}; };
} // namespace views } // namespace views
......
// 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 "ui/views/controls/menu/submenu_view.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/controls/menu/menu_delegate.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/test/menu_test_utils.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
namespace views {
namespace test {
namespace {
// MenuDelegate mock to control the CreateFootnoteView() method.
class MockMenuDelegate : public MenuDelegate {
public:
MockMenuDelegate() = default;
~MockMenuDelegate() override = default;
void set_create_footnote_view_value(View* view) {
create_footnote_view_value_ = view;
}
int create_footnote_view_count() { return create_footnote_view_count_; }
// MenuDelegate:
View* CreateFootnoteView() override {
create_footnote_view_count_++;
return create_footnote_view_value_;
}
private:
// The return value for the next CreateFootnoteView call.
View* create_footnote_view_value_ = nullptr;
// The number of times CreateFootnoteView was called.
int create_footnote_view_count_ = 0;
DISALLOW_COPY_AND_ASSIGN(MockMenuDelegate);
};
} // namespace
class MenuFootnoteTest : public ViewsTestBase {
public:
MenuFootnoteTest();
~MenuFootnoteTest() override;
// ViewsTestBase:
void SetUp() override {
ViewsTestBase::SetUp();
menu_delegate_ = std::make_unique<MockMenuDelegate>();
menu_item_view_ = new MenuItemView(menu_delegate_.get());
item_with_submenu_ = menu_item_view_->AppendSubMenu(0, base::string16());
owner_ = std::make_unique<Widget>();
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
owner_->Init(params);
owner_->Show();
menu_runner_ = std::make_unique<MenuRunner>(menu_item_view_, 0);
}
void TearDown() override {
if (owner_)
owner_->CloseNow();
ViewsTestBase::TearDown();
}
protected:
// Owned by menu_runner_.
MenuItemView* menu_item_view_ = nullptr;
// An item with a submenu, in menu_item_view_.
MenuItemView* item_with_submenu_ = nullptr;
std::unique_ptr<MockMenuDelegate> menu_delegate_;
std::unique_ptr<MenuRunner> menu_runner_;
std::unique_ptr<Widget> owner_;
private:
DISALLOW_COPY_AND_ASSIGN(MenuFootnoteTest);
};
MenuFootnoteTest::MenuFootnoteTest() = default;
MenuFootnoteTest::~MenuFootnoteTest() = default;
TEST_F(MenuFootnoteTest, TopLevelContainerShowsFootnote) {
View* footnote = new View();
menu_delegate_->set_create_footnote_view_value(footnote);
menu_runner_->RunMenuAt(owner_.get(), nullptr, gfx::Rect(),
MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE);
EXPECT_EQ(1, menu_delegate_->create_footnote_view_count());
EXPECT_TRUE(menu_item_view_->GetSubmenu()->Contains(footnote));
}
TEST_F(MenuFootnoteTest, SubmenuDoesNotShowFootnote) {
View* footnote = new View();
menu_delegate_->set_create_footnote_view_value(footnote);
menu_runner_->RunMenuAt(owner_.get(), nullptr, gfx::Rect(),
MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE);
// Trigger the code that would create a footnote, then check that the footnote
// was not created.
item_with_submenu_->GetSubmenu()->GetScrollViewContainer();
EXPECT_FALSE(item_with_submenu_->GetSubmenu()->Contains(footnote));
EXPECT_EQ(1, menu_delegate_->create_footnote_view_count());
}
} // namespace test
} // namespace views
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "ui/gfx/color_palette.h" #include "ui/gfx/color_palette.h"
#include "ui/views/border.h" #include "ui/views/border.h"
#include "ui/views/bubble/bubble_border.h" #include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/footnote_container_view.h"
#include "ui/views/controls/menu/menu_config.h" #include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_controller.h" #include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/controls/menu/menu_item_view.h" #include "ui/views/controls/menu/menu_item_view.h"
...@@ -172,9 +173,7 @@ class MenuScrollViewContainer::MenuScrollView : public View { ...@@ -172,9 +173,7 @@ class MenuScrollViewContainer::MenuScrollView : public View {
// MenuScrollViewContainer ---------------------------------------------------- // MenuScrollViewContainer ----------------------------------------------------
MenuScrollViewContainer::MenuScrollViewContainer(SubmenuView* content_view) MenuScrollViewContainer::MenuScrollViewContainer(SubmenuView* content_view)
: content_view_(content_view), : content_view_(content_view) {
arrow_(BubbleBorder::NONE),
bubble_border_(NULL) {
scroll_up_button_ = new MenuScrollButton(content_view, true); scroll_up_button_ = new MenuScrollButton(content_view, true);
scroll_down_button_ = new MenuScrollButton(content_view, false); scroll_down_button_ = new MenuScrollButton(content_view, false);
AddChildView(scroll_up_button_); AddChildView(scroll_up_button_);
...@@ -186,10 +185,7 @@ MenuScrollViewContainer::MenuScrollViewContainer(SubmenuView* content_view) ...@@ -186,10 +185,7 @@ MenuScrollViewContainer::MenuScrollViewContainer(SubmenuView* content_view)
arrow_ = BubbleBorderTypeFromAnchor( arrow_ = BubbleBorderTypeFromAnchor(
content_view_->GetMenuItem()->GetMenuController()->GetAnchorPosition()); content_view_->GetMenuItem()->GetMenuController()->GetAnchorPosition());
if (arrow_ != BubbleBorder::NONE) CreateBorder();
CreateBubbleBorder();
else
CreateDefaultBorder();
} }
bool MenuScrollViewContainer::HasBubbleBorder() { bool MenuScrollViewContainer::HasBubbleBorder() {
...@@ -201,6 +197,21 @@ void MenuScrollViewContainer::SetBubbleArrowOffset(int offset) { ...@@ -201,6 +197,21 @@ void MenuScrollViewContainer::SetBubbleArrowOffset(int offset) {
bubble_border_->set_arrow_offset(offset); bubble_border_->set_arrow_offset(offset);
} }
void MenuScrollViewContainer::SetFootnoteView(View* view) {
DCHECK(view);
DCHECK(!footnote_container_);
footnote_container_ = new FootnoteContainerView(gfx::Insets(), view, 0);
content_view_->AddChildView(footnote_container_);
// Recreate the border. This updates the corner-radius for
// |footnote_container_| and margins, so |footnote_container_| can draw the
// bottom of the menu.
CreateBorder();
}
bool MenuScrollViewContainer::HasVisibleFootnote() {
return footnote_container_ && footnote_container_->visible();
}
gfx::Size MenuScrollViewContainer::CalculatePreferredSize() const { gfx::Size MenuScrollViewContainer::CalculatePreferredSize() const {
gfx::Size prefsize = scroll_view_->GetContents()->GetPreferredSize(); gfx::Size prefsize = scroll_view_->GetContents()->GetPreferredSize();
gfx::Insets insets = GetInsets(); gfx::Insets insets = GetInsets();
...@@ -217,6 +228,10 @@ void MenuScrollViewContainer::Layout() { ...@@ -217,6 +228,10 @@ void MenuScrollViewContainer::Layout() {
if (!scroll_up_button_->visible()) { if (!scroll_up_button_->visible()) {
scroll_view_->SetBounds(x, y, width, content_height); scroll_view_->SetBounds(x, y, width, content_height);
scroll_view_->Layout(); scroll_view_->Layout();
if (footnote_container_ && bubble_border_) {
int radius = bubble_border_->GetBorderCornerRadius();
footnote_container_->SetCornerRadius(radius);
}
return; return;
} }
...@@ -231,13 +246,17 @@ void MenuScrollViewContainer::Layout() { ...@@ -231,13 +246,17 @@ void MenuScrollViewContainer::Layout() {
width, pref.height()); width, pref.height());
content_height -= pref.height(); content_height -= pref.height();
// Don't round the footnote when the scroll button is visible.
if (footnote_container_)
footnote_container_->SetCornerRadius(0);
scroll_view_->SetBounds(x, scroll_view_y, width, content_height); scroll_view_->SetBounds(x, scroll_view_y, width, content_height);
scroll_view_->Layout(); scroll_view_->Layout();
} }
void MenuScrollViewContainer::OnNativeThemeChanged( void MenuScrollViewContainer::OnNativeThemeChanged(
const ui::NativeTheme* theme) { const ui::NativeTheme* theme) {
if (arrow_ == BubbleBorder::NONE) if (!HasBubbleBorder())
CreateDefaultBorder(); CreateDefaultBorder();
} }
...@@ -270,6 +289,13 @@ void MenuScrollViewContainer::OnBoundsChanged( ...@@ -270,6 +289,13 @@ void MenuScrollViewContainer::OnBoundsChanged(
Layout(); Layout();
} }
void MenuScrollViewContainer::CreateBorder() {
if (HasBubbleBorder())
CreateBubbleBorder();
else
CreateDefaultBorder();
}
void MenuScrollViewContainer::CreateDefaultBorder() { void MenuScrollViewContainer::CreateDefaultBorder() {
DCHECK_EQ(arrow_, BubbleBorder::NONE); DCHECK_EQ(arrow_, BubbleBorder::NONE);
bubble_border_ = nullptr; bubble_border_ = nullptr;
...@@ -292,6 +318,8 @@ void MenuScrollViewContainer::CreateDefaultBorder() { ...@@ -292,6 +318,8 @@ void MenuScrollViewContainer::CreateDefaultBorder() {
const int horizontal_inset = const int horizontal_inset =
menu_config.menu_horizontal_border_size + padding; menu_config.menu_horizontal_border_size + padding;
int bottom_inset = HasVisibleFootnote() ? 0 : vertical_inset;
if (use_outer_border) { if (use_outer_border) {
SkColor color = GetNativeTheme() SkColor color = GetNativeTheme()
? GetNativeTheme()->GetSystemColor( ? GetNativeTheme()->GetSystemColor(
...@@ -299,10 +327,11 @@ void MenuScrollViewContainer::CreateDefaultBorder() { ...@@ -299,10 +327,11 @@ void MenuScrollViewContainer::CreateDefaultBorder() {
: gfx::kPlaceholderColor; : gfx::kPlaceholderColor;
SetBorder(views::CreateBorderPainter( SetBorder(views::CreateBorderPainter(
std::make_unique<views::RoundRectPainter>(color, corner_radius), std::make_unique<views::RoundRectPainter>(color, corner_radius),
gfx::Insets(vertical_inset, horizontal_inset))); gfx::Insets(vertical_inset, horizontal_inset, bottom_inset,
horizontal_inset)));
} else { } else {
SetBorder(CreateEmptyBorder(vertical_inset, horizontal_inset, SetBorder(CreateEmptyBorder(vertical_inset, horizontal_inset, bottom_inset,
vertical_inset, horizontal_inset)); horizontal_inset));
} }
} }
...@@ -316,8 +345,10 @@ void MenuScrollViewContainer::CreateBubbleBorder() { ...@@ -316,8 +345,10 @@ void MenuScrollViewContainer::CreateBubbleBorder() {
bubble_border_->SetCornerRadius(menu_config.touchable_corner_radius); bubble_border_->SetCornerRadius(menu_config.touchable_corner_radius);
bubble_border_->set_md_shadow_elevation( bubble_border_->set_md_shadow_elevation(
menu_config.touchable_menu_shadow_elevation); menu_config.touchable_menu_shadow_elevation);
scroll_view_->GetContents()->SetBorder(CreateEmptyBorder( gfx::Insets insets(menu_config.vertical_touchable_menu_item_padding, 0);
gfx::Insets(menu_config.vertical_touchable_menu_item_padding, 0))); if (HasVisibleFootnote())
insets.Set(menu_config.vertical_touchable_menu_item_padding, 0, 0, 0);
scroll_view_->GetContents()->SetBorder(CreateEmptyBorder(insets));
} }
SetBorder(std::unique_ptr<Border>(bubble_border_)); SetBorder(std::unique_ptr<Border>(bubble_border_));
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
namespace views { namespace views {
class FootnoteContainerView;
class SubmenuView; class SubmenuView;
// MenuScrollViewContainer contains the SubmenuView (through a MenuScrollView) // MenuScrollViewContainer contains the SubmenuView (through a MenuScrollView)
...@@ -31,6 +32,8 @@ class MenuScrollViewContainer : public View { ...@@ -31,6 +32,8 @@ class MenuScrollViewContainer : public View {
// Offsets the Arrow from the default location. // Offsets the Arrow from the default location.
void SetBubbleArrowOffset(int offset); void SetBubbleArrowOffset(int offset);
void SetFootnoteView(View* view);
// View overrides. // View overrides.
gfx::Size CalculatePreferredSize() const override; gfx::Size CalculatePreferredSize() const override;
void Layout() override; void Layout() override;
...@@ -43,6 +46,9 @@ class MenuScrollViewContainer : public View { ...@@ -43,6 +46,9 @@ class MenuScrollViewContainer : public View {
void OnBoundsChanged(const gfx::Rect& previous_bounds) override; void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
private: private:
// Create a default border or bubble border, as appropriate.
void CreateBorder();
// Create the default border. // Create the default border.
void CreateDefaultBorder(); void CreateDefaultBorder();
...@@ -51,6 +57,8 @@ class MenuScrollViewContainer : public View { ...@@ -51,6 +57,8 @@ class MenuScrollViewContainer : public View {
BubbleBorder::Arrow BubbleBorderTypeFromAnchor(MenuAnchorPosition anchor); BubbleBorder::Arrow BubbleBorderTypeFromAnchor(MenuAnchorPosition anchor);
bool HasVisibleFootnote();
class MenuScrollView; class MenuScrollView;
// The scroll buttons. // The scroll buttons.
...@@ -64,10 +72,13 @@ class MenuScrollViewContainer : public View { ...@@ -64,10 +72,13 @@ class MenuScrollViewContainer : public View {
SubmenuView* content_view_; SubmenuView* content_view_;
// If set the currently set border is a bubble border. // If set the currently set border is a bubble border.
BubbleBorder::Arrow arrow_; BubbleBorder::Arrow arrow_ = BubbleBorder::NONE;
// Weak reference to the currently set border. // Weak reference to the currently set border.
BubbleBorder* bubble_border_; BubbleBorder* bubble_border_ = nullptr;
// A view to contain the footnote view, if it exists.
FootnoteContainerView* footnote_container_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(MenuScrollViewContainer); DISALLOW_COPY_AND_ASSIGN(MenuScrollViewContainer);
}; };
......
...@@ -469,6 +469,13 @@ bool SubmenuView::GetShowSelection(MenuItemView* item) { ...@@ -469,6 +469,13 @@ bool SubmenuView::GetShowSelection(MenuItemView* item) {
MenuScrollViewContainer* SubmenuView::GetScrollViewContainer() { MenuScrollViewContainer* SubmenuView::GetScrollViewContainer() {
if (!scroll_view_container_) { if (!scroll_view_container_) {
scroll_view_container_ = new MenuScrollViewContainer(this); scroll_view_container_ = new MenuScrollViewContainer(this);
if (GetMenuItem()->GetParentMenuItem() == nullptr) {
// Top-level menu, this may have a footnote. Submenus can't have a
// footnote, because they share the |MenuDelegate| with their parent.
View* footnote_view = GetMenuItem()->GetDelegate()->CreateFootnoteView();
if (footnote_view)
scroll_view_container_->SetFootnoteView(footnote_view);
}
// Otherwise MenuHost would delete us. // Otherwise MenuHost would delete us.
scroll_view_container_->set_owned_by_client(); scroll_view_container_->set_owned_by_client();
} }
......
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