diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-28 19:36:46 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-28 19:36:46 +0000 |
commit | d1ba5b511c94fb02b79ceae67a172d6bdb716e98 (patch) | |
tree | 23288e2b27f8513e76e5f22750f3166c92edaae5 /views | |
parent | d3038bf0175f75df75385a17298134a2ee39b8a1 (diff) | |
download | chromium_src-d1ba5b511c94fb02b79ceae67a172d6bdb716e98.zip chromium_src-d1ba5b511c94fb02b79ceae67a172d6bdb716e98.tar.gz chromium_src-d1ba5b511c94fb02b79ceae67a172d6bdb716e98.tar.bz2 |
Makes it so deleting a bookmark from the context menu doesn't close
the bookmark menu.
BUG=2469
TEST=click on a bookmark folder on the bookmark bar, right click on an
item and chose delete. Make sure the folder stays up and still works
correctly (and the item you deleted isn't there).
Review URL: http://codereview.chromium.org/551178
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37424 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/controls/menu/menu_controller.cc | 70 | ||||
-rw-r--r-- | views/controls/menu/menu_controller.h | 24 | ||||
-rw-r--r-- | views/controls/menu/menu_delegate.h | 9 | ||||
-rw-r--r-- | views/controls/menu/menu_item_view.cc | 14 | ||||
-rw-r--r-- | views/controls/menu/menu_item_view.h | 8 | ||||
-rw-r--r-- | views/controls/menu/submenu_view.cc | 4 | ||||
-rw-r--r-- | views/controls/menu/submenu_view.h | 3 |
7 files changed, 108 insertions, 24 deletions
diff --git a/views/controls/menu/menu_controller.cc b/views/controls/menu/menu_controller.cc index ef33bc7..fb35908 100644 --- a/views/controls/menu/menu_controller.cc +++ b/views/controls/menu/menu_controller.cc @@ -149,7 +149,7 @@ MenuItemView* MenuController::Run(gfx::NativeWindow parent, const gfx::Rect& bounds, MenuItemView::AnchorPosition position, int* result_mouse_event_flags) { - exit_all_ = false; + exit_type_ = EXIT_NONE; possible_drag_ = false; bool nested_menu = showing_; @@ -228,15 +228,18 @@ MenuItemView* MenuController::Run(gfx::NativeWindow parent, if (result_mouse_event_flags) *result_mouse_event_flags = result_mouse_event_flags_; - if (nested_menu && result) { - // We're nested and about to return a value. The caller might enter another - // blocking loop. We need to make sure all menus are hidden before that - // happens otherwise the menus will stay on screen. - CloseAllNestedMenus(); - - // Set exit_all_ to true, which makes sure all nested loops exit - // immediately. - exit_all_ = true; + if (exit_type_ == EXIT_OUTERMOST) { + exit_type_ = EXIT_NONE; + } else { + if (nested_menu && result) { + // We're nested and about to return a value. The caller might enter + // another blocking loop. We need to make sure all menus are hidden + // before that happens otherwise the menus will stay on screen. + CloseAllNestedMenus(); + + // Set exit_all_, which makes sure all nested loops exit immediately. + exit_type_ = EXIT_ALL; + } } if (menu_button_) { @@ -291,7 +294,7 @@ void MenuController::Cancel(bool all) { } MenuItemView* selected = state_.item; - exit_all_ = all; + exit_type_ = all ? EXIT_ALL : EXIT_OUTERMOST; // Hide windows immediately. SetSelection(NULL, false, true); @@ -605,7 +608,7 @@ int MenuController::OnPerformDrop(SubmenuView* source, // Set state such that we exit. showing_ = false; - exit_all_ = true; + exit_type_ = EXIT_ALL; if (!IsBlockingRun()) item->GetRootMenuItem()->DropMenuClosed(false); @@ -648,7 +651,7 @@ void MenuController::SetActiveInstance(MenuController* controller) { bool MenuController::Dispatch(const MSG& msg) { DCHECK(blocking_run_); - if (exit_all_) { + if (exit_type_ == EXIT_ALL) { // We must translate/dispatch the message here, otherwise we would drop // the message on the floor. TranslateMessage(&msg); @@ -697,14 +700,14 @@ bool MenuController::Dispatch(const MSG& msg) { } TranslateMessage(&msg); DispatchMessage(&msg); - return !exit_all_; + return exit_type_ == EXIT_NONE; } #else bool MenuController::Dispatch(GdkEvent* event) { gtk_main_do_event(event); - if (exit_all_) + if (exit_type_ == EXIT_ALL) return false; switch (event->type) { @@ -721,7 +724,7 @@ bool MenuController::Dispatch(GdkEvent* event) { break; } - return !exit_all_; + return exit_type_ == EXIT_NONE; } #endif @@ -799,7 +802,7 @@ bool MenuController::OnKeyDown(int key_code MenuController::MenuController(bool blocking) : blocking_run_(blocking), showing_(false), - exit_all_(false), + exit_type_(EXIT_NONE), did_capture_(false), result_(NULL), result_mouse_event_flags_(0), @@ -845,7 +848,12 @@ void MenuController::UpdateInitialLocation( void MenuController::Accept(MenuItemView* item, int mouse_event_flags) { DCHECK(IsBlockingRun()); result_ = item; - exit_all_ = true; + if (item && !menu_stack_.empty() && + !item->GetDelegate()->ShouldCloseAllMenusOnExecute(item->GetCommand())) { + exit_type_ = EXIT_OUTERMOST; + } else { + exit_type_ = EXIT_ALL; + } result_mouse_event_flags_ = mouse_event_flags; } @@ -1114,6 +1122,11 @@ void MenuController::OpenMenu(MenuItemView* item) { return; } + OpenMenuImpl(item, true); + did_capture_ = true; +} + +void MenuController::OpenMenuImpl(MenuItemView* item, bool show) { bool prefer_leading = state_.open_leading.empty() ? true : state_.open_leading.back(); bool resulting_direction; @@ -1122,9 +1135,26 @@ void MenuController::OpenMenu(MenuItemView* item) { state_.open_leading.push_back(resulting_direction); bool do_capture = (!did_capture_ && blocking_run_); showing_submenu_ = true; - item->GetSubmenu()->ShowAt(owner_, bounds, do_capture); + if (show) + item->GetSubmenu()->ShowAt(owner_, bounds, do_capture); + else + item->GetSubmenu()->Reposition(bounds); showing_submenu_ = false; - did_capture_ = true; +} + +void MenuController::MenuChildrenChanged(MenuItemView* item) { + DCHECK(item); + DCHECK(item->GetSubmenu()->IsShowing()); + + // Currently this only supports adjusting the bounds of the last menu. + DCHECK(item == state_.item->GetParentMenuItem()); + + // Make sure the submenu isn't showing for the current item (the position may + // have changed or the menu removed). This also moves the selection back to + // the parent, which handles the case where the selected item was removed. + SetSelection(state_.item->GetParentMenuItem(), true, true); + + OpenMenuImpl(item, false); } void MenuController::BuildPathsAndCalculateDiff( diff --git a/views/controls/menu/menu_controller.h b/views/controls/menu/menu_controller.h index 2ef1bb7..c92f4b9 100644 --- a/views/controls/menu/menu_controller.h +++ b/views/controls/menu/menu_controller.h @@ -98,6 +98,18 @@ class MenuController : public MessageLoopForUI::Dispatcher { void OnDragExitedScrollButton(SubmenuView* source); private: + // Enumeration of how the menu should exit. + enum ExitType { + // Don't exit. + EXIT_NONE, + + // All menus, including nested, should be exited. + EXIT_ALL, + + // Only the outermost menu should be exited. + EXIT_OUTERMOST + }; + class MenuScrollTask; // Tracks selection information. @@ -243,6 +255,14 @@ class MenuController : public MessageLoopForUI::Dispatcher { // in anyway. void OpenMenu(MenuItemView* item); + // Implementation of OpenMenu. If |show| is true, this invokes show on the + // menu, otherwise Reposition is invoked. + void OpenMenuImpl(MenuItemView* item, bool show); + + // Invoked when the children of a menu change and the menu is showing. + // This closes any submenus and resizes the submenu. + void MenuChildrenChanged(MenuItemView* item); + // Builds the paths of the two menu items into the two paths, and // sets first_diff_at to the location of the first difference between the // two paths. @@ -317,8 +337,8 @@ class MenuController : public MessageLoopForUI::Dispatcher { // If true, we're showing. bool showing_; - // If true, all nested run loops should be exited. - bool exit_all_; + // Indicates what to exit. + ExitType exit_type_; // Whether we did a capture. We do a capture only if we're blocking and // the mouse was down when Run. diff --git a/views/controls/menu/menu_delegate.h b/views/controls/menu/menu_delegate.h index cb06f21..cbb295a 100644 --- a/views/controls/menu/menu_delegate.h +++ b/views/controls/menu/menu_delegate.h @@ -84,6 +84,15 @@ class MenuDelegate : Controller { virtual void ExecuteCommand(int id) { } + // If nested menus are showing (nested menus occur when a menu shows a context + // menu) this is invoked to determine if all the menus should be closed when + // the user selects the menu with the command |id|. This returns true to + // indicate that all menus should be closed. Return false if only the + // context menu should be closed. + virtual bool ShouldCloseAllMenusOnExecute(int id) { + return true; + } + // Executes the specified command. mouse_event_flags give the flags of the // mouse event that triggered this to be invoked (views::MouseEvent // flags). mouse_event_flags is 0 if this is triggered by a user gesture diff --git a/views/controls/menu/menu_item_view.cc b/views/controls/menu/menu_item_view.cc index 5e92186..698502b 100644 --- a/views/controls/menu/menu_item_view.cc +++ b/views/controls/menu/menu_item_view.cc @@ -233,6 +233,20 @@ MenuItemView* MenuItemView::GetMenuItemByID(int id) { return NULL; } +void MenuItemView::ChildrenChanged() { + MenuController* controller = GetMenuController(); + if (!controller) + return; // We're not showing, nothing to do. + + // Handles the case where we were empty and are no longer empty. + RemoveEmptyMenus(); + + // Handles the case where we were not empty, but now are. + AddEmptyMenus(); + + controller->MenuChildrenChanged(this); +} + MenuItemView::MenuItemView(MenuItemView* parent, int command, MenuItemView::Type type) { diff --git a/views/controls/menu/menu_item_view.h b/views/controls/menu/menu_item_view.h index c528671..936ff1e 100644 --- a/views/controls/menu/menu_item_view.h +++ b/views/controls/menu/menu_item_view.h @@ -221,6 +221,10 @@ class MenuItemView : public View { // Returns the descendant with the specified command. MenuItemView* GetMenuItemByID(int id); + // Invoke if you remove/add children to the menu while it's showing. This + // recalculates the bounds. + void ChildrenChanged(); + protected: // Creates a MenuItemView. This is used by the various AddXXX methods. MenuItemView(MenuItemView* parent, int command, Type type); @@ -255,8 +259,8 @@ class MenuItemView : public View { int GetDrawStringFlags(); // If this menu item has no children a child is added showing it has no - // children. Otherwise AddEmtpyMenuIfNecessary is recursively invoked on - // child menu items that have children. + // children. Otherwise AddEmtpyMenus is recursively invoked on child menu + // items that have children. void AddEmptyMenus(); // Undoes the work of AddEmptyMenus. diff --git a/views/controls/menu/submenu_view.cc b/views/controls/menu/submenu_view.cc index b6ca627..0170e0c 100644 --- a/views/controls/menu/submenu_view.cc +++ b/views/controls/menu/submenu_view.cc @@ -234,6 +234,10 @@ void SubmenuView::ShowAt(gfx::NativeWindow parent, host_->Init(parent, bounds, scroll_view_container_, do_capture); } +void SubmenuView::Reposition(const gfx::Rect& bounds) { + host_->SetBounds(bounds); +} + void SubmenuView::Close() { if (host_) { host_->Close(); diff --git a/views/controls/menu/submenu_view.h b/views/controls/menu/submenu_view.h index 8cc4461..1e82f73 100644 --- a/views/controls/menu/submenu_view.h +++ b/views/controls/menu/submenu_view.h @@ -76,6 +76,9 @@ class SubmenuView : public View { // coordinates. max_width gives the max width the view should be. void ShowAt(gfx::NativeWindow parent, const gfx::Rect& bounds, bool do_capture); + // Resets the bounds of the submenu to |bounds|. + void Reposition(const gfx::Rect& bounds); + // Closes the menu, destroying the host. void Close(); |