summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfinnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-27 04:55:57 +0000
committerfinnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-27 04:55:57 +0000
commite578e76354f5838edb54dc1d9457561030002123 (patch)
treec13ba5657921756bed0a167aa56edbec68730823
parent7d767625372cad11adca0789531753bd56e40e0e (diff)
downloadchromium_src-e578e76354f5838edb54dc1d9457561030002123.zip
chromium_src-e578e76354f5838edb54dc1d9457561030002123.tar.gz
chromium_src-e578e76354f5838edb54dc1d9457561030002123.tar.bz2
Add overflow menu to the browser action container (part 2 of
supporting resize for the container). Also improved RTL support a bit (the divider wasn't drawn on the right side of the container and resizing was reversed). BUG=32101 TEST=Overflow menu for browser action container should now work. Make sure to test also right-clicking on a menu item in the overflow menu to bring up a context menu for that item. And resizing the container in RTL locales should work. Review URL: http://codereview.chromium.org/557006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37232 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/views/browser_actions_container.cc54
-rw-r--r--chrome/browser/views/browser_actions_container.h10
-rw-r--r--chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc82
-rw-r--r--chrome/browser/views/extensions/browser_action_overflow_menu_controller.h63
-rw-r--r--chrome/browser/views/extensions/extension_action_context_menu.cc5
-rw-r--r--chrome/browser/views/extensions/extension_action_context_menu.h3
-rwxr-xr-xchrome/chrome_browser.gypi8
-rw-r--r--views/controls/resize_gripper.cc22
-rw-r--r--views/controls/resize_gripper.h10
9 files changed, 228 insertions, 29 deletions
diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc
index 6aaa387..02c213a 100644
--- a/chrome/browser/views/browser_actions_container.cc
+++ b/chrome/browser/views/browser_actions_container.cc
@@ -19,6 +19,7 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/view_ids.h"
#include "chrome/browser/views/detachable_toolbar_view.h"
+#include "chrome/browser/views/extensions/browser_action_overflow_menu_controller.h"
#include "chrome/browser/views/extensions/extension_popup.h"
#include "chrome/browser/views/toolbar_view.h"
#include "chrome/common/notification_source.h"
@@ -30,6 +31,7 @@
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "views/controls/button/menu_button.h"
#include "views/controls/button/text_button.h"
+#include "views/window/window.h"
#include "grit/theme_resources.h"
@@ -311,6 +313,7 @@ BrowserActionsContainer::BrowserActionsContainer(
}
BrowserActionsContainer::~BrowserActionsContainer() {
+ CloseOverflowMenu();
HidePopup();
DeleteBrowserActionViews();
}
@@ -357,11 +360,7 @@ void BrowserActionsContainer::AddBrowserAction(Extension* extension) {
return;
// Before we change anything, determine the number of visible browser actions.
- size_t visible_actions = 0;
- for (size_t i = 0; i < browser_action_views_.size(); ++i) {
- if (browser_action_views_[i]->IsVisible())
- ++visible_actions;
- }
+ size_t visible_actions = VisibleBrowserActions();
// Add the new browser action to the vector and the view hierarchy.
BrowserActionView* view = new BrowserActionView(extension, this);
@@ -401,11 +400,7 @@ void BrowserActionsContainer::RemoveBrowserAction(Extension* extension) {
}
// Before we change anything, determine the number of visible browser actions.
- int visible_actions = 0;
- for (size_t i = 0; i < browser_action_views_.size(); ++i) {
- if (browser_action_views_[i]->IsVisible())
- ++visible_actions;
- }
+ int visible_actions = VisibleBrowserActions();
for (std::vector<BrowserActionView*>::iterator iter =
browser_action_views_.begin(); iter != browser_action_views_.end();
@@ -435,6 +430,12 @@ void BrowserActionsContainer::RemoveBrowserAction(Extension* extension) {
}
}
+void BrowserActionsContainer::CloseOverflowMenu() {
+ // Close the overflow menu if open (and the context menu off of that).
+ if (overflow_menu_.get())
+ overflow_menu_->CancelMenu();
+}
+
void BrowserActionsContainer::DeleteBrowserActionViews() {
if (!browser_action_views_.empty()) {
for (size_t i = 0; i < browser_action_views_.size(); ++i)
@@ -495,9 +496,13 @@ void BrowserActionsContainer::OnBrowserActionExecuted(
if (same_showing)
return;
+ // We can get the execute event for browser actions that are not visible,
+ // since buttons can be activated from the overflow menu (chevron). In that
+ // case we show the popup as originating from the chevron.
+ View* reference_view = button->GetParent()->IsVisible() ? button : chevron_;
gfx::Point origin;
- View::ConvertPointToScreen(button, &origin);
- gfx::Rect rect = button->bounds();
+ View::ConvertPointToScreen(reference_view, &origin);
+ gfx::Rect rect = reference_view->bounds();
rect.set_x(origin.x());
rect.set_y(origin.y());
@@ -603,10 +608,11 @@ void BrowserActionsContainer::Layout() {
}
void BrowserActionsContainer::Paint(gfx::Canvas* canvas) {
- // The one pixel themed vertical divider to the right of the browser actions.
+ // The one-pixel themed vertical divider to the right of the browser actions.
+ int x = UILayoutIsRightToLeft() ? kDividerHorizontalMargin :
+ width() - kDividerHorizontalMargin;
DetachableToolbarView::PaintVerticalDivider(
- canvas,
- width() - kDividerHorizontalMargin, height(), kDividerVerticalPadding,
+ canvas, x, height(), kDividerVerticalPadding,
DetachableToolbarView::kEdgeDividerColor,
DetachableToolbarView::kMiddleDividerColor,
GetThemeProvider()->GetColor(BrowserThemeProvider::COLOR_TOOLBAR));
@@ -632,12 +638,14 @@ void BrowserActionsContainer::Observe(NotificationType type,
const NotificationDetails& details) {
switch (type.value) {
case NotificationType::EXTENSION_LOADED:
+ CloseOverflowMenu();
AddBrowserAction(Details<Extension>(details).ptr());
OnBrowserActionVisibilityChanged();
break;
case NotificationType::EXTENSION_UNLOADED:
case NotificationType::EXTENSION_UNLOADED_DISABLED:
+ CloseOverflowMenu();
RemoveBrowserAction(Details<Extension>(details).ptr());
OnBrowserActionVisibilityChanged();
break;
@@ -698,7 +706,11 @@ void BrowserActionsContainer::BubbleLostFocus(BrowserBubble* bubble,
}
void BrowserActionsContainer::RunMenu(View* source, const gfx::Point& pt) {
- // TODO(finnur): Show menu for all the hidden icons.
+ if (source == chevron_) {
+ overflow_menu_.reset(new BrowserActionOverflowMenuController(
+ this, chevron_, browser_action_views_, VisibleBrowserActions()));
+ overflow_menu_->RunMenu(GetWindow()->GetNativeWindow());
+ }
}
int BrowserActionsContainer::ClampToNearestIconCount(int pixelWidth) const {
@@ -758,6 +770,16 @@ int BrowserActionsContainer::ContainerMinSize() const {
return resize_gripper_->width() + chevron_->width() + kChevronRightMargin;
}
+size_t BrowserActionsContainer::VisibleBrowserActions() const {
+ size_t visible_actions = 0;
+ for (size_t i = 0; i < browser_action_views_.size(); ++i) {
+ if (browser_action_views_[i]->IsVisible())
+ ++visible_actions;
+ }
+
+ return visible_actions;
+}
+
void BrowserActionsContainer::OnResize(int resize_amount, bool done_resizing) {
if (!done_resizing) {
resize_amount_ = resize_amount;
diff --git a/chrome/browser/views/browser_actions_container.h b/chrome/browser/views/browser_actions_container.h
index d2b87a4..c668965 100644
--- a/chrome/browser/views/browser_actions_container.h
+++ b/chrome/browser/views/browser_actions_container.h
@@ -19,6 +19,7 @@
#include "views/view.h"
class BrowserActionsContainer;
+class BrowserActionOverflowMenuController;
class Extension;
class ExtensionAction;
class ExtensionPopup;
@@ -303,6 +304,9 @@ class BrowserActionsContainer
// no such view.
void RemoveBrowserAction(Extension* extension);
+ // Closes the overflow menu if open.
+ void CloseOverflowMenu();
+
// Takes a width in pixels, calculates how many icons fit within that space
// (up to the maximum number of icons in our vector) and shaves off the
// excess pixels.
@@ -321,6 +325,9 @@ class BrowserActionsContainer
// all the padding that we normally show if there are icons.
int ContainerMinSize() const;
+ // Returns how many browser actions are visible.
+ size_t VisibleBrowserActions() const;
+
// The vector of browser actions (icons/image buttons for each action).
std::vector<BrowserActionView*> browser_action_views_;
@@ -347,6 +354,9 @@ class BrowserActionsContainer
// The chevron for accessing the overflow items.
views::MenuButton* chevron_;
+ // The menu to show for the overflow button (chevron).
+ scoped_ptr<BrowserActionOverflowMenuController> overflow_menu_;
+
// The animation that happens when the container snaps to place.
scoped_ptr<SlideAnimation> resize_animation_;
diff --git a/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc b/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc
new file mode 100644
index 0000000..66b209c
--- /dev/null
+++ b/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2010 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/views/extensions/browser_action_overflow_menu_controller.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/views/browser_actions_container.h"
+#include "chrome/common/extensions/extension.h"
+#include "views/controls/menu/menu_item_view.h"
+
+BrowserActionOverflowMenuController::BrowserActionOverflowMenuController(
+ BrowserActionsContainer* owner,
+ views::MenuButton* menu_button,
+ const std::vector<BrowserActionView*>& views,
+ int start_index)
+ : owner_(owner),
+ menu_button_(menu_button),
+ views_(&views),
+ start_index_(start_index) {
+ menu_.reset(new views::MenuItemView(this));
+ menu_->set_has_icons(true);
+
+ TabContents* tab = BrowserList::GetLastActive()->GetSelectedTabContents();
+ int tab_id = tab->controller().session_id().id();
+
+ size_t command_id = 0;
+ for (size_t i = start_index; i < views_->size(); ++i) {
+ BrowserActionView* view = (*views_)[i];
+ menu_->AppendMenuItemWithIcon(
+ command_id,
+ UTF8ToWide(view->button()->extension()->name()),
+ view->button()->extension()->browser_action()->GetIcon(tab_id));
+ ++command_id;
+ }
+}
+
+BrowserActionOverflowMenuController::~BrowserActionOverflowMenuController() {
+}
+
+bool BrowserActionOverflowMenuController::RunMenu(gfx::NativeWindow window) {
+ gfx::Rect bounds = menu_button_->GetBounds(
+ views::View::IGNORE_MIRRORING_TRANSFORMATION);
+ gfx::Point screen_loc;
+ views::View::ConvertPointToScreen(menu_button_, &screen_loc);
+ bounds.set_x(screen_loc.x());
+ bounds.set_y(screen_loc.y());
+
+ views::MenuItemView::AnchorPosition anchor =
+ menu_button_->UILayoutIsRightToLeft() ? views::MenuItemView::TOPRIGHT :
+ views::MenuItemView::TOPLEFT;
+ menu_->RunMenuAt(window, menu_button_, bounds, anchor, false);
+ return true;
+}
+
+void BrowserActionOverflowMenuController::CancelMenu() {
+ if (context_menu_.get())
+ context_menu_->Cancel();
+ menu_->Cancel();
+}
+
+void BrowserActionOverflowMenuController::ExecuteCommand(int id) {
+ BrowserActionView* view = (*views_)[start_index_ + id];
+ owner_->OnBrowserActionExecuted(view->button());
+}
+
+bool BrowserActionOverflowMenuController::ShowContextMenu(
+ views::MenuItemView* source, int id, int x, int y, bool is_mouse_gesture) {
+ if (!context_menu_.get())
+ context_menu_.reset(new ExtensionActionContextMenu());
+ // This blocks until the user choses something or dismisses.
+ context_menu_->Run((*views_)[start_index_ + id]->button()->extension(),
+ gfx::Point(x, y));
+
+ // The user is done with the context menu, so we can close the underlying
+ // menu.
+ menu_->Cancel();
+
+ return true;
+}
diff --git a/chrome/browser/views/extensions/browser_action_overflow_menu_controller.h b/chrome/browser/views/extensions/browser_action_overflow_menu_controller.h
new file mode 100644
index 0000000..02950a4
--- /dev/null
+++ b/chrome/browser/views/extensions/browser_action_overflow_menu_controller.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 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_VIEWS_EXTENSIONS_BROWSER_ACTION_OVERFLOW_MENU_CONTROLLER_H_
+#define CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_OVERFLOW_MENU_CONTROLLER_H_
+
+#include <vector>
+
+#include "views/controls/menu/menu_delegate.h"
+
+class BrowserActionsContainer;
+class BrowserActionView;
+class ExtensionActionContextMenu;
+
+class BrowserActionOverflowMenuController : public views::MenuDelegate {
+ public:
+ BrowserActionOverflowMenuController(
+ BrowserActionsContainer* owner,
+ views::MenuButton* menu_button,
+ const std::vector<BrowserActionView*>& views,
+ int start_index);
+ virtual ~BrowserActionOverflowMenuController();
+
+ // Shows the overflow menu.
+ bool RunMenu(gfx::NativeWindow window);
+
+ // Closes the overflow menu (and its context menu if open as well).
+ void CancelMenu();
+
+ // Overridden from views::MenuDelegate:
+ virtual void ExecuteCommand(int id);
+ virtual bool ShowContextMenu(views::MenuItemView* source,
+ int id,
+ int x,
+ int y,
+ bool is_mouse_gesture);
+
+ private:
+ // A pointer to the browser action container that owns the overflow menu.
+ BrowserActionsContainer* owner_;
+
+ // A pointer to the overflow menu button that we are showing the menu for.
+ views::MenuButton* menu_button_;
+
+ // The overflow menu for the menu button.
+ scoped_ptr<views::MenuItemView> menu_;
+
+ // The context menu (when you right click a menu item in the overflow menu).
+ scoped_ptr<ExtensionActionContextMenu> context_menu_;
+
+ // The views vector of all the browser actions the container knows about. We
+ // won't show all items, just the one starting at |start_index| and above.
+ const std::vector<BrowserActionView*>* views_;
+
+ // The index into the BrowserActionView vector, indicating where to start
+ // picking browser actions to draw.
+ int start_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserActionOverflowMenuController);
+};
+
+#endif // CHROME_BROWSER_VIEWS_EXTENSIONS_BROWSER_ACTION_OVERFLOW_MENU_CONTROLLER_H_
diff --git a/chrome/browser/views/extensions/extension_action_context_menu.cc b/chrome/browser/views/extensions/extension_action_context_menu.cc
index 47927fc..eafdf5c 100644
--- a/chrome/browser/views/extensions/extension_action_context_menu.cc
+++ b/chrome/browser/views/extensions/extension_action_context_menu.cc
@@ -25,3 +25,8 @@ void ExtensionActionContextMenu::Run(Extension* extension,
context_menu_menu_.reset(new views::Menu2(context_menu_contents_.get()));
context_menu_menu_->RunContextMenuAt(point);
}
+
+void ExtensionActionContextMenu::Cancel() {
+ if (context_menu_menu_.get())
+ context_menu_menu_->CancelMenu();
+}
diff --git a/chrome/browser/views/extensions/extension_action_context_menu.h b/chrome/browser/views/extensions/extension_action_context_menu.h
index 25d1949..5340a389 100644
--- a/chrome/browser/views/extensions/extension_action_context_menu.h
+++ b/chrome/browser/views/extensions/extension_action_context_menu.h
@@ -20,6 +20,9 @@ class ExtensionActionContextMenu {
// Display the context menu at a given point.
void Run(Extension* extension, const gfx::Point& point);
+ // Closes the context menu if open.
+ void Cancel();
+
private:
// The options menu.
scoped_ptr<ExtensionActionContextMenuModel> context_menu_contents_;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 791c46d..a0a4565 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -697,14 +697,14 @@
'browser/download/save_types.h',
'browser/encoding_menu_controller.cc',
'browser/encoding_menu_controller.h',
- 'browser/extensions/extension_action_context_menu_model.cc',
- 'browser/extensions/extension_action_context_menu_model.h',
'browser/extensions/convert_user_script.cc',
'browser/extensions/convert_user_script.h',
'browser/extensions/crashed_extension_infobar.cc',
'browser/extensions/crashed_extension_infobar.h',
'browser/extensions/crx_installer.cc',
'browser/extensions/crx_installer.h',
+ 'browser/extensions/extension_action_context_menu_model.cc',
+ 'browser/extensions/extension_action_context_menu_model.h',
'browser/extensions/extension_bookmarks_module.cc',
'browser/extensions/extension_bookmarks_module.h',
'browser/extensions/extension_bookmarks_module_constants.cc',
@@ -1709,6 +1709,8 @@
'browser/views/edit_search_engine_dialog.h',
'browser/views/event_utils.cc',
'browser/views/event_utils.h',
+ 'browser/views/extensions/browser_action_overflow_menu_controller.cc',
+ 'browser/views/extensions/browser_action_overflow_menu_controller.h',
'browser/views/extensions/extension_action_context_menu.cc',
'browser/views/extensions/extension_action_context_menu.h',
'browser/views/extensions/extension_install_prompt.cc',
@@ -2256,6 +2258,8 @@
['include', '^browser/views/dropdown_bar_view.h'],
['include', '^browser/views/event_utils.cc'],
['include', '^browser/views/event_utils.h'],
+ ['include', '^browser/views/extensions/browser_action_overflow_menu_controller.cc'],
+ ['include', '^browser/views/extensions/browser_action_overflow_menu_controller.h'],
['include', '^browser/views/extensions/extension_action_context_menu.cc'],
['include', '^browser/views/extensions/extension_action_context_menu.h'],
['include', '^browser/views/extensions/extension_install_prompt.cc'],
diff --git a/views/controls/resize_gripper.cc b/views/controls/resize_gripper.cc
index f443f33..59a13aa 100644
--- a/views/controls/resize_gripper.cc
+++ b/views/controls/resize_gripper.cc
@@ -64,22 +64,26 @@ bool ResizeGripper::OnMouseDragged(const views::MouseEvent& event) {
if (!event.IsLeftMouseButton())
return false;
- gfx::Point point(event.x(), 0);
- View::ConvertPointToScreen(this, &point);
-
- delegate_->OnResize(point.x() - initial_position_, false);
+ ReportResizeAmount(event.x(), false);
return true;
}
void ResizeGripper::OnMouseReleased(const views::MouseEvent& event,
bool canceled) {
- gfx::Point point(event.x(), 0);
- View::ConvertPointToScreen(this, &point);
-
if (canceled)
- delegate_->OnResize(0, true);
+ ReportResizeAmount(initial_position_, true);
else
- delegate_->OnResize(point.x() - initial_position_, true);
+ ReportResizeAmount(event.x(), true);
+}
+
+void ResizeGripper::ReportResizeAmount(int resize_amount, bool last_update) {
+ gfx::Point point(resize_amount, 0);
+ View::ConvertPointToScreen(this, &point);
+ resize_amount = point.x() - initial_position_;
+
+ if (UILayoutIsRightToLeft())
+ resize_amount = -1 * resize_amount;
+ delegate_->OnResize(resize_amount, last_update);
}
} // namespace views
diff --git a/views/controls/resize_gripper.h b/views/controls/resize_gripper.h
index 1b65066..204aa9f 100644
--- a/views/controls/resize_gripper.h
+++ b/views/controls/resize_gripper.h
@@ -27,8 +27,10 @@ class ResizeGripper : public ImageView {
public:
// OnResize is sent when resizing is detected. |resize_amount| specifies the
// number of pixels that the user wants to resize by, and can be negative or
- // positive (depending on direction of dragging). |done_resizing| is
- // true if the user has released the mouse.
+ // positive (depending on direction of dragging and flips according to
+ // locale directionality: dragging to the left in LTR locales gives negative
+ // |resize_amount| but positive amount for RTL). |done_resizing| is true if
+ // the user has released the mouse.
virtual void OnResize(int resize_amount, bool done_resizing) = 0;
};
@@ -46,6 +48,10 @@ class ResizeGripper : public ImageView {
static const char kViewClassName[];
private:
+ // Report the amount the user resized by to the delegate, accounting for
+ // directionality.
+ void ReportResizeAmount(int resize_amount, bool last_update);
+
// The delegate to notify when we have updates.
ResizeGripperDelegate* delegate_;