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/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 // Returns true if |menu| doesn't have a mnemonic and first character of the its | 82 // Returns true if |menu| doesn't have a mnemonic and first character of the its |
83 // title is |key|. | 83 // title is |key|. |
84 bool TitleMatchesMnemonic(MenuItemView* menu, base::char16 key) { | 84 bool TitleMatchesMnemonic(MenuItemView* menu, base::char16 key) { |
85 if (menu->GetMnemonic()) | 85 if (menu->GetMnemonic()) |
86 return false; | 86 return false; |
87 | 87 |
88 base::string16 lower_title = base::i18n::ToLower(menu->title()); | 88 base::string16 lower_title = base::i18n::ToLower(menu->title()); |
89 return !lower_title.empty() && lower_title[0] == key; | 89 return !lower_title.empty() && lower_title[0] == key; |
90 } | 90 } |
91 | 91 |
92 } // namespace | |
93 | |
94 // Returns the first descendant of |view| that is hot tracked. | 92 // Returns the first descendant of |view| that is hot tracked. |
95 static CustomButton* GetFirstHotTrackedView(View* view) { | 93 static CustomButton* GetFirstHotTrackedView(View* view) { |
96 if (!view) | 94 if (!view) |
97 return NULL; | 95 return NULL; |
98 CustomButton* button = CustomButton::AsCustomButton(view); | 96 CustomButton* button = CustomButton::AsCustomButton(view); |
99 if (button) { | 97 if (button) { |
100 if (button->IsHotTracked()) | 98 if (button->IsHotTracked()) |
101 return button; | 99 return button; |
102 } | 100 } |
103 | 101 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 if (forward || index != -1) { | 148 if (forward || index != -1) { |
151 View* next = GetFirstFocusableView(new_parent, index, forward); | 149 View* next = GetFirstFocusableView(new_parent, index, forward); |
152 if (next) | 150 if (next) |
153 return next; | 151 return next; |
154 } | 152 } |
155 parent = new_parent; | 153 parent = new_parent; |
156 } while (parent != ancestor); | 154 } while (parent != ancestor); |
157 return NULL; | 155 return NULL; |
158 } | 156 } |
159 | 157 |
| 158 } // namespace |
| 159 |
160 // MenuScrollTask -------------------------------------------------------------- | 160 // MenuScrollTask -------------------------------------------------------------- |
161 | 161 |
162 // MenuScrollTask is used when the SubmenuView does not all fit on screen and | 162 // MenuScrollTask is used when the SubmenuView does not all fit on screen and |
163 // the mouse is over the scroll up/down buttons. MenuScrollTask schedules | 163 // the mouse is over the scroll up/down buttons. MenuScrollTask schedules |
164 // itself with a RepeatingTimer. When Run is invoked MenuScrollTask scrolls | 164 // itself with a RepeatingTimer. When Run is invoked MenuScrollTask scrolls |
165 // appropriately. | 165 // appropriately. |
166 | 166 |
167 class MenuController::MenuScrollTask { | 167 class MenuController::MenuScrollTask { |
168 public: | 168 public: |
169 MenuScrollTask() : submenu_(NULL), is_scrolling_up_(false), start_y_(0) { | 169 MenuScrollTask() : submenu_(NULL), is_scrolling_up_(false), start_y_(0) { |
(...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 item->GetWidget()->RunShellDrag(NULL, data, widget_loc, drag_ops, | 1021 item->GetWidget()->RunShellDrag(NULL, data, widget_loc, drag_ops, |
1022 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE); | 1022 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE); |
1023 did_initiate_drag_ = false; | 1023 did_initiate_drag_ = false; |
1024 } | 1024 } |
1025 | 1025 |
1026 bool MenuController::OnKeyDown(ui::KeyboardCode key_code) { | 1026 bool MenuController::OnKeyDown(ui::KeyboardCode key_code) { |
1027 DCHECK(blocking_run_); | 1027 DCHECK(blocking_run_); |
1028 | 1028 |
1029 switch (key_code) { | 1029 switch (key_code) { |
1030 case ui::VKEY_UP: | 1030 case ui::VKEY_UP: |
1031 IncrementSelection(-1); | 1031 IncrementSelection(INCREMENT_SELECTION_UP); |
1032 break; | 1032 break; |
1033 | 1033 |
1034 case ui::VKEY_DOWN: | 1034 case ui::VKEY_DOWN: |
1035 IncrementSelection(1); | 1035 IncrementSelection(INCREMENT_SELECTION_DOWN); |
1036 break; | 1036 break; |
1037 | 1037 |
1038 // Handling of VK_RIGHT and VK_LEFT is different depending on the UI | 1038 // Handling of VK_RIGHT and VK_LEFT is different depending on the UI |
1039 // layout. | 1039 // layout. |
1040 case ui::VKEY_RIGHT: | 1040 case ui::VKEY_RIGHT: |
1041 if (base::i18n::IsRTL()) | 1041 if (base::i18n::IsRTL()) |
1042 CloseSubmenu(); | 1042 CloseSubmenu(); |
1043 else | 1043 else |
1044 OpenSubmenuChangeSelectionIfCan(); | 1044 OpenSubmenuChangeSelectionIfCan(); |
1045 break; | 1045 break; |
(...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1896 pref.height() / 2 - y + y_old); | 1896 pref.height() / 2 - y + y_old); |
1897 } | 1897 } |
1898 return gfx::Rect(x, y, pref.width(), pref.height()); | 1898 return gfx::Rect(x, y, pref.width(), pref.height()); |
1899 } | 1899 } |
1900 | 1900 |
1901 // static | 1901 // static |
1902 int MenuController::MenuDepth(MenuItemView* item) { | 1902 int MenuController::MenuDepth(MenuItemView* item) { |
1903 return item ? (MenuDepth(item->GetParentMenuItem()) + 1) : 0; | 1903 return item ? (MenuDepth(item->GetParentMenuItem()) + 1) : 0; |
1904 } | 1904 } |
1905 | 1905 |
1906 void MenuController::IncrementSelection(int delta) { | 1906 void MenuController::IncrementSelection( |
| 1907 SelectionIncrementDirectionType direction) { |
1907 MenuItemView* item = pending_state_.item; | 1908 MenuItemView* item = pending_state_.item; |
1908 DCHECK(item); | 1909 DCHECK(item); |
1909 if (pending_state_.submenu_open && item->HasSubmenu() && | 1910 if (pending_state_.submenu_open && item->HasSubmenu() && |
1910 item->GetSubmenu()->IsShowing()) { | 1911 item->GetSubmenu()->IsShowing()) { |
1911 // A menu is selected and open, but none of its children are selected, | 1912 // A menu is selected and open, but none of its children are selected, |
1912 // select the first menu item that is visible and enabled. | 1913 // select the first menu item that is visible and enabled. |
1913 if (item->GetSubmenu()->GetMenuItemCount()) { | 1914 if (item->GetSubmenu()->GetMenuItemCount()) { |
1914 MenuItemView* to_select = FindFirstSelectableMenuItem(item); | 1915 MenuItemView* to_select = FindInitialSelectableMenuItem(item, direction); |
1915 if (to_select) | 1916 if (to_select) |
1916 SetSelection(to_select, SELECTION_DEFAULT); | 1917 SetSelection(to_select, SELECTION_DEFAULT); |
1917 return; | 1918 return; |
1918 } | 1919 } |
1919 } | 1920 } |
1920 | 1921 |
1921 if (item->has_children()) { | 1922 if (item->has_children()) { |
1922 CustomButton* button = GetFirstHotTrackedView(item); | 1923 CustomButton* button = GetFirstHotTrackedView(item); |
1923 if (button) { | 1924 if (button) { |
1924 button->SetHotTracked(false); | 1925 button->SetHotTracked(false); |
1925 View* to_make_hot = GetNextFocusableView(item, button, delta == 1); | 1926 View* to_make_hot = GetNextFocusableView( |
| 1927 item, button, direction == INCREMENT_SELECTION_DOWN); |
1926 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); | 1928 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); |
1927 if (button_hot) { | 1929 if (button_hot) { |
1928 button_hot->SetHotTracked(true); | 1930 button_hot->SetHotTracked(true); |
1929 return; | 1931 return; |
1930 } | 1932 } |
1931 } else { | 1933 } else { |
1932 View* to_make_hot = GetInitialFocusableView(item, delta == 1); | 1934 View* to_make_hot = |
| 1935 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN); |
1933 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); | 1936 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); |
1934 if (button_hot) { | 1937 if (button_hot) { |
1935 button_hot->SetHotTracked(true); | 1938 button_hot->SetHotTracked(true); |
1936 return; | 1939 return; |
1937 } | 1940 } |
1938 } | 1941 } |
1939 } | 1942 } |
1940 | 1943 |
1941 MenuItemView* parent = item->GetParentMenuItem(); | 1944 MenuItemView* parent = item->GetParentMenuItem(); |
1942 if (parent) { | 1945 if (parent) { |
1943 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); | 1946 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); |
1944 if (parent_count > 1) { | 1947 if (parent_count > 1) { |
1945 for (int i = 0; i < parent_count; ++i) { | 1948 for (int i = 0; i < parent_count; ++i) { |
1946 if (parent->GetSubmenu()->GetMenuItemAt(i) == item) { | 1949 if (parent->GetSubmenu()->GetMenuItemAt(i) == item) { |
1947 MenuItemView* to_select = | 1950 MenuItemView* to_select = |
1948 FindNextSelectableMenuItem(parent, i, delta); | 1951 FindNextSelectableMenuItem(parent, i, direction); |
1949 if (!to_select) | 1952 if (!to_select) |
1950 break; | 1953 break; |
1951 SetSelection(to_select, SELECTION_DEFAULT); | 1954 SetSelection(to_select, SELECTION_DEFAULT); |
1952 View* to_make_hot = GetInitialFocusableView(to_select, delta == 1); | 1955 View* to_make_hot = GetInitialFocusableView( |
| 1956 to_select, direction == INCREMENT_SELECTION_DOWN); |
1953 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); | 1957 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); |
1954 if (button_hot) | 1958 if (button_hot) |
1955 button_hot->SetHotTracked(true); | 1959 button_hot->SetHotTracked(true); |
1956 break; | 1960 break; |
1957 } | 1961 } |
1958 } | 1962 } |
1959 } | 1963 } |
1960 } | 1964 } |
1961 } | 1965 } |
1962 | 1966 |
1963 MenuItemView* MenuController::FindFirstSelectableMenuItem( | 1967 MenuItemView* MenuController::FindInitialSelectableMenuItem( |
1964 MenuItemView* parent) { | 1968 MenuItemView* parent, |
1965 MenuItemView* child = parent->GetSubmenu()->GetMenuItemAt(0); | 1969 SelectionIncrementDirectionType direction) { |
1966 if (!child->visible() || !child->enabled()) | 1970 return FindNextSelectableMenuItem( |
1967 child = FindNextSelectableMenuItem(parent, 0, 1); | 1971 parent, direction == INCREMENT_SELECTION_DOWN ? -1 : 0, direction); |
1968 return child; | |
1969 } | 1972 } |
1970 | 1973 |
1971 MenuItemView* MenuController::FindNextSelectableMenuItem(MenuItemView* parent, | 1974 MenuItemView* MenuController::FindNextSelectableMenuItem( |
1972 int index, | 1975 MenuItemView* parent, |
1973 int delta) { | 1976 int index, |
1974 int start_index = index; | 1977 SelectionIncrementDirectionType direction) { |
1975 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); | 1978 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); |
| 1979 int stop_index = (index + parent_count) % parent_count; |
| 1980 bool include_all_items = |
| 1981 (index == -1 && direction == INCREMENT_SELECTION_DOWN) || |
| 1982 (index == 0 && direction == INCREMENT_SELECTION_UP); |
| 1983 int delta = direction == INCREMENT_SELECTION_UP ? -1 : 1; |
1976 // Loop through the menu items skipping any invisible menus. The loop stops | 1984 // Loop through the menu items skipping any invisible menus. The loop stops |
1977 // when we wrap or find a visible and enabled child. | 1985 // when we wrap or find a visible and enabled child. |
1978 do { | 1986 do { |
1979 index = (index + delta + parent_count) % parent_count; | 1987 index = (index + delta + parent_count) % parent_count; |
1980 if (index == start_index) | 1988 if (index == stop_index && !include_all_items) |
1981 return NULL; | 1989 return NULL; |
1982 MenuItemView* child = parent->GetSubmenu()->GetMenuItemAt(index); | 1990 MenuItemView* child = parent->GetSubmenu()->GetMenuItemAt(index); |
1983 if (child->visible() && child->enabled()) | 1991 if (child->visible() && child->enabled()) |
1984 return child; | 1992 return child; |
1985 } while (index != start_index); | 1993 } while (index != stop_index); |
1986 return NULL; | 1994 return NULL; |
1987 } | 1995 } |
1988 | 1996 |
1989 void MenuController::OpenSubmenuChangeSelectionIfCan() { | 1997 void MenuController::OpenSubmenuChangeSelectionIfCan() { |
1990 MenuItemView* item = pending_state_.item; | 1998 MenuItemView* item = pending_state_.item; |
1991 if (!item->HasSubmenu() || !item->enabled()) | 1999 if (!item->HasSubmenu() || !item->enabled()) |
1992 return; | 2000 return; |
1993 MenuItemView* to_select = NULL; | 2001 MenuItemView* to_select = NULL; |
1994 if (item->GetSubmenu()->GetMenuItemCount() > 0) | 2002 if (item->GetSubmenu()->GetMenuItemCount() > 0) |
1995 to_select = FindFirstSelectableMenuItem(item); | 2003 to_select = FindInitialSelectableMenuItem(item, INCREMENT_SELECTION_DOWN); |
1996 if (to_select) { | 2004 if (to_select) { |
1997 SetSelection(to_select, SELECTION_UPDATE_IMMEDIATELY); | 2005 SetSelection(to_select, SELECTION_UPDATE_IMMEDIATELY); |
1998 return; | 2006 return; |
1999 } | 2007 } |
2000 // No menu items, just show the sub-menu. | 2008 // No menu items, just show the sub-menu. |
2001 SetSelection(item, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); | 2009 SetSelection(item, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); |
2002 } | 2010 } |
2003 | 2011 |
2004 void MenuController::CloseSubmenu() { | 2012 void MenuController::CloseSubmenu() { |
2005 MenuItemView* item = state_.item; | 2013 MenuItemView* item = state_.item; |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2364 } | 2372 } |
2365 } | 2373 } |
2366 | 2374 |
2367 gfx::Screen* MenuController::GetScreen() { | 2375 gfx::Screen* MenuController::GetScreen() { |
2368 Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL; | 2376 Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL; |
2369 return root ? gfx::Screen::GetScreenFor(root->GetNativeView()) | 2377 return root ? gfx::Screen::GetScreenFor(root->GetNativeView()) |
2370 : gfx::Screen::GetNativeScreen(); | 2378 : gfx::Screen::GetNativeScreen(); |
2371 } | 2379 } |
2372 | 2380 |
2373 } // namespace views | 2381 } // namespace views |
OLD | NEW |