OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "views/accessible_pane_view.h" | |
6 | |
7 #include "base/message_loop.h" | |
8 #include "ui/base/accessibility/accessible_view_state.h" | |
9 #include "ui/views/focus/focus_search.h" | |
10 #include "ui/views/focus/view_storage.h" | |
11 #include "ui/views/widget/widget.h" | |
12 | |
13 namespace views { | |
14 | |
15 AccessiblePaneView::AccessiblePaneView() | |
16 : pane_has_focus_(false), | |
17 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), | |
18 focus_manager_(NULL), | |
19 home_key_(ui::VKEY_HOME, false, false, false), | |
20 end_key_(ui::VKEY_END, false, false, false), | |
21 escape_key_(ui::VKEY_ESCAPE, false, false, false), | |
22 left_key_(ui::VKEY_LEFT, false, false, false), | |
23 right_key_(ui::VKEY_RIGHT, false, false, false) { | |
24 focus_search_.reset(new views::FocusSearch(this, true, true)); | |
25 } | |
26 | |
27 AccessiblePaneView::~AccessiblePaneView() { | |
28 if (pane_has_focus_) { | |
29 focus_manager_->RemoveFocusChangeListener(this); | |
30 } | |
31 } | |
32 | |
33 bool AccessiblePaneView::SetPaneFocus(views::View* initial_focus) { | |
34 if (!IsVisible()) | |
35 return false; | |
36 | |
37 if (!focus_manager_) | |
38 focus_manager_ = GetFocusManager(); | |
39 | |
40 focus_manager_->StoreFocusedView(); | |
41 | |
42 // Use the provided initial focus if it's visible and enabled, otherwise | |
43 // use the first focusable child. | |
44 if (!initial_focus || | |
45 !Contains(initial_focus) || | |
46 !initial_focus->IsVisible() || | |
47 !initial_focus->IsEnabled()) { | |
48 initial_focus = GetFirstFocusableChild(); | |
49 } | |
50 | |
51 // Return false if there are no focusable children. | |
52 if (!initial_focus) | |
53 return false; | |
54 | |
55 focus_manager_->SetFocusedView(initial_focus); | |
56 | |
57 // If we already have pane focus, we're done. | |
58 if (pane_has_focus_) | |
59 return true; | |
60 | |
61 // Otherwise, set accelerators and start listening for focus change events. | |
62 pane_has_focus_ = true; | |
63 focus_manager_->RegisterAccelerator(home_key_, this); | |
64 focus_manager_->RegisterAccelerator(end_key_, this); | |
65 focus_manager_->RegisterAccelerator(escape_key_, this); | |
66 focus_manager_->RegisterAccelerator(left_key_, this); | |
67 focus_manager_->RegisterAccelerator(right_key_, this); | |
68 focus_manager_->AddFocusChangeListener(this); | |
69 | |
70 return true; | |
71 } | |
72 | |
73 bool AccessiblePaneView::SetPaneFocusAndFocusDefault() { | |
74 return SetPaneFocus(GetDefaultFocusableChild()); | |
75 } | |
76 | |
77 views::View* AccessiblePaneView::GetDefaultFocusableChild() { | |
78 return NULL; | |
79 } | |
80 | |
81 void AccessiblePaneView::RemovePaneFocus() { | |
82 focus_manager_->RemoveFocusChangeListener(this); | |
83 pane_has_focus_ = false; | |
84 | |
85 focus_manager_->UnregisterAccelerator(home_key_, this); | |
86 focus_manager_->UnregisterAccelerator(end_key_, this); | |
87 focus_manager_->UnregisterAccelerator(escape_key_, this); | |
88 focus_manager_->UnregisterAccelerator(left_key_, this); | |
89 focus_manager_->UnregisterAccelerator(right_key_, this); | |
90 } | |
91 | |
92 views::View* AccessiblePaneView::GetFirstFocusableChild() { | |
93 FocusTraversable* dummy_focus_traversable; | |
94 views::View* dummy_focus_traversable_view; | |
95 return focus_search_->FindNextFocusableView( | |
96 NULL, false, views::FocusSearch::DOWN, false, | |
97 &dummy_focus_traversable, &dummy_focus_traversable_view); | |
98 } | |
99 | |
100 views::View* AccessiblePaneView::GetLastFocusableChild() { | |
101 FocusTraversable* dummy_focus_traversable; | |
102 views::View* dummy_focus_traversable_view; | |
103 return focus_search_->FindNextFocusableView( | |
104 this, true, views::FocusSearch::DOWN, false, | |
105 &dummy_focus_traversable, &dummy_focus_traversable_view); | |
106 } | |
107 | |
108 //////////////////////////////////////////////////////////////////////////////// | |
109 // View overrides: | |
110 | |
111 views::FocusTraversable* AccessiblePaneView::GetPaneFocusTraversable() { | |
112 if (pane_has_focus_) | |
113 return this; | |
114 else | |
115 return NULL; | |
116 } | |
117 | |
118 bool AccessiblePaneView::AcceleratorPressed( | |
119 const ui::Accelerator& accelerator) { | |
120 | |
121 const views::View* focused_view = focus_manager_->GetFocusedView(); | |
122 if (!Contains(focused_view)) | |
123 return false; | |
124 | |
125 switch (accelerator.key_code()) { | |
126 case ui::VKEY_ESCAPE: | |
127 RemovePaneFocus(); | |
128 focus_manager_->RestoreFocusedView(); | |
129 return true; | |
130 case ui::VKEY_LEFT: | |
131 focus_manager_->AdvanceFocus(true); | |
132 return true; | |
133 case ui::VKEY_RIGHT: | |
134 focus_manager_->AdvanceFocus(false); | |
135 return true; | |
136 case ui::VKEY_HOME: | |
137 focus_manager_->SetFocusedViewWithReason( | |
138 GetFirstFocusableChild(), views::FocusManager::kReasonFocusTraversal); | |
139 return true; | |
140 case ui::VKEY_END: | |
141 focus_manager_->SetFocusedViewWithReason( | |
142 GetLastFocusableChild(), views::FocusManager::kReasonFocusTraversal); | |
143 return true; | |
144 default: | |
145 return false; | |
146 } | |
147 } | |
148 | |
149 void AccessiblePaneView::SetVisible(bool flag) { | |
150 if (IsVisible() && !flag && pane_has_focus_) { | |
151 RemovePaneFocus(); | |
152 focus_manager_->RestoreFocusedView(); | |
153 } | |
154 View::SetVisible(flag); | |
155 } | |
156 | |
157 void AccessiblePaneView::GetAccessibleState(ui::AccessibleViewState* state) { | |
158 state->role = ui::AccessibilityTypes::ROLE_PANE; | |
159 } | |
160 | |
161 //////////////////////////////////////////////////////////////////////////////// | |
162 // FocusChangeListener overrides: | |
163 | |
164 void AccessiblePaneView::OnWillChangeFocus(views::View* focused_before, | |
165 views::View* focused_now) { | |
166 // Act when focus has changed. | |
167 } | |
168 | |
169 void AccessiblePaneView::OnDidChangeFocus(views::View* focused_before, | |
170 views::View* focused_now) { | |
171 if (!focused_now) | |
172 return; | |
173 | |
174 views::FocusManager::FocusChangeReason reason = | |
175 focus_manager_->focus_change_reason(); | |
176 | |
177 if (!Contains(focused_now) || | |
178 reason == views::FocusManager::kReasonDirectFocusChange) { | |
179 // We should remove pane focus (i.e. make most of the controls | |
180 // not focusable again) because the focus has left the pane, | |
181 // or because the focus changed within the pane due to the user | |
182 // directly focusing to a specific view (e.g., clicking on it). | |
183 RemovePaneFocus(); | |
184 } | |
185 } | |
186 | |
187 //////////////////////////////////////////////////////////////////////////////// | |
188 // FocusTraversable overrides: | |
189 | |
190 views::FocusSearch* AccessiblePaneView::GetFocusSearch() { | |
191 DCHECK(pane_has_focus_); | |
192 return focus_search_.get(); | |
193 } | |
194 | |
195 views::FocusTraversable* AccessiblePaneView::GetFocusTraversableParent() { | |
196 DCHECK(pane_has_focus_); | |
197 return NULL; | |
198 } | |
199 | |
200 views::View* AccessiblePaneView::GetFocusTraversableParentView() { | |
201 DCHECK(pane_has_focus_); | |
202 return NULL; | |
203 } | |
204 | |
205 } // namespace views | |
OLD | NEW |