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 |