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