OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "ui/views/focus/focus_manager.h" | 6 #include "ui/views/focus/focus_manager.h" |
7 #include "ui/views/focus/focus_search.h" | 7 #include "ui/views/focus/focus_search.h" |
8 #include "ui/views/view.h" | 8 #include "ui/views/view.h" |
9 | 9 |
10 namespace ui { | 10 namespace ui { |
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) const { | 23 View** focus_traversable_view) const { |
24 *focus_traversable = NULL; | 24 *focus_traversable = NULL; |
25 *focus_traversable_view = NULL; | 25 *focus_traversable_view = NULL; |
26 | 26 |
27 if (root_->child_count() == 0) { | 27 if (root_->children_empty()) { |
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->group(); | 36 starting_view_group = starting_view->group(); |
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_->child_count() - 1) : | 42 root_->child_at(root_->children_size() - 1) : |
43 root_->GetChildViewAt(0); | 43 root_->child_at(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_->Contains(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_->Contains(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->group()); | 115 View* selected_view = view->GetSelectedViewForGroup(view->group()); |
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) const { | 123 View* FocusSearch::GetParent(View* v) const { |
124 return root_->Contains(v) ? v->parent() : NULL; | 124 return root_->Contains(*v) ? v->parent() : NULL; |
125 } | 125 } |
126 | 126 |
127 // Strategy for finding the next focusable view: | 127 // Strategy for finding the next focusable view: |
128 // - 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 |
129 // 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 |
130 // with no children. | 130 // with no children. |
131 // - 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 |
132 // FindNextFocusableViewImpl on that view). | 132 // FindNextFocusableViewImpl on that view). |
133 // - 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 |
134 // 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... |
151 | 151 |
152 *focus_traversable = starting_view->GetFocusTraversable(); | 152 *focus_traversable = starting_view->GetFocusTraversable(); |
153 if (*focus_traversable) { | 153 if (*focus_traversable) { |
154 *focus_traversable_view = starting_view; | 154 *focus_traversable_view = starting_view; |
155 return NULL; | 155 return NULL; |
156 } | 156 } |
157 } | 157 } |
158 | 158 |
159 // First let's try the left child. | 159 // First let's try the left child. |
160 if (can_go_down) { | 160 if (can_go_down) { |
161 if (starting_view->child_count() > 0) { | 161 if (!starting_view->children_empty()) { |
162 View* v = FindNextFocusableViewImpl(starting_view->GetChildViewAt(0), | 162 View* v = FindNextFocusableViewImpl(starting_view->child_at(0), |
163 true, false, true, skip_group_id, | 163 true, false, true, skip_group_id, |
164 focus_traversable, | 164 focus_traversable, |
165 focus_traversable_view); | 165 focus_traversable_view); |
166 if (v || *focus_traversable) | 166 if (v || *focus_traversable) |
167 return v; | 167 return v; |
168 } | 168 } |
169 } | 169 } |
170 | 170 |
171 // Then try the right sibling. | 171 // Then try the right sibling. |
172 View* sibling = starting_view->GetNextFocusableView(); | 172 View* sibling = starting_view->GetNextFocusableView(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 // Let's go down and right as much as we can. | 216 // Let's go down and right as much as we can. |
217 if (can_go_down) { | 217 if (can_go_down) { |
218 // 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 |
219 // a FocusTraversable. | 219 // a FocusTraversable. |
220 *focus_traversable = starting_view->GetFocusTraversable(); | 220 *focus_traversable = starting_view->GetFocusTraversable(); |
221 if (*focus_traversable) { | 221 if (*focus_traversable) { |
222 *focus_traversable_view = starting_view; | 222 *focus_traversable_view = starting_view; |
223 return NULL; | 223 return NULL; |
224 } | 224 } |
225 | 225 |
226 if (starting_view->child_count() > 0) { | 226 if (!starting_view->children_empty()) { |
227 View* view = | 227 View* view = starting_view->child_at(starting_view->children_size() - 1); |
228 starting_view->GetChildViewAt(starting_view->child_count() - 1); | |
229 View* v = FindPreviousFocusableViewImpl(view, true, false, true, | 228 View* v = FindPreviousFocusableViewImpl(view, true, false, true, |
230 skip_group_id, | 229 skip_group_id, |
231 focus_traversable, | 230 focus_traversable, |
232 focus_traversable_view); | 231 focus_traversable_view); |
233 if (v || *focus_traversable) | 232 if (v || *focus_traversable) |
234 return v; | 233 return v; |
235 } | 234 } |
236 } | 235 } |
237 | 236 |
238 // Then look at this view. Here, we do not need to see if the view has | 237 // Then look at this view. Here, we do not need to see if the view has |
(...skipping 26 matching lines...) Expand all Loading... |
265 skip_group_id, | 264 skip_group_id, |
266 focus_traversable, | 265 focus_traversable, |
267 focus_traversable_view); | 266 focus_traversable_view); |
268 } | 267 } |
269 | 268 |
270 // We found nothing. | 269 // We found nothing. |
271 return NULL; | 270 return NULL; |
272 } | 271 } |
273 | 272 |
274 } // namespace ui | 273 } // namespace ui |
OLD | NEW |