1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/time/time.h"
12 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
13 #include "chrome/browser/ui/views/frame/browser_view.h"
14 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
15 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
16 #include "chrome/browser/ui/views/toolbar/wrench_menu.h"
17 #include "ui/views/controls/menu/menu_item_view.h"
18 #include "ui/views/controls/menu/submenu_view.h"
21 // The delay before we close the wrench menu if this was opened for a drop so
22 // that the user can see a browser action if one was moved.
23 // This can be changed for tests.
24 int g_close_menu_delay
= 300;
27 ExtensionToolbarMenuView::ExtensionToolbarMenuView(Browser
* browser
,
28 WrenchMenu
* wrench_menu
)
30 wrench_menu_(wrench_menu
),
33 browser_actions_container_observer_(this),
35 BrowserActionsContainer
* main
=
36 BrowserView::GetBrowserViewForBrowser(browser_
)
37 ->toolbar()->browser_actions();
38 container_
= new BrowserActionsContainer(browser_
, main
);
40 SetContents(container_
);
41 // We Layout() the container here so that we know the number of actions
42 // that will be visible in ShouldShow().
45 // Listen for the drop to finish so we can close the wrench menu, if
47 browser_actions_container_observer_
.Add(container_
);
48 browser_actions_container_observer_
.Add(main
);
50 // In *very* extreme cases, it's possible that there are so many overflowed
51 // actions, we won't be able to show them all. Cap the height so that the
52 // overflow won't be excessively tall (at 8 icons per row, this allows for
53 // 104 total extensions).
54 const int kMaxOverflowRows
= 13;
55 max_height_
= ToolbarActionsBar::IconHeight() * kMaxOverflowRows
;
56 ClipHeightTo(0, max_height_
);
59 ExtensionToolbarMenuView::~ExtensionToolbarMenuView() {
62 bool ExtensionToolbarMenuView::ShouldShow() {
63 return wrench_menu_
->for_drop() ||
64 container_
->VisibleBrowserActionsAfterAnimation();
67 gfx::Size
ExtensionToolbarMenuView::GetPreferredSize() const {
68 gfx::Size s
= views::ScrollView::GetPreferredSize();
69 // views::ScrollView::GetPreferredSize() includes the contents' size, but
70 // not the scrollbar width. Add it in if necessary.
71 if (container_
->GetPreferredSize().height() > max_height_
)
72 s
.Enlarge(GetScrollBarWidth(), 0);
76 int ExtensionToolbarMenuView::GetHeightForWidth(int width
) const {
77 // The width passed in here includes the full width of the menu, so we need
78 // to omit the necessary padding.
79 const views::MenuConfig
& menu_config
=
80 static_cast<const views::MenuItemView
*>(parent())->GetMenuConfig();
81 int end_padding
= menu_config
.arrow_to_edge_padding
-
82 container_
->toolbar_actions_bar()->platform_settings().item_spacing
;
83 width
-= start_padding() + end_padding
;
85 return views::ScrollView::GetHeightForWidth(width
);
88 void ExtensionToolbarMenuView::Layout() {
89 SetPosition(gfx::Point(start_padding(), 0));
90 SizeToPreferredSize();
91 views::ScrollView::Layout();
94 void ExtensionToolbarMenuView::set_close_menu_delay_for_testing(int delay
) {
95 g_close_menu_delay
= delay
;
98 void ExtensionToolbarMenuView::OnBrowserActionDragDone() {
99 // We need to close the wrench menu if it was just opened for the drag and
100 // drop, or if there are no more extensions in the overflow menu after a drag
102 if (wrench_menu_
->for_drop() ||
103 container_
->toolbar_actions_bar()->GetIconCount() == 0) {
104 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
105 FROM_HERE
, base::Bind(&ExtensionToolbarMenuView::CloseWrenchMenu
,
106 weak_factory_
.GetWeakPtr()),
107 base::TimeDelta::FromMilliseconds(g_close_menu_delay
));
111 void ExtensionToolbarMenuView::CloseWrenchMenu() {
112 wrench_menu_
->CloseMenu();
115 int ExtensionToolbarMenuView::start_padding() const {
116 // We pad enough on the left so that the first icon starts at the same point
117 // as the labels. We subtract kItemSpacing because there needs to be padding
118 // so we can see the drop indicator.
119 return views::MenuItemView::label_start() -
120 container_
->toolbar_actions_bar()->platform_settings().item_spacing
;