| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/app_list/views/search_result_list_view.h" | 5 #include "ui/app_list/views/search_result_list_view.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 11 #include "base/time/time.h" | 11 #include "base/time/time.h" |
| 12 #include "third_party/skia/include/core/SkColor.h" | 12 #include "third_party/skia/include/core/SkColor.h" |
| 13 #include "ui/app_list/app_list_view_delegate.h" |
| 13 #include "ui/app_list/views/search_result_list_view_delegate.h" | 14 #include "ui/app_list/views/search_result_list_view_delegate.h" |
| 14 #include "ui/app_list/views/search_result_view.h" | 15 #include "ui/app_list/views/search_result_view.h" |
| 15 #include "ui/events/event.h" | 16 #include "ui/events/event.h" |
| 16 #include "ui/gfx/animation/linear_animation.h" | 17 #include "ui/gfx/animation/linear_animation.h" |
| 17 #include "ui/views/background.h" | 18 #include "ui/views/background.h" |
| 18 #include "ui/views/layout/box_layout.h" | 19 #include "ui/views/layout/box_layout.h" |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 | 22 |
| 22 const int kMaxResults = 6; | 23 const int kMaxResults = 6; |
| 23 const int kTimeoutIndicatorHeight = 2; | 24 const int kTimeoutIndicatorHeight = 2; |
| 24 const int kTimeoutFramerate = 60; | 25 const int kTimeoutFramerate = 60; |
| 25 const SkColor kTimeoutIndicatorColor = SkColorSetRGB(30, 144, 255); | 26 const SkColor kTimeoutIndicatorColor = SkColorSetRGB(30, 144, 255); |
| 26 | 27 |
| 27 } // namespace | 28 } // namespace |
| 28 | 29 |
| 29 namespace app_list { | 30 namespace app_list { |
| 30 | 31 |
| 31 SearchResultListView::SearchResultListView( | 32 SearchResultListView::SearchResultListView( |
| 32 SearchResultListViewDelegate* delegate) | 33 SearchResultListViewDelegate* delegate, |
| 34 AppListViewDelegate* view_delegate) |
| 33 : delegate_(delegate), | 35 : delegate_(delegate), |
| 36 view_delegate_(view_delegate), |
| 34 results_(NULL), | 37 results_(NULL), |
| 35 results_container_(new views::View), | 38 results_container_(new views::View), |
| 36 auto_launch_indicator_(new views::View), | 39 auto_launch_indicator_(new views::View), |
| 37 last_visible_index_(0), | 40 last_visible_index_(0), |
| 38 selected_index_(-1), | 41 selected_index_(-1), |
| 39 update_factory_(this) { | 42 update_factory_(this) { |
| 40 results_container_->SetLayoutManager( | 43 results_container_->SetLayoutManager( |
| 41 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); | 44 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); |
| 42 | 45 |
| 43 for (int i = 0; i < kMaxResults; ++i) | 46 for (int i = 0; i < kMaxResults; ++i) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 | 82 |
| 80 selected_index_ = selected_index; | 83 selected_index_ = selected_index; |
| 81 | 84 |
| 82 if (selected_index_ >= 0) { | 85 if (selected_index_ >= 0) { |
| 83 SearchResultView* selected_view = GetResultViewAt(selected_index_); | 86 SearchResultView* selected_view = GetResultViewAt(selected_index_); |
| 84 selected_view->ClearSelectedAction(); | 87 selected_view->ClearSelectedAction(); |
| 85 selected_view->SchedulePaint(); | 88 selected_view->SchedulePaint(); |
| 86 selected_view->NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, | 89 selected_view->NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, |
| 87 true); | 90 true); |
| 88 } | 91 } |
| 92 if (auto_launch_animation_) |
| 93 CancelAutoLaunchTimeout(); |
| 89 } | 94 } |
| 90 | 95 |
| 91 bool SearchResultListView::IsResultViewSelected( | 96 bool SearchResultListView::IsResultViewSelected( |
| 92 const SearchResultView* result_view) const { | 97 const SearchResultView* result_view) const { |
| 93 if (selected_index_ < 0) | 98 if (selected_index_ < 0) |
| 94 return false; | 99 return false; |
| 95 | 100 |
| 96 return static_cast<const SearchResultView*>( | 101 return static_cast<const SearchResultView*>( |
| 97 results_container_->child_at(selected_index_)) == result_view; | 102 results_container_->child_at(selected_index_)) == result_view; |
| 98 } | 103 } |
| 99 | 104 |
| 100 void SearchResultListView::SetAutoLaunchTimeout( | 105 void SearchResultListView::UpdateAutoLaunchState() { |
| 101 const base::TimeDelta& timeout) { | 106 SetAutoLaunchTimeout(view_delegate_->GetAutoLaunchTimeout()); |
| 102 if (timeout > base::TimeDelta()) { | |
| 103 auto_launch_indicator_->SetVisible(true); | |
| 104 auto_launch_indicator_->SetBounds(0, 0, 0, kTimeoutIndicatorHeight); | |
| 105 auto_launch_animation_.reset(new gfx::LinearAnimation( | |
| 106 timeout.InMilliseconds(), kTimeoutFramerate, this)); | |
| 107 } else { | |
| 108 auto_launch_indicator_->SetVisible(false); | |
| 109 auto_launch_animation_.reset(); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 void SearchResultListView::CancelAutoLaunchTimeout() { | |
| 114 SetAutoLaunchTimeout(base::TimeDelta()); | |
| 115 } | 107 } |
| 116 | 108 |
| 117 bool SearchResultListView::OnKeyPressed(const ui::KeyEvent& event) { | 109 bool SearchResultListView::OnKeyPressed(const ui::KeyEvent& event) { |
| 118 if (selected_index_ >= 0 && | 110 if (selected_index_ >= 0 && |
| 119 results_container_->child_at(selected_index_)->OnKeyPressed(event)) { | 111 results_container_->child_at(selected_index_)->OnKeyPressed(event)) { |
| 120 return true; | 112 return true; |
| 121 } | 113 } |
| 122 | 114 |
| 123 switch (event.key_code()) { | 115 switch (event.key_code()) { |
| 124 case ui::VKEY_TAB: | 116 case ui::VKEY_TAB: |
| 125 if (event.IsShiftDown()) | 117 if (event.IsShiftDown()) |
| 126 SetSelectedIndex(std::max(selected_index_ - 1, 0)); | 118 SetSelectedIndex(std::max(selected_index_ - 1, 0)); |
| 127 else | 119 else |
| 128 SetSelectedIndex(std::min(selected_index_ + 1, last_visible_index_)); | 120 SetSelectedIndex(std::min(selected_index_ + 1, last_visible_index_)); |
| 129 return true; | 121 return true; |
| 130 case ui::VKEY_UP: | 122 case ui::VKEY_UP: |
| 131 SetSelectedIndex(std::max(selected_index_ - 1, 0)); | 123 SetSelectedIndex(std::max(selected_index_ - 1, 0)); |
| 132 return true; | 124 return true; |
| 133 case ui::VKEY_DOWN: | 125 case ui::VKEY_DOWN: |
| 134 SetSelectedIndex(std::min(selected_index_ + 1, last_visible_index_)); | 126 SetSelectedIndex(std::min(selected_index_ + 1, last_visible_index_)); |
| 135 return true; | 127 return true; |
| 136 default: | 128 default: |
| 137 break; | 129 break; |
| 138 } | 130 } |
| 139 | 131 |
| 140 return false; | 132 return false; |
| 141 } | 133 } |
| 142 | 134 |
| 135 void SearchResultListView::SetAutoLaunchTimeout( |
| 136 const base::TimeDelta& timeout) { |
| 137 if (timeout > base::TimeDelta()) { |
| 138 auto_launch_indicator_->SetVisible(true); |
| 139 auto_launch_indicator_->SetBounds(0, 0, 0, kTimeoutIndicatorHeight); |
| 140 auto_launch_animation_.reset(new gfx::LinearAnimation( |
| 141 timeout.InMilliseconds(), kTimeoutFramerate, this)); |
| 142 auto_launch_animation_->Start(); |
| 143 } else { |
| 144 auto_launch_indicator_->SetVisible(false); |
| 145 auto_launch_animation_.reset(); |
| 146 } |
| 147 } |
| 148 |
| 149 void SearchResultListView::CancelAutoLaunchTimeout() { |
| 150 SetAutoLaunchTimeout(base::TimeDelta()); |
| 151 view_delegate_->AutoLaunchCanceled(); |
| 152 } |
| 153 |
| 143 SearchResultView* SearchResultListView::GetResultViewAt(int index) { | 154 SearchResultView* SearchResultListView::GetResultViewAt(int index) { |
| 144 DCHECK(index >= 0 && index < results_container_->child_count()); | 155 DCHECK(index >= 0 && index < results_container_->child_count()); |
| 145 return static_cast<SearchResultView*>(results_container_->child_at(index)); | 156 return static_cast<SearchResultView*>(results_container_->child_at(index)); |
| 146 } | 157 } |
| 147 | 158 |
| 148 void SearchResultListView::Update() { | 159 void SearchResultListView::Update() { |
| 149 last_visible_index_ = 0; | 160 last_visible_index_ = 0; |
| 150 for (size_t i = 0; i < static_cast<size_t>(results_container_->child_count()); | 161 for (size_t i = 0; i < static_cast<size_t>(results_container_->child_count()); |
| 151 ++i) { | 162 ++i) { |
| 152 SearchResultView* result_view = GetResultViewAt(i); | 163 SearchResultView* result_view = GetResultViewAt(i); |
| 153 if (i < results_->item_count()) { | 164 if (i < results_->item_count()) { |
| 154 result_view->SetResult(results_->GetItemAt(i)); | 165 result_view->SetResult(results_->GetItemAt(i)); |
| 155 result_view->SetVisible(true); | 166 result_view->SetVisible(true); |
| 156 last_visible_index_ = i; | 167 last_visible_index_ = i; |
| 157 } else { | 168 } else { |
| 158 result_view->SetResult(NULL); | 169 result_view->SetResult(NULL); |
| 159 result_view->SetVisible(false); | 170 result_view->SetVisible(false); |
| 160 } | 171 } |
| 161 } | 172 } |
| 162 if (selected_index_ > last_visible_index_) | 173 if (selected_index_ > last_visible_index_) |
| 163 SetSelectedIndex(last_visible_index_); | 174 SetSelectedIndex(last_visible_index_); |
| 164 | 175 |
| 165 Layout(); | 176 Layout(); |
| 166 update_factory_.InvalidateWeakPtrs(); | 177 update_factory_.InvalidateWeakPtrs(); |
| 167 if (auto_launch_animation_) | 178 UpdateAutoLaunchState(); |
| 168 auto_launch_animation_->Start(); | |
| 169 } | 179 } |
| 170 | 180 |
| 171 void SearchResultListView::ScheduleUpdate() { | 181 void SearchResultListView::ScheduleUpdate() { |
| 172 // When search results are added one by one, each addition generates an update | 182 // When search results are added one by one, each addition generates an update |
| 173 // request. Consolidates those update requests into one Update call. | 183 // request. Consolidates those update requests into one Update call. |
| 174 if (!update_factory_.HasWeakPtrs()) { | 184 if (!update_factory_.HasWeakPtrs()) { |
| 175 base::MessageLoop::current()->PostTask( | 185 base::MessageLoop::current()->PostTask( |
| 176 FROM_HERE, | 186 FROM_HERE, |
| 177 base::Bind(&SearchResultListView::Update, | 187 base::Bind(&SearchResultListView::Update, |
| 178 update_factory_.GetWeakPtr())); | 188 update_factory_.GetWeakPtr())); |
| 179 } | 189 } |
| 180 } | 190 } |
| 181 | 191 |
| 192 void SearchResultListView::ForceAutoLaunchForTest() { |
| 193 if (auto_launch_animation_) |
| 194 AnimationEnded(auto_launch_animation_.get()); |
| 195 } |
| 196 |
| 182 void SearchResultListView::Layout() { | 197 void SearchResultListView::Layout() { |
| 183 results_container_->SetBoundsRect(GetLocalBounds()); | 198 results_container_->SetBoundsRect(GetLocalBounds()); |
| 184 } | 199 } |
| 185 | 200 |
| 186 gfx::Size SearchResultListView::GetPreferredSize() { | 201 gfx::Size SearchResultListView::GetPreferredSize() { |
| 187 return results_container_->GetPreferredSize(); | 202 return results_container_->GetPreferredSize(); |
| 188 } | 203 } |
| 189 | 204 |
| 190 int SearchResultListView::GetHeightForWidth(int w) { | 205 int SearchResultListView::GetHeightForWidth(int w) { |
| 191 return results_container_->GetHeightForWidth(w); | 206 return results_container_->GetHeightForWidth(w); |
| 192 } | 207 } |
| 193 | 208 |
| 194 void SearchResultListView::VisibilityChanged(views::View* starting_from, | 209 void SearchResultListView::VisibilityChanged(views::View* starting_from, |
| 195 bool is_visible) { | 210 bool is_visible) { |
| 196 if (!is_visible) { | 211 if (is_visible) |
| 197 auto_launch_indicator_->SetVisible(false); | 212 UpdateAutoLaunchState(); |
| 198 auto_launch_animation_.reset(); | 213 else |
| 199 } | 214 CancelAutoLaunchTimeout(); |
| 200 } | 215 } |
| 201 | 216 |
| 202 void SearchResultListView::AnimationEnded(const gfx::Animation* animation) { | 217 void SearchResultListView::AnimationEnded(const gfx::Animation* animation) { |
| 203 DCHECK_EQ(auto_launch_animation_.get(), animation); | 218 DCHECK_EQ(auto_launch_animation_.get(), animation); |
| 204 delegate_->OpenResult(results_->GetItemAt(0), ui::EF_NONE); | 219 delegate_->OpenResult(results_->GetItemAt(0), ui::EF_NONE); |
| 220 auto_launch_animation_.reset(); |
| 205 } | 221 } |
| 206 | 222 |
| 207 void SearchResultListView::AnimationProgressed( | 223 void SearchResultListView::AnimationProgressed( |
| 208 const gfx::Animation* animation) { | 224 const gfx::Animation* animation) { |
| 209 DCHECK_EQ(auto_launch_animation_.get(), animation); | 225 DCHECK_EQ(auto_launch_animation_.get(), animation); |
| 210 int indicator_width = auto_launch_animation_->CurrentValueBetween(0, width()); | 226 int indicator_width = auto_launch_animation_->CurrentValueBetween(0, width()); |
| 211 auto_launch_indicator_->SetBounds( | 227 auto_launch_indicator_->SetBounds( |
| 212 0, 0, indicator_width, kTimeoutIndicatorHeight); | 228 0, 0, indicator_width, kTimeoutIndicatorHeight); |
| 213 } | 229 } |
| 214 | 230 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 if (delegate_ && view->result()) | 269 if (delegate_ && view->result()) |
| 254 delegate_->OnResultInstalled(view->result()); | 270 delegate_->OnResultInstalled(view->result()); |
| 255 } | 271 } |
| 256 | 272 |
| 257 void SearchResultListView::OnSearchResultUninstalled(SearchResultView* view) { | 273 void SearchResultListView::OnSearchResultUninstalled(SearchResultView* view) { |
| 258 if (delegate_ && view->result()) | 274 if (delegate_ && view->result()) |
| 259 delegate_->OnResultUninstalled(view->result()); | 275 delegate_->OnResultUninstalled(view->result()); |
| 260 } | 276 } |
| 261 | 277 |
| 262 } // namespace app_list | 278 } // namespace app_list |
| OLD | NEW |