Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/controls/menu/menu_controller.h" | 5 #include "ui/views/controls/menu/menu_controller.h" |
| 6 | 6 |
| 7 #include "base/i18n/case_conversion.h" | 7 #include "base/i18n/case_conversion.h" |
| 8 #include "base/i18n/rtl.h" | 8 #include "base/i18n/rtl.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 } | 107 } |
| 108 | 108 |
| 109 for (int i = 0; i < view->child_count(); ++i) { | 109 for (int i = 0; i < view->child_count(); ++i) { |
| 110 CustomButton* hot_view = GetFirstHotTrackedView(view->child_at(i)); | 110 CustomButton* hot_view = GetFirstHotTrackedView(view->child_at(i)); |
| 111 if (hot_view) | 111 if (hot_view) |
| 112 return hot_view; | 112 return hot_view; |
| 113 } | 113 } |
| 114 return NULL; | 114 return NULL; |
| 115 } | 115 } |
| 116 | 116 |
| 117 CustomButton* OtherHotTrackedButton(View* view, CustomButton* button_hot) { | |
| 118 if (!view) | |
| 119 return nullptr; | |
| 120 CustomButton* button = CustomButton::AsCustomButton(view); | |
| 121 if (button && button != button_hot && button->IsHotTracked()) | |
| 122 return button; | |
| 123 | |
| 124 for (int i = 0; i < view->child_count(); ++i) { | |
| 125 button = OtherHotTrackedButton(view->child_at(i), button_hot); | |
| 126 if (button) | |
| 127 return button; | |
| 128 } | |
| 129 return nullptr; | |
| 130 } | |
| 131 | |
| 117 // Recurses through the child views of |view| returning the first view starting | 132 // Recurses through the child views of |view| returning the first view starting |
| 118 // at |start| that is focusable. A value of -1 for |start| indicates to start at | 133 // at |start| that is focusable. A value of -1 for |start| indicates to start at |
| 119 // the first view (if |forward| is false, iterating starts at the last view). If | 134 // the first view (if |forward| is false, iterating starts at the last view). If |
| 120 // |forward| is true the children are considered first to last, otherwise last | 135 // |forward| is true the children are considered first to last, otherwise last |
| 121 // to first. | 136 // to first. |
| 122 static View* GetFirstFocusableView(View* view, int start, bool forward) { | 137 static View* GetFirstFocusableView(View* view, int start, bool forward) { |
| 123 if (forward) { | 138 if (forward) { |
| 124 for (int i = start == -1 ? 0 : start; i < view->child_count(); ++i) { | 139 for (int i = start == -1 ? 0 : start; i < view->child_count(); ++i) { |
| 125 View* deepest = GetFirstFocusableView(view->child_at(i), -1, forward); | 140 View* deepest = GetFirstFocusableView(view->child_at(i), -1, forward); |
| 126 if (deepest) | 141 if (deepest) |
| (...skipping 805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 932 BuildPathsAndCalculateDiff(pending_state_.item, menu_item, ¤t_path, | 947 BuildPathsAndCalculateDiff(pending_state_.item, menu_item, ¤t_path, |
| 933 &new_path, &paths_differ_at); | 948 &new_path, &paths_differ_at); |
| 934 | 949 |
| 935 size_t current_size = current_path.size(); | 950 size_t current_size = current_path.size(); |
| 936 size_t new_size = new_path.size(); | 951 size_t new_size = new_path.size(); |
| 937 | 952 |
| 938 bool pending_item_changed = pending_state_.item != menu_item; | 953 bool pending_item_changed = pending_state_.item != menu_item; |
| 939 if (pending_item_changed && pending_state_.item) { | 954 if (pending_item_changed && pending_state_.item) { |
| 940 CustomButton* button = GetFirstHotTrackedView(pending_state_.item); | 955 CustomButton* button = GetFirstHotTrackedView(pending_state_.item); |
| 941 if (button) | 956 if (button) |
| 942 button->SetHotTracked(false); | 957 SetHotTrackedButton(button, false); |
| 958 } | |
| 959 CustomButton* new_hot_button = OtherHotTrackedButton(menu_item, hot_button_); | |
| 960 if (new_hot_button) { | |
| 961 if (hot_button_) | |
| 962 SetHotTrackedButton(hot_button_, false); | |
| 963 SetHotTrackedButton(new_hot_button, true); | |
| 943 } | 964 } |
| 944 | 965 |
| 945 // Notify the old path it isn't selected. | 966 // Notify the old path it isn't selected. |
| 946 MenuDelegate* current_delegate = | 967 MenuDelegate* current_delegate = |
| 947 current_path.empty() ? NULL : current_path.front()->GetDelegate(); | 968 current_path.empty() ? NULL : current_path.front()->GetDelegate(); |
| 948 for (size_t i = paths_differ_at; i < current_size; ++i) { | 969 for (size_t i = paths_differ_at; i < current_size; ++i) { |
| 949 if (current_delegate && | 970 if (current_delegate && |
| 950 current_path[i]->GetType() == MenuItemView::SUBMENU) { | 971 current_path[i]->GetType() == MenuItemView::SUBMENU) { |
| 951 current_delegate->WillHideMenu(current_path[i]); | 972 current_delegate->WillHideMenu(current_path[i]); |
| 952 } | 973 } |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1184 drop_target_(NULL), | 1205 drop_target_(NULL), |
| 1185 drop_position_(MenuDelegate::DROP_UNKNOWN), | 1206 drop_position_(MenuDelegate::DROP_UNKNOWN), |
| 1186 owner_(NULL), | 1207 owner_(NULL), |
| 1187 possible_drag_(false), | 1208 possible_drag_(false), |
| 1188 drag_in_progress_(false), | 1209 drag_in_progress_(false), |
| 1189 did_initiate_drag_(false), | 1210 did_initiate_drag_(false), |
| 1190 valid_drop_coordinates_(false), | 1211 valid_drop_coordinates_(false), |
| 1191 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), | 1212 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), |
| 1192 showing_submenu_(false), | 1213 showing_submenu_(false), |
| 1193 active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()), | 1214 active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()), |
| 1215 hot_button_(nullptr), | |
| 1194 delegate_(delegate), | 1216 delegate_(delegate), |
| 1195 message_loop_depth_(0), | 1217 message_loop_depth_(0), |
| 1196 closing_event_time_(base::TimeDelta()), | 1218 closing_event_time_(base::TimeDelta()), |
| 1197 menu_start_time_(base::TimeTicks()), | 1219 menu_start_time_(base::TimeTicks()), |
| 1198 async_run_(false), | 1220 async_run_(false), |
| 1199 is_combobox_(false), | 1221 is_combobox_(false), |
| 1200 item_selected_by_touch_(false), | 1222 item_selected_by_touch_(false), |
| 1201 current_mouse_event_target_(nullptr), | 1223 current_mouse_event_target_(nullptr), |
| 1202 current_mouse_pressed_state_(0), | 1224 current_mouse_pressed_state_(0), |
| 1203 message_loop_(MenuMessageLoop::Create()) { | 1225 message_loop_(MenuMessageLoop::Create()) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1219 message_loop_->Run(this, owner_, nested_menu); | 1241 message_loop_->Run(this, owner_, nested_menu); |
| 1220 } | 1242 } |
| 1221 | 1243 |
| 1222 bool MenuController::SendAcceleratorToHotTrackedView() { | 1244 bool MenuController::SendAcceleratorToHotTrackedView() { |
| 1223 CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item); | 1245 CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item); |
| 1224 if (!hot_view) | 1246 if (!hot_view) |
| 1225 return false; | 1247 return false; |
| 1226 | 1248 |
| 1227 ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE); | 1249 ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE); |
| 1228 hot_view->AcceleratorPressed(accelerator); | 1250 hot_view->AcceleratorPressed(accelerator); |
| 1229 CustomButton* button = static_cast<CustomButton*>(hot_view); | 1251 SetHotTrackedButton(hot_view, true); |
| 1230 button->SetHotTracked(true); | |
| 1231 return true; | 1252 return true; |
| 1232 } | 1253 } |
| 1233 | 1254 |
| 1234 void MenuController::UpdateInitialLocation(const gfx::Rect& bounds, | 1255 void MenuController::UpdateInitialLocation(const gfx::Rect& bounds, |
| 1235 MenuAnchorPosition position, | 1256 MenuAnchorPosition position, |
| 1236 bool context_menu) { | 1257 bool context_menu) { |
| 1237 pending_state_.context_menu = context_menu; | 1258 pending_state_.context_menu = context_menu; |
| 1238 pending_state_.initial_bounds = bounds; | 1259 pending_state_.initial_bounds = bounds; |
| 1239 if (bounds.height() > 1) { | 1260 if (bounds.height() > 1) { |
| 1240 // Inset the bounds slightly, otherwise drag coordinates don't line up | 1261 // Inset the bounds slightly, otherwise drag coordinates don't line up |
| (...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1982 void MenuController::IncrementSelection( | 2003 void MenuController::IncrementSelection( |
| 1983 SelectionIncrementDirectionType direction) { | 2004 SelectionIncrementDirectionType direction) { |
| 1984 MenuItemView* item = pending_state_.item; | 2005 MenuItemView* item = pending_state_.item; |
| 1985 DCHECK(item); | 2006 DCHECK(item); |
| 1986 if (pending_state_.submenu_open && item->HasSubmenu() && | 2007 if (pending_state_.submenu_open && item->HasSubmenu() && |
| 1987 item->GetSubmenu()->IsShowing()) { | 2008 item->GetSubmenu()->IsShowing()) { |
| 1988 // A menu is selected and open, but none of its children are selected, | 2009 // A menu is selected and open, but none of its children are selected, |
| 1989 // select the first menu item that is visible and enabled. | 2010 // select the first menu item that is visible and enabled. |
| 1990 if (item->GetSubmenu()->GetMenuItemCount()) { | 2011 if (item->GetSubmenu()->GetMenuItemCount()) { |
| 1991 MenuItemView* to_select = FindInitialSelectableMenuItem(item, direction); | 2012 MenuItemView* to_select = FindInitialSelectableMenuItem(item, direction); |
| 1992 if (to_select) | 2013 SetInitialHotTrackedView(to_select, direction); |
| 1993 SetSelection(to_select, SELECTION_DEFAULT); | |
| 1994 return; | 2014 return; |
| 1995 } | 2015 } |
| 1996 } | 2016 } |
| 1997 | 2017 |
| 1998 if (item->has_children()) { | 2018 if (item->has_children()) { |
| 1999 CustomButton* button = GetFirstHotTrackedView(item); | 2019 CustomButton* button = GetFirstHotTrackedView(item); |
| 2000 if (button) { | 2020 if (button) { |
| 2001 button->SetHotTracked(false); | 2021 SetHotTrackedButton(button, false); |
| 2002 View* to_make_hot = GetNextFocusableView( | 2022 View* to_make_hot = GetNextFocusableView( |
| 2003 item, button, direction == INCREMENT_SELECTION_DOWN); | 2023 item, button, direction == INCREMENT_SELECTION_DOWN); |
| 2004 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); | 2024 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); |
| 2005 if (button_hot) { | 2025 if (button_hot) { |
| 2006 button_hot->SetHotTracked(true); | 2026 SetHotTrackedButton(button_hot, true); |
| 2007 return; | 2027 return; |
| 2008 } | 2028 } |
| 2009 } else { | 2029 } else { |
| 2010 View* to_make_hot = | 2030 View* to_make_hot = |
| 2011 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN); | 2031 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN); |
| 2012 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); | 2032 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); |
| 2013 if (button_hot) { | 2033 if (button_hot) { |
| 2014 button_hot->SetHotTracked(true); | 2034 SetHotTrackedButton(button_hot, true); |
| 2015 return; | 2035 return; |
| 2016 } | 2036 } |
| 2017 } | 2037 } |
| 2018 } | 2038 } |
| 2019 | 2039 |
| 2020 MenuItemView* parent = item->GetParentMenuItem(); | 2040 MenuItemView* parent = item->GetParentMenuItem(); |
| 2021 if (parent) { | 2041 if (parent) { |
| 2022 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); | 2042 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); |
| 2023 if (parent_count > 1) { | 2043 if (parent_count > 1) { |
| 2024 for (int i = 0; i < parent_count; ++i) { | 2044 for (int i = 0; i < parent_count; ++i) { |
| 2025 if (parent->GetSubmenu()->GetMenuItemAt(i) == item) { | 2045 if (parent->GetSubmenu()->GetMenuItemAt(i) == item) { |
| 2026 MenuItemView* to_select = | 2046 MenuItemView* to_select = |
| 2027 FindNextSelectableMenuItem(parent, i, direction); | 2047 FindNextSelectableMenuItem(parent, i, direction); |
| 2028 if (!to_select) | 2048 SetInitialHotTrackedView(to_select, direction); |
| 2029 break; | |
| 2030 SetSelection(to_select, SELECTION_DEFAULT); | |
| 2031 View* to_make_hot = GetInitialFocusableView( | |
| 2032 to_select, direction == INCREMENT_SELECTION_DOWN); | |
| 2033 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); | |
| 2034 if (button_hot) | |
| 2035 button_hot->SetHotTracked(true); | |
| 2036 break; | 2049 break; |
| 2037 } | 2050 } |
| 2038 } | 2051 } |
| 2039 } | 2052 } |
| 2040 } | 2053 } |
| 2041 } | 2054 } |
| 2042 | 2055 |
| 2043 MenuItemView* MenuController::FindInitialSelectableMenuItem( | 2056 MenuItemView* MenuController::FindInitialSelectableMenuItem( |
| 2044 MenuItemView* parent, | 2057 MenuItemView* parent, |
| 2045 SelectionIncrementDirectionType direction) { | 2058 SelectionIncrementDirectionType direction) { |
| (...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2590 pending_state_.item->GetParentMenuItem() && | 2603 pending_state_.item->GetParentMenuItem() && |
| 2591 (!pending_state_.item->HasSubmenu() || | 2604 (!pending_state_.item->HasSubmenu() || |
| 2592 !pending_state_.item->GetSubmenu()->IsShowing())) { | 2605 !pending_state_.item->GetSubmenu()->IsShowing())) { |
| 2593 // On exit if the user hasn't selected an item with a submenu, move the | 2606 // On exit if the user hasn't selected an item with a submenu, move the |
| 2594 // selection back to the parent menu item. | 2607 // selection back to the parent menu item. |
| 2595 SetSelection(pending_state_.item->GetParentMenuItem(), | 2608 SetSelection(pending_state_.item->GetParentMenuItem(), |
| 2596 SELECTION_OPEN_SUBMENU); | 2609 SELECTION_OPEN_SUBMENU); |
| 2597 } | 2610 } |
| 2598 } | 2611 } |
| 2599 | 2612 |
| 2613 void MenuController::SetHotTrackedButton(CustomButton* hot_button, | |
| 2614 bool is_hot_tracked) { | |
| 2615 DCHECK(hot_button); | |
| 2616 hot_button->SetHotTracked(is_hot_tracked); | |
| 2617 if (is_hot_tracked) | |
| 2618 hot_button_ = hot_button; | |
| 2619 else if (hot_button_ == hot_button) | |
| 2620 hot_button_ = nullptr; | |
| 2621 else | |
| 2622 NOTREACHED(); | |
|
Peter Kasting
2016/02/06 02:51:12
Nit: Simpler:
DCHECK(is_hot_tracked || (hot_but
varkha
2016/02/16 19:59:44
Done.
| |
| 2623 } | |
| 2624 | |
| 2625 void MenuController::SetInitialHotTrackedView( | |
| 2626 MenuItemView* item, | |
| 2627 SelectionIncrementDirectionType direction) { | |
| 2628 if (!item) | |
| 2629 return; | |
| 2630 SetSelection(item, SELECTION_DEFAULT); | |
| 2631 View* to_make_hot = | |
|
Peter Kasting
2016/02/06 02:51:13
Nit: |hot_view| is shorter and, to me, less awkwar
varkha
2016/02/16 19:59:44
Done.
| |
| 2632 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN); | |
| 2633 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); | |
|
Peter Kasting
2016/02/06 02:51:12
Nit: Use |hot_button| for consistency with previou
varkha
2016/02/16 19:59:44
Done.
| |
| 2634 if (button_hot) | |
| 2635 SetHotTrackedButton(button_hot, true); | |
| 2636 return; | |
| 2637 } | |
| 2638 | |
| 2600 } // namespace views | 2639 } // namespace views |
| OLD | NEW |