diff options
author | rhashimoto@chromium.org <rhashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-24 19:41:38 +0000 |
---|---|---|
committer | rhashimoto@chromium.org <rhashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-24 19:41:38 +0000 |
commit | bc019c5e8f7a3d63f745389f52b730c02e603a75 (patch) | |
tree | 513e1fcc368ef7361da55e48d8165f305404fbf7 /views/controls/menu | |
parent | 5ed0ff0966c516f76552c49dfc426e157b335b3e (diff) | |
download | chromium_src-bc019c5e8f7a3d63f745389f52b730c02e603a75.zip chromium_src-bc019c5e8f7a3d63f745389f52b730c02e603a75.tar.gz chromium_src-bc019c5e8f7a3d63f745389f52b730c02e603a75.tar.bz2 |
Add MenuItemView API to control menu repositioning.
The use case for this is the ChromiumOS OOBE network menu. This menu is dynamic - access points may be added or removed while the menu is open so the number of items in the menu can change. At a certain threshold, the menu will "hop" between above and below the button. This CL provides a way to disable repositioning so the menu is always displayed below the button.
BUG=chromium-os:16720
TEST=open OOBE network menu with a lot of WiFi access points around, check that the menu is drawn below the button
Review URL: http://codereview.chromium.org/7217026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90410 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/controls/menu')
-rw-r--r-- | views/controls/menu/menu_controller.cc | 29 | ||||
-rw-r--r-- | views/controls/menu/menu_item_view.cc | 10 | ||||
-rw-r--r-- | views/controls/menu/menu_item_view.h | 29 |
3 files changed, 59 insertions, 9 deletions
diff --git a/views/controls/menu/menu_controller.cc b/views/controls/menu/menu_controller.cc index e1b38aa..c1e8d2a 100644 --- a/views/controls/menu/menu_controller.cc +++ b/views/controls/menu/menu_controller.cc @@ -1460,19 +1460,36 @@ gfx::Rect MenuController::CalculateMenuBounds(MenuItemView* item, x = x + state_.initial_bounds.width() - pref.width(); if (!state_.monitor_bounds.IsEmpty() && y + pref.height() > state_.monitor_bounds.bottom()) { - // The menu doesn't fit on screen. If the first location is above the - // half way point, show from the mouse location to bottom of screen. - // Otherwise show from the top of the screen to the location of the mouse. - // While odd, this behavior matches IE. - if (y < (state_.monitor_bounds.y() + - state_.monitor_bounds.height() / 2)) { + // The menu doesn't fit on screen. The menu position with + // respect to the bounds will be preserved if it has already + // been drawn. On the first drawing if the first location is + // above the half way point then show from the mouse location to + // bottom of screen, otherwise show from the top of the screen + // to the location of the mouse. While odd, this behavior + // matches IE. + if (item->actual_menu_position() == MenuItemView::POSITION_BELOW_BOUNDS || + (item->actual_menu_position() == MenuItemView::POSITION_BEST_FIT && + y < (state_.monitor_bounds.y() + + state_.monitor_bounds.height() / 2))) { pref.set_height(std::min(pref.height(), state_.monitor_bounds.bottom() - y)); + item->set_actual_menu_position(MenuItemView::POSITION_BELOW_BOUNDS); } else { pref.set_height(std::min(pref.height(), state_.initial_bounds.y() - state_.monitor_bounds.y())); y = state_.initial_bounds.y() - pref.height(); + item->set_actual_menu_position(MenuItemView::POSITION_ABOVE_BOUNDS); } + } else if (item->actual_menu_position() == + MenuItemView::POSITION_ABOVE_BOUNDS) { + // The menu would fit below the bounds, but it has already been + // drawn above so keep it there. + pref.set_height(std::min(pref.height(), + state_.initial_bounds.y() - state_.monitor_bounds.y())); + y = state_.initial_bounds.y() - pref.height(); + item->set_actual_menu_position(MenuItemView::POSITION_ABOVE_BOUNDS); + } else { + item->set_actual_menu_position(MenuItemView::POSITION_BELOW_BOUNDS); } } else { // Not the first menu; position it relative to the bounds of the menu diff --git a/views/controls/menu/menu_item_view.cc b/views/controls/menu/menu_item_view.cc index beee1b3..2e82569a 100644 --- a/views/controls/menu/menu_item_view.cc +++ b/views/controls/menu/menu_item_view.cc @@ -92,7 +92,9 @@ MenuItemView::MenuItemView(MenuDelegate* delegate) show_mnemonics_(false), has_icons_(false), top_margin_(-1), - bottom_margin_(-1) { + bottom_margin_(-1), + requested_menu_position_(POSITION_BEST_FIT), + actual_menu_position_(requested_menu_position_) { // NOTE: don't check the delegate for NULL, UpdateMenuPartSizes supplies a // NULL delegate. Init(NULL, 0, SUBMENU, delegate); @@ -513,7 +515,9 @@ MenuItemView::MenuItemView(MenuItemView* parent, show_mnemonics_(false), has_icons_(false), top_margin_(-1), - bottom_margin_(-1) { + bottom_margin_(-1), + requested_menu_position_(POSITION_BEST_FIT), + actual_menu_position_(requested_menu_position_) { Init(parent, command, type, NULL); } @@ -594,7 +598,7 @@ void MenuItemView::PrepareForRun(bool has_mnemonics, bool show_mnemonics) { // Force us to have a submenu. CreateSubmenu(); - + actual_menu_position_ = requested_menu_position_; canceled_ = false; has_mnemonics_ = has_mnemonics; diff --git a/views/controls/menu/menu_item_view.h b/views/controls/menu/menu_item_view.h index f24dadd4..9f5c9b3 100644 --- a/views/controls/menu/menu_item_view.h +++ b/views/controls/menu/menu_item_view.h @@ -97,6 +97,16 @@ class MenuItemView : public View { TOPRIGHT }; + // Where the menu should be drawn, above or below the bounds (when + // the bounds is non-empty). POSITION_BEST_FIT (default) positions + // the menu below the bounds unless the menu does not fit on the + // screen and the re is more space above. + enum MenuPosition { + POSITION_BEST_FIT, + POSITION_ABOVE_BOUNDS, + POSITION_BELOW_BOUNDS + }; + // Constructor for use with the top level menu item. This menu is never // shown to the user, rather its use as the parent for all menu items. explicit MenuItemView(MenuDelegate* delegate); @@ -317,6 +327,12 @@ class MenuItemView : public View { bottom_margin_ = bottom_margin; } + // Set the position of the menu with respect to the bounds (top + // level only). + void set_menu_position(MenuPosition menu_position) { + requested_menu_position_ = menu_position; + } + protected: // Creates a MenuItemView. This is used by the various AddXXX methods. MenuItemView(MenuItemView* parent, int command, Type type); @@ -396,6 +412,13 @@ class MenuItemView : public View { // Calculates the preferred size. gfx::Size CalculatePreferredSize(); + // Used by MenuController to cache the menu position in use by the + // active menu. + MenuPosition actual_menu_position() const { return actual_menu_position_; } + void set_actual_menu_position(MenuPosition actual_menu_position) { + actual_menu_position_ = actual_menu_position; + } + // The delegate. This is only valid for the root menu item. You shouldn't // use this directly, instead use GetDelegate() which walks the tree as // as necessary. @@ -465,6 +488,12 @@ class MenuItemView : public View { int top_margin_; int bottom_margin_; + // |menu_position_| is the requested position with respect to the bounds. + // |actual_menu_position_| is used by the controller to cache the + // position of the menu being shown. + MenuPosition requested_menu_position_; + MenuPosition actual_menu_position_; + DISALLOW_COPY_AND_ASSIGN(MenuItemView); }; |