Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(122)

Unified Diff: views/controls/menu/menu_controller.cc

Issue 2741004: Makes it so child views of menuitemview can be traversed with the (Closed)
Patch Set: Tweaks Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « views/controls/menu/menu_controller.h ('k') | views/controls/menu/menu_item_view.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: views/controls/menu/menu_controller.cc
diff --git a/views/controls/menu/menu_controller.cc b/views/controls/menu/menu_controller.cc
index 9005fd6117afbe7705d3468340966c55406fee7e..723f8bb8eb320d3fa07bc79aa42ba661a4e1a694 100644
--- a/views/controls/menu/menu_controller.cc
+++ b/views/controls/menu/menu_controller.cc
@@ -51,6 +51,73 @@ static void ScrollToVisible(View* view) {
view->ScrollRectToVisible(gfx::Rect(gfx::Point(), view->size()));
}
+// Returns the first descendant of |view| that is hot tracked.
+static View* GetFirstHotTrackedView(View* view) {
+ if (!view)
+ return NULL;
+
+ if (view->IsHotTracked())
+ return view;
+
+ for (int i = 0; i < view->GetChildViewCount(); ++i) {
+ View* hot_view = GetFirstHotTrackedView(view->GetChildViewAt(i));
+ if (hot_view)
+ return hot_view;
+ }
+ return NULL;
+}
+
+// Recurses through the child views of |view| returning the first view starting
+// at |start| that is focusable. A value of -1 for |start| indicates to start at
+// the first view (if |forward| is false, iterating starts at the last view). If
+// |forward| is true the children are considered first to last, otherwise last
+// to first.
+static View* GetFirstFocusableView(View* view, int start, bool forward) {
+ if (forward) {
+ for (int i = start == -1 ? 0 : start; i < view->GetChildViewCount(); ++i) {
+ View* deepest = GetFirstFocusableView(view->GetChildViewAt(i), -1,
+ forward);
Jay Civelli 2010/06/09 16:03:47 Nit: you could use true instead of forward.
+ if (deepest)
+ return deepest;
+ }
+ } else {
+ for (int i = start == -1 ? view->GetChildViewCount() - 1 : start;
+ i >= 0; --i) {
+ View* deepest = GetFirstFocusableView(view->GetChildViewAt(i), -1,
+ forward);
Jay Civelli 2010/06/09 16:03:47 Nit: you could use false instead of forward.
+ if (deepest)
+ return deepest;
+ }
+ }
+ return view->IsFocusable() ? view : NULL;
+}
+
+// Returns the first child of |start| that is focusable.
+static View* GetInitialFocusableView(View* start, bool forward) {
+ return GetFirstFocusableView(start, -1, forward);
+}
+
+// Returns the next view after |start_at| that is focusable. Returns NULL if
+// there are no focusable children of |ancestor| after |start_at|.
+static View* GetNextFocusableView(View* ancestor,
+ View* start_at,
+ bool forward) {
+ DCHECK(ancestor->IsParentOf(start_at));
+ View* parent = start_at;
+ do {
+ View* new_parent = parent->GetParent();
+ int index = new_parent->GetChildIndex(parent);
+ index += forward ? 1 : -1;
+ if (forward || index != -1) {
+ View* next = GetFirstFocusableView(new_parent, index, forward);
+ if (next)
+ return next;
+ }
+ parent = new_parent;
+ } while (parent != ancestor);
+ return NULL;
+}
+
// MenuScrollTask --------------------------------------------------------------
// MenuScrollTask is used when the SubmenuView does not all fit on screen and
@@ -275,6 +342,12 @@ void MenuController::SetSelection(MenuItemView* menu_item,
size_t current_size = current_path.size();
size_t new_size = new_path.size();
+ if (pending_state_.item != menu_item && pending_state_.item) {
+ View* current_hot_view = GetFirstHotTrackedView(pending_state_.item);
+ if (current_hot_view)
+ current_hot_view->SetHotTracked(false);
+ }
+
// Notify the old path it isn't selected.
for (size_t i = paths_differ_at; i < current_size; ++i)
current_path[i]->SetSelected(false);
@@ -765,11 +838,16 @@ bool MenuController::OnKeyDown(int key_code
CloseSubmenu();
break;
+ case base::VKEY_SPACE:
+ SendAcceleratorToHotTrackedView();
+ break;
+
case base::VKEY_RETURN:
if (pending_state_.item) {
if (pending_state_.item->HasSubmenu()) {
OpenSubmenuChangeSelectionIfCan();
- } else if (pending_state_.item->IsEnabled()) {
+ } else if (!SendAcceleratorToHotTrackedView() &&
+ pending_state_.item->IsEnabled()) {
Accept(pending_state_.item, 0);
return false;
}
@@ -833,6 +911,17 @@ MenuController::~MenuController() {
#endif
}
+bool MenuController::SendAcceleratorToHotTrackedView() {
+ View* hot_view = GetFirstHotTrackedView(pending_state_.item);
+ if (!hot_view)
+ return false;
+
+ Accelerator accelerator(base::VKEY_RETURN, false, false, false);
+ hot_view->AcceleratorPressed(accelerator);
+ hot_view->SetHotTracked(true);
+ return true;
+}
+
void MenuController::UpdateInitialLocation(
const gfx::Rect& bounds,
MenuItemView::AnchorPosition position) {
@@ -935,7 +1024,12 @@ void MenuController::CloseAllNestedMenus() {
}
MenuItemView* MenuController::GetMenuItemAt(View* source, int x, int y) {
+ // Walk the view hierarchy until we find a menu item (or the root).
View* child_under_mouse = source->GetViewForPoint(gfx::Point(x, y));
+ while (child_under_mouse &&
+ child_under_mouse->GetID() != MenuItemView::kMenuItemViewID) {
+ child_under_mouse = child_under_mouse->GetParent();
+ }
if (child_under_mouse && child_under_mouse->IsEnabled() &&
child_under_mouse->GetID() == MenuItemView::kMenuItemViewID) {
return static_cast<MenuItemView*>(child_under_mouse);
@@ -1324,9 +1418,28 @@ void MenuController::IncrementSelection(int delta) {
if (item->GetSubmenu()->GetMenuItemCount()) {
SetSelection(item->GetSubmenu()->GetMenuItemAt(0), false, false);
ScrollToVisible(item->GetSubmenu()->GetMenuItemAt(0));
- return; // return so else case can fall through.
+ return;
}
}
+
+ if (item->GetChildViewCount()) {
+ View* hot_view = GetFirstHotTrackedView(item);
+ if (hot_view) {
+ hot_view->SetHotTracked(false);
+ View* to_make_hot = GetNextFocusableView(item, hot_view, delta == 1);
+ if (to_make_hot) {
+ to_make_hot->SetHotTracked(true);
+ return;
+ }
+ } else {
+ View* to_make_hot = GetInitialFocusableView(item, delta == 1);
+ if (to_make_hot) {
+ to_make_hot->SetHotTracked(true);
+ return;
+ }
+ }
+ }
+
if (item->GetParentMenuItem()) {
MenuItemView* parent = item->GetParentMenuItem();
int parent_count = parent->GetSubmenu()->GetMenuItemCount();
@@ -1335,8 +1448,12 @@ void MenuController::IncrementSelection(int delta) {
if (parent->GetSubmenu()->GetMenuItemAt(i) == item) {
int next_index = (i + delta + parent_count) % parent_count;
ScrollToVisible(parent->GetSubmenu()->GetMenuItemAt(next_index));
- SetSelection(parent->GetSubmenu()->GetMenuItemAt(next_index), false,
- false);
+ MenuItemView* to_select =
+ parent->GetSubmenu()->GetMenuItemAt(next_index);
+ SetSelection(to_select, false, false);
+ View* to_make_hot = GetInitialFocusableView(to_select, delta == 1);
+ if (to_make_hot)
+ to_make_hot->SetHotTracked(true);
break;
}
}
« no previous file with comments | « views/controls/menu/menu_controller.h ('k') | views/controls/menu/menu_item_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698