summaryrefslogtreecommitdiffstats
path: root/views/controls/menu
diff options
context:
space:
mode:
authorrhashimoto@chromium.org <rhashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-24 19:41:38 +0000
committerrhashimoto@chromium.org <rhashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-24 19:41:38 +0000
commitbc019c5e8f7a3d63f745389f52b730c02e603a75 (patch)
tree513e1fcc368ef7361da55e48d8165f305404fbf7 /views/controls/menu
parent5ed0ff0966c516f76552c49dfc426e157b335b3e (diff)
downloadchromium_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.cc29
-rw-r--r--views/controls/menu/menu_item_view.cc10
-rw-r--r--views/controls/menu/menu_item_view.h29
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);
};