Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(303)

Side by Side Diff: ui/app_list/views/search_result_list_view.cc

Issue 164193005: Refactors the auto-launch logic and adds tests for it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix win error 2 Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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), true, ui::EF_NONE); 219 delegate_->OpenResult(results_->GetItemAt(0), true, ui::EF_NONE);
220
221 // The auto-launch has to be canceled explicitly. Think that one of searcher
222 // is extremely slow. Sometimes the events would happen in the following
223 // order:
224 // 1. The search results arrive, auto-launch is dispatched
225 // 2. Timed out and auto-launch the first search result
226 // 3. Then another searcher adds search results more
227 // At the step 3, we shouldn't dispatch the auto-launch again.
228 CancelAutoLaunchTimeout();
205 } 229 }
206 230
207 void SearchResultListView::AnimationProgressed( 231 void SearchResultListView::AnimationProgressed(
208 const gfx::Animation* animation) { 232 const gfx::Animation* animation) {
209 DCHECK_EQ(auto_launch_animation_.get(), animation); 233 DCHECK_EQ(auto_launch_animation_.get(), animation);
210 int indicator_width = auto_launch_animation_->CurrentValueBetween(0, width()); 234 int indicator_width = auto_launch_animation_->CurrentValueBetween(0, width());
211 auto_launch_indicator_->SetBounds( 235 auto_launch_indicator_->SetBounds(
212 0, 0, indicator_width, kTimeoutIndicatorHeight); 236 0, 0, indicator_width, kTimeoutIndicatorHeight);
213 } 237 }
214 238
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 if (delegate_ && view->result()) 277 if (delegate_ && view->result())
254 delegate_->OnResultInstalled(view->result()); 278 delegate_->OnResultInstalled(view->result());
255 } 279 }
256 280
257 void SearchResultListView::OnSearchResultUninstalled(SearchResultView* view) { 281 void SearchResultListView::OnSearchResultUninstalled(SearchResultView* view) {
258 if (delegate_ && view->result()) 282 if (delegate_ && view->result())
259 delegate_->OnResultUninstalled(view->result()); 283 delegate_->OnResultUninstalled(view->result());
260 } 284 }
261 285
262 } // namespace app_list 286 } // namespace app_list
OLDNEW
« no previous file with comments | « ui/app_list/views/search_result_list_view.h ('k') | ui/app_list/views/search_result_list_view_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698