| 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 |