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