| OLD | NEW | 
|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/logging.h" | 5 #include "base/logging.h" | 
| 6 #include "views/focus/focus_manager.h" | 6 #include "views/focus/focus_manager.h" | 
| 7 #include "views/focus/focus_search.h" | 7 #include "views/focus/focus_search.h" | 
| 8 #include "views/view.h" | 8 #include "views/view.h" | 
| 9 | 9 | 
| 10 namespace views { | 10 namespace views { | 
| 11 | 11 | 
| 12 FocusSearch::FocusSearch(View* root, bool cycle, bool accessibility_mode) | 12 FocusSearch::FocusSearch(View* root, bool cycle, bool accessibility_mode) | 
| 13     : root_(root), | 13     : root_(root), | 
| 14       cycle_(cycle), | 14       cycle_(cycle), | 
| 15       accessibility_mode_(accessibility_mode) { | 15       accessibility_mode_(accessibility_mode) { | 
| 16 } | 16 } | 
| 17 | 17 | 
| 18 View* FocusSearch::FindNextFocusableView(View* starting_view, | 18 View* FocusSearch::FindNextFocusableView(View* starting_view, | 
| 19                                          bool reverse, | 19                                          bool reverse, | 
| 20                                          Direction direction, | 20                                          Direction direction, | 
| 21                                          bool check_starting_view, | 21                                          bool check_starting_view, | 
| 22                                          FocusTraversable** focus_traversable, | 22                                          FocusTraversable** focus_traversable, | 
| 23                                          View** focus_traversable_view) { | 23                                          View** focus_traversable_view) { | 
| 24   *focus_traversable = NULL; | 24   *focus_traversable = NULL; | 
| 25   *focus_traversable_view = NULL; | 25   *focus_traversable_view = NULL; | 
| 26 | 26 | 
| 27   if (root_->GetChildViewCount() == 0) { | 27   if (!root_->has_children()) { | 
| 28     NOTREACHED(); | 28     NOTREACHED(); | 
| 29     // Nothing to focus on here. | 29     // Nothing to focus on here. | 
| 30     return NULL; | 30     return NULL; | 
| 31   } | 31   } | 
| 32 | 32 | 
| 33   View* initial_starting_view = starting_view; | 33   View* initial_starting_view = starting_view; | 
| 34   int starting_view_group = -1; | 34   int starting_view_group = -1; | 
| 35   if (starting_view) | 35   if (starting_view) | 
| 36     starting_view_group = starting_view->GetGroup(); | 36     starting_view_group = starting_view->GetGroup(); | 
| 37 | 37 | 
| 38   if (!starting_view) { | 38   if (!starting_view) { | 
| 39     // Default to the first/last child | 39     // Default to the first/last child | 
| 40     starting_view = | 40     starting_view = | 
| 41         reverse ? | 41         reverse ? | 
| 42         root_->GetChildViewAt(root_->GetChildViewCount() - 1) : | 42         root_->GetChildViewAt(root_->child_count() - 1) : | 
| 43         root_->GetChildViewAt(0); | 43         root_->GetChildViewAt(0); | 
| 44     // If there was no starting view, then the one we select is a potential | 44     // If there was no starting view, then the one we select is a potential | 
| 45     // focus candidate. | 45     // focus candidate. | 
| 46     check_starting_view = true; | 46     check_starting_view = true; | 
| 47   } else { | 47   } else { | 
| 48     // The starting view should be a direct or indirect child of the root. | 48     // The starting view should be a direct or indirect child of the root. | 
| 49     DCHECK(root_->IsParentOf(starting_view)); | 49     DCHECK(root_->Contains(starting_view)); | 
| 50   } | 50   } | 
| 51 | 51 | 
| 52   View* v = NULL; | 52   View* v = NULL; | 
| 53   if (!reverse) { | 53   if (!reverse) { | 
| 54     v = FindNextFocusableViewImpl(starting_view, check_starting_view, | 54     v = FindNextFocusableViewImpl(starting_view, check_starting_view, | 
| 55                                   true, | 55                                   true, | 
| 56                                   (direction == DOWN) ? true : false, | 56                                   (direction == DOWN) ? true : false, | 
| 57                                   starting_view_group, | 57                                   starting_view_group, | 
| 58                                   focus_traversable, | 58                                   focus_traversable, | 
| 59                                   focus_traversable_view); | 59                                   focus_traversable_view); | 
| 60   } else { | 60   } else { | 
| 61     // If the starting view is focusable, we don't want to go down, as we are | 61     // If the starting view is focusable, we don't want to go down, as we are | 
| 62     // traversing the view hierarchy tree bottom-up. | 62     // traversing the view hierarchy tree bottom-up. | 
| 63     bool can_go_down = (direction == DOWN) && !IsFocusable(starting_view); | 63     bool can_go_down = (direction == DOWN) && !IsFocusable(starting_view); | 
| 64     v = FindPreviousFocusableViewImpl(starting_view, check_starting_view, | 64     v = FindPreviousFocusableViewImpl(starting_view, check_starting_view, | 
| 65                                       true, | 65                                       true, | 
| 66                                       can_go_down, | 66                                       can_go_down, | 
| 67                                       starting_view_group, | 67                                       starting_view_group, | 
| 68                                       focus_traversable, | 68                                       focus_traversable, | 
| 69                                       focus_traversable_view); | 69                                       focus_traversable_view); | 
| 70   } | 70   } | 
| 71 | 71 | 
| 72   // Don't set the focus to something outside of this view hierarchy. | 72   // Don't set the focus to something outside of this view hierarchy. | 
| 73   if (v && v != root_ && !root_->IsParentOf(v)) | 73   if (v && v != root_ && !root_->Contains(v)) | 
| 74     v = NULL; | 74     v = NULL; | 
| 75 | 75 | 
| 76   // If |cycle_| is true, prefer to keep cycling rather than returning NULL. | 76   // If |cycle_| is true, prefer to keep cycling rather than returning NULL. | 
| 77   if (cycle_ && !v && initial_starting_view) { | 77   if (cycle_ && !v && initial_starting_view) { | 
| 78     v = FindNextFocusableView(NULL, reverse, direction, check_starting_view, | 78     v = FindNextFocusableView(NULL, reverse, direction, check_starting_view, | 
| 79                               focus_traversable, focus_traversable_view); | 79                               focus_traversable, focus_traversable_view); | 
| 80     DCHECK(IsFocusable(v)); | 80     DCHECK(IsFocusable(v)); | 
| 81     return v; | 81     return v; | 
| 82   } | 82   } | 
| 83 | 83 | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 114 | 114 | 
| 115   View* selected_view = view->GetSelectedViewForGroup(view->GetGroup()); | 115   View* selected_view = view->GetSelectedViewForGroup(view->GetGroup()); | 
| 116   if (selected_view) | 116   if (selected_view) | 
| 117     return selected_view; | 117     return selected_view; | 
| 118 | 118 | 
| 119   // No view selected for that group, default to the specified view. | 119   // No view selected for that group, default to the specified view. | 
| 120   return view; | 120   return view; | 
| 121 } | 121 } | 
| 122 | 122 | 
| 123 View* FocusSearch::GetParent(View* v) { | 123 View* FocusSearch::GetParent(View* v) { | 
| 124   if (root_->IsParentOf(v)) { | 124   return root_->Contains(v) ? v->parent() : NULL; | 
| 125     return v->GetParent(); |  | 
| 126   } else { |  | 
| 127     return NULL; |  | 
| 128   } |  | 
| 129 } | 125 } | 
| 130 | 126 | 
| 131 // Strategy for finding the next focusable view: | 127 // Strategy for finding the next focusable view: | 
| 132 // - keep going down the first child, stop when you find a focusable view or | 128 // - keep going down the first child, stop when you find a focusable view or | 
| 133 //   a focus traversable view (in that case return it) or when you reach a view | 129 //   a focus traversable view (in that case return it) or when you reach a view | 
| 134 //   with no children. | 130 //   with no children. | 
| 135 // - go to the right sibling and start the search from there (by invoking | 131 // - go to the right sibling and start the search from there (by invoking | 
| 136 //   FindNextFocusableViewImpl on that view). | 132 //   FindNextFocusableViewImpl on that view). | 
| 137 // - if the view has no right sibling, go up the parents until you find a parent | 133 // - if the view has no right sibling, go up the parents until you find a parent | 
| 138 //   with a right sibling and start the search from there. | 134 //   with a right sibling and start the search from there. | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 155 | 151 | 
| 156     *focus_traversable = starting_view->GetFocusTraversable(); | 152     *focus_traversable = starting_view->GetFocusTraversable(); | 
| 157     if (*focus_traversable) { | 153     if (*focus_traversable) { | 
| 158       *focus_traversable_view = starting_view; | 154       *focus_traversable_view = starting_view; | 
| 159       return NULL; | 155       return NULL; | 
| 160     } | 156     } | 
| 161   } | 157   } | 
| 162 | 158 | 
| 163   // First let's try the left child. | 159   // First let's try the left child. | 
| 164   if (can_go_down) { | 160   if (can_go_down) { | 
| 165     if (starting_view->GetChildViewCount() > 0) { | 161     if (starting_view->has_children()) { | 
| 166       View* v = FindNextFocusableViewImpl(starting_view->GetChildViewAt(0), | 162       View* v = FindNextFocusableViewImpl(starting_view->GetChildViewAt(0), | 
| 167                                           true, false, true, skip_group_id, | 163                                           true, false, true, skip_group_id, | 
| 168                                           focus_traversable, | 164                                           focus_traversable, | 
| 169                                           focus_traversable_view); | 165                                           focus_traversable_view); | 
| 170       if (v || *focus_traversable) | 166       if (v || *focus_traversable) | 
| 171         return v; | 167         return v; | 
| 172     } | 168     } | 
| 173   } | 169   } | 
| 174 | 170 | 
| 175   // Then try the right sibling. | 171   // Then try the right sibling. | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 220   // Let's go down and right as much as we can. | 216   // Let's go down and right as much as we can. | 
| 221   if (can_go_down) { | 217   if (can_go_down) { | 
| 222     // Before we go into the direct children, we have to check if this view has | 218     // Before we go into the direct children, we have to check if this view has | 
| 223     // a FocusTraversable. | 219     // a FocusTraversable. | 
| 224     *focus_traversable = starting_view->GetFocusTraversable(); | 220     *focus_traversable = starting_view->GetFocusTraversable(); | 
| 225     if (*focus_traversable) { | 221     if (*focus_traversable) { | 
| 226       *focus_traversable_view = starting_view; | 222       *focus_traversable_view = starting_view; | 
| 227       return NULL; | 223       return NULL; | 
| 228     } | 224     } | 
| 229 | 225 | 
| 230     if (starting_view->GetChildViewCount() > 0) { | 226     if (starting_view->has_children()) { | 
| 231       View* view = | 227       View* view = | 
| 232           starting_view->GetChildViewAt(starting_view->GetChildViewCount() - 1); | 228           starting_view->GetChildViewAt(starting_view->child_count() - 1); | 
| 233       View* v = FindPreviousFocusableViewImpl(view, true, false, true, | 229       View* v = FindPreviousFocusableViewImpl(view, true, false, true, | 
| 234                                               skip_group_id, | 230                                               skip_group_id, | 
| 235                                               focus_traversable, | 231                                               focus_traversable, | 
| 236                                               focus_traversable_view); | 232                                               focus_traversable_view); | 
| 237       if (v || *focus_traversable) | 233       if (v || *focus_traversable) | 
| 238         return v; | 234         return v; | 
| 239     } | 235     } | 
| 240   } | 236   } | 
| 241 | 237 | 
| 242   // Then look at this view. Here, we do not need to see if the view has | 238   // Then look at this view. Here, we do not need to see if the view has | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 269                                            skip_group_id, | 265                                            skip_group_id, | 
| 270                                            focus_traversable, | 266                                            focus_traversable, | 
| 271                                            focus_traversable_view); | 267                                            focus_traversable_view); | 
| 272   } | 268   } | 
| 273 | 269 | 
| 274   // We found nothing. | 270   // We found nothing. | 
| 275   return NULL; | 271   return NULL; | 
| 276 } | 272 } | 
| 277 | 273 | 
| 278 }  // namespace views | 274 }  // namespace views | 
| OLD | NEW | 
|---|