| 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 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1889 pref.height() / 2 - y + y_old); | 1889 pref.height() / 2 - y + y_old); |
| 1890 } | 1890 } |
| 1891 return gfx::Rect(x, y, pref.width(), pref.height()); | 1891 return gfx::Rect(x, y, pref.width(), pref.height()); |
| 1892 } | 1892 } |
| 1893 | 1893 |
| 1894 // static | 1894 // static |
| 1895 int MenuController::MenuDepth(MenuItemView* item) { | 1895 int MenuController::MenuDepth(MenuItemView* item) { |
| 1896 return item ? (MenuDepth(item->GetParentMenuItem()) + 1) : 0; | 1896 return item ? (MenuDepth(item->GetParentMenuItem()) + 1) : 0; |
| 1897 } | 1897 } |
| 1898 | 1898 |
| 1899 void MenuController::IncrementSelection(int delta) { | 1899 void MenuController::IncrementSelection( |
| 1900 SelectionIncrementDirectionType direction) { |
| 1900 MenuItemView* item = pending_state_.item; | 1901 MenuItemView* item = pending_state_.item; |
| 1901 DCHECK(item); | 1902 DCHECK(item); |
| 1902 if (pending_state_.submenu_open && item->HasSubmenu() && | 1903 if (pending_state_.submenu_open && item->HasSubmenu() && |
| 1903 item->GetSubmenu()->IsShowing()) { | 1904 item->GetSubmenu()->IsShowing()) { |
| 1904 // A menu is selected and open, but none of its children are selected, | 1905 // A menu is selected and open, but none of its children are selected, |
| 1905 // select the first menu item that is visible and enabled. | 1906 // select the first menu item that is visible and enabled. |
| 1906 if (item->GetSubmenu()->GetMenuItemCount()) { | 1907 if (item->GetSubmenu()->GetMenuItemCount()) { |
| 1907 MenuItemView* to_select = FindFirstSelectableMenuItem(item); | 1908 MenuItemView* to_select = FindInitialSelectableMenuItem(item, direction); |
| 1908 if (to_select) | 1909 if (to_select) |
| 1909 SetSelection(to_select, SELECTION_DEFAULT); | 1910 SetSelection(to_select, SELECTION_DEFAULT); |
| 1910 return; | 1911 return; |
| 1911 } | 1912 } |
| 1912 } | 1913 } |
| 1913 | 1914 |
| 1914 if (item->has_children()) { | 1915 if (item->has_children()) { |
| 1915 CustomButton* button = GetFirstHotTrackedView(item); | 1916 CustomButton* button = GetFirstHotTrackedView(item); |
| 1916 if (button) { | 1917 if (button) { |
| 1917 button->SetHotTracked(false); | 1918 button->SetHotTracked(false); |
| 1918 View* to_make_hot = GetNextFocusableView(item, button, delta == 1); | 1919 View* to_make_hot = GetNextFocusableView( |
| 1920 item, button, direction == INCREMENT_SELECTION_DOWN); |
| 1919 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); | 1921 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); |
| 1920 if (button_hot) { | 1922 if (button_hot) { |
| 1921 button_hot->SetHotTracked(true); | 1923 button_hot->SetHotTracked(true); |
| 1922 return; | 1924 return; |
| 1923 } | 1925 } |
| 1924 } else { | 1926 } else { |
| 1925 View* to_make_hot = GetInitialFocusableView(item, delta == 1); | 1927 View* to_make_hot = |
| 1928 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN); |
| 1926 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); | 1929 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); |
| 1927 if (button_hot) { | 1930 if (button_hot) { |
| 1928 button_hot->SetHotTracked(true); | 1931 button_hot->SetHotTracked(true); |
| 1929 return; | 1932 return; |
| 1930 } | 1933 } |
| 1931 } | 1934 } |
| 1932 } | 1935 } |
| 1933 | 1936 |
| 1934 MenuItemView* parent = item->GetParentMenuItem(); | 1937 MenuItemView* parent = item->GetParentMenuItem(); |
| 1935 if (parent) { | 1938 if (parent) { |
| 1936 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); | 1939 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); |
| 1937 if (parent_count > 1) { | 1940 if (parent_count > 1) { |
| 1938 for (int i = 0; i < parent_count; ++i) { | 1941 for (int i = 0; i < parent_count; ++i) { |
| 1939 if (parent->GetSubmenu()->GetMenuItemAt(i) == item) { | 1942 if (parent->GetSubmenu()->GetMenuItemAt(i) == item) { |
| 1940 MenuItemView* to_select = | 1943 MenuItemView* to_select = |
| 1941 FindNextSelectableMenuItem(parent, i, delta); | 1944 FindNextSelectableMenuItem(parent, i, direction); |
| 1942 if (!to_select) | 1945 if (!to_select) |
| 1943 break; | 1946 break; |
| 1944 SetSelection(to_select, SELECTION_DEFAULT); | 1947 SetSelection(to_select, SELECTION_DEFAULT); |
| 1945 View* to_make_hot = GetInitialFocusableView(to_select, delta == 1); | 1948 View* to_make_hot = GetInitialFocusableView( |
| 1949 to_select, direction == INCREMENT_SELECTION_DOWN); |
| 1946 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); | 1950 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); |
| 1947 if (button_hot) | 1951 if (button_hot) |
| 1948 button_hot->SetHotTracked(true); | 1952 button_hot->SetHotTracked(true); |
| 1949 break; | 1953 break; |
| 1950 } | 1954 } |
| 1951 } | 1955 } |
| 1952 } | 1956 } |
| 1953 } | 1957 } |
| 1954 } | 1958 } |
| 1955 | 1959 |
| 1956 MenuItemView* MenuController::FindFirstSelectableMenuItem( | 1960 MenuItemView* MenuController::FindInitialSelectableMenuItem( |
| 1957 MenuItemView* parent) { | 1961 MenuItemView* parent, |
| 1958 MenuItemView* child = parent->GetSubmenu()->GetMenuItemAt(0); | 1962 SelectionIncrementDirectionType direction) { |
| 1959 if (!child->visible() || !child->enabled()) | 1963 return FindNextSelectableMenuItem( |
| 1960 child = FindNextSelectableMenuItem(parent, 0, 1); | 1964 parent, direction == INCREMENT_SELECTION_DOWN ? -1 : 0, direction); |
| 1961 return child; | |
| 1962 } | 1965 } |
| 1963 | 1966 |
| 1964 MenuItemView* MenuController::FindNextSelectableMenuItem(MenuItemView* parent, | 1967 MenuItemView* MenuController::FindNextSelectableMenuItem( |
| 1965 int index, | 1968 MenuItemView* parent, |
| 1966 int delta) { | 1969 int index, |
| 1967 int start_index = index; | 1970 SelectionIncrementDirectionType direction) { |
| 1968 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); | 1971 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); |
| 1972 int stop_index = (index + parent_count) % parent_count; |
| 1973 bool include_all_items = |
| 1974 (index == -1 && direction == INCREMENT_SELECTION_DOWN) || |
| 1975 (index == 0 && direction == INCREMENT_SELECTION_UP); |
| 1976 int delta = direction == INCREMENT_SELECTION_UP ? -1 : 1; |
| 1969 // Loop through the menu items skipping any invisible menus. The loop stops | 1977 // Loop through the menu items skipping any invisible menus. The loop stops |
| 1970 // when we wrap or find a visible and enabled child. | 1978 // when we wrap or find a visible and enabled child. |
| 1971 do { | 1979 do { |
| 1972 index = (index + delta + parent_count) % parent_count; | 1980 index = (index + delta + parent_count) % parent_count; |
| 1973 if (index == start_index) | 1981 if (index == stop_index && !include_all_items) |
| 1974 return NULL; | 1982 return NULL; |
| 1975 MenuItemView* child = parent->GetSubmenu()->GetMenuItemAt(index); | 1983 MenuItemView* child = parent->GetSubmenu()->GetMenuItemAt(index); |
| 1976 if (child->visible() && child->enabled()) | 1984 if (child->visible() && child->enabled()) |
| 1977 return child; | 1985 return child; |
| 1978 } while (index != start_index); | 1986 } while (index != stop_index); |
| 1979 return NULL; | 1987 return NULL; |
| 1980 } | 1988 } |
| 1981 | 1989 |
| 1982 void MenuController::OpenSubmenuChangeSelectionIfCan() { | 1990 void MenuController::OpenSubmenuChangeSelectionIfCan() { |
| 1983 MenuItemView* item = pending_state_.item; | 1991 MenuItemView* item = pending_state_.item; |
| 1984 if (!item->HasSubmenu() || !item->enabled()) | 1992 if (!item->HasSubmenu() || !item->enabled()) |
| 1985 return; | 1993 return; |
| 1986 MenuItemView* to_select = NULL; | 1994 MenuItemView* to_select = NULL; |
| 1987 if (item->GetSubmenu()->GetMenuItemCount() > 0) | 1995 if (item->GetSubmenu()->GetMenuItemCount() > 0) |
| 1988 to_select = FindFirstSelectableMenuItem(item); | 1996 to_select = FindInitialSelectableMenuItem(item, INCREMENT_SELECTION_DOWN); |
| 1989 if (to_select) { | 1997 if (to_select) { |
| 1990 SetSelection(to_select, SELECTION_UPDATE_IMMEDIATELY); | 1998 SetSelection(to_select, SELECTION_UPDATE_IMMEDIATELY); |
| 1991 return; | 1999 return; |
| 1992 } | 2000 } |
| 1993 // No menu items, just show the sub-menu. | 2001 // No menu items, just show the sub-menu. |
| 1994 SetSelection(item, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); | 2002 SetSelection(item, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); |
| 1995 } | 2003 } |
| 1996 | 2004 |
| 1997 void MenuController::CloseSubmenu() { | 2005 void MenuController::CloseSubmenu() { |
| 1998 MenuItemView* item = state_.item; | 2006 MenuItemView* item = state_.item; |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2357 } | 2365 } |
| 2358 } | 2366 } |
| 2359 | 2367 |
| 2360 gfx::Screen* MenuController::GetScreen() { | 2368 gfx::Screen* MenuController::GetScreen() { |
| 2361 Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL; | 2369 Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL; |
| 2362 return root ? gfx::Screen::GetScreenFor(root->GetNativeView()) | 2370 return root ? gfx::Screen::GetScreenFor(root->GetNativeView()) |
| 2363 : gfx::Screen::GetNativeScreen(); | 2371 : gfx::Screen::GetNativeScreen(); |
| 2364 } | 2372 } |
| 2365 | 2373 |
| 2366 } // namespace views | 2374 } // namespace views |
| OLD | NEW |