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

Side by Side Diff: ui/app_list/app_list_view.cc

Issue 10386224: app_list: Add search box and search result view for v2. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix win_aura Created 8 years, 7 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/app_list_view.h" 5 #include "ui/app_list/app_list_view.h"
6 6
7 #include <algorithm>
7 #include <string> 8 #include <string>
8 9
9 #include "ui/app_list/app_list_bubble_border.h" 10 #include "ui/app_list/app_list_bubble_border.h"
10 #include "ui/app_list/app_list_item_view.h" 11 #include "ui/app_list/app_list_item_view.h"
11 #include "ui/app_list/app_list_model.h" 12 #include "ui/app_list/app_list_model.h"
12 #include "ui/app_list/app_list_model_view.h"
13 #include "ui/app_list/app_list_view_delegate.h" 13 #include "ui/app_list/app_list_view_delegate.h"
14 #include "ui/app_list/apps_grid_view.h"
14 #include "ui/app_list/page_switcher.h" 15 #include "ui/app_list/page_switcher.h"
15 #include "ui/app_list/pagination_model.h" 16 #include "ui/app_list/pagination_model.h"
17 #include "ui/app_list/search_box_model.h"
18 #include "ui/app_list/search_box_view.h"
19 #include "ui/app_list/search_result_list_view.h"
16 #include "ui/compositor/layer.h" 20 #include "ui/compositor/layer.h"
17 #include "ui/compositor/scoped_layer_animation_settings.h" 21 #include "ui/compositor/scoped_layer_animation_settings.h"
18 #include "ui/gfx/screen.h" 22 #include "ui/gfx/screen.h"
19 #include "ui/gfx/transform_util.h" 23 #include "ui/gfx/transform_util.h"
20 #include "ui/views/background.h" 24 #include "ui/views/background.h"
21 #include "ui/views/bubble/bubble_frame_view.h" 25 #include "ui/views/bubble/bubble_frame_view.h"
22 #include "ui/views/layout/box_layout.h" 26 #include "ui/views/controls/textfield/textfield.h"
23 #include "ui/views/widget/widget.h" 27 #include "ui/views/widget/widget.h"
24 28
25 namespace app_list { 29 namespace app_list {
26 30
27 namespace { 31 namespace {
28 32
29 // 0.2 black 33 // 0.2 black
30 const SkColor kWidgetBackgroundColor = SkColorSetARGB(0x33, 0, 0, 0); 34 const SkColor kWidgetBackgroundColor = SkColorSetARGB(0x33, 0, 0, 0);
31 35
32 const float kModelViewAnimationScaleFactor = 0.9f; 36 const float kModelViewAnimationScaleFactor = 0.9f;
33 37
38 const int kPreferredWidth = 360;
39
34 const int kPreferredIconDimension = 48; 40 const int kPreferredIconDimension = 48;
35 const int kPreferredCols = 4; 41 const int kPreferredCols = 4;
36 const int kPreferredRows = 4; 42 const int kPreferredRows = 4;
37 43
38 ui::Transform GetScaleTransform(AppListModelView* model_view) { 44 // Inner padding space in pixels of bubble contents.
45 const int kInnerPadding = 1;
46
47 ui::Transform GetScaleTransform(AppsGridView* model_view) {
39 gfx::Rect pixel_bounds = model_view->GetLayerBoundsInPixel(); 48 gfx::Rect pixel_bounds = model_view->GetLayerBoundsInPixel();
40 gfx::Point center(pixel_bounds.width() / 2, pixel_bounds.height() / 2); 49 gfx::Point center(pixel_bounds.width() / 2, pixel_bounds.height() / 2);
41 return ui::GetScaleTransform(center, kModelViewAnimationScaleFactor); 50 return ui::GetScaleTransform(center, kModelViewAnimationScaleFactor);
42 } 51 }
43 52
44 } // namespace 53 } // namespace
45 54
46 //////////////////////////////////////////////////////////////////////////////// 55 ////////////////////////////////////////////////////////////////////////////////
47 // AppListView: 56 // AppListView:
48 57
49 AppListView::AppListView(AppListViewDelegate* delegate) 58 AppListView::AppListView(AppListViewDelegate* delegate)
50 : delegate_(delegate), 59 : delegate_(delegate),
51 pagination_model_(new PaginationModel), 60 pagination_model_(new PaginationModel),
52 bubble_style_(false), 61 bubble_style_(false),
53 bubble_border_(NULL), 62 bubble_border_(NULL),
54 model_view_(NULL) { 63 apps_view_(NULL),
64 page_switcher_view_(NULL),
65 search_box_view_(NULL),
66 search_results_view_(NULL) {
55 } 67 }
56 68
57 AppListView::~AppListView() { 69 AppListView::~AppListView() {
58 // Deletes all child views while the models are still valid. 70 // Deletes all child views while the models are still valid.
59 RemoveAllChildViews(true); 71 RemoveAllChildViews(true);
60 } 72 }
61 73
62 void AppListView::InitAsFullscreenWidget(gfx::NativeView parent, 74 void AppListView::InitAsFullscreenWidget(gfx::NativeView parent,
63 const gfx::Rect& screen_bounds, 75 const gfx::Rect& screen_bounds,
64 const gfx::Rect& work_area) { 76 const gfx::Rect& work_area) {
65 bubble_style_ = false; 77 bubble_style_ = false;
66 set_background(views::Background::CreateSolidBackground( 78 set_background(views::Background::CreateSolidBackground(
67 kWidgetBackgroundColor)); 79 kWidgetBackgroundColor));
68 work_area_ = work_area; 80 work_area_ = work_area;
69 81
70 model_view_ = new AppListModelView(this, pagination_model_.get()); 82 apps_view_ = new AppsGridView(this, pagination_model_.get());
71 model_view_->SetPaintToLayer(true); 83 apps_view_->SetPaintToLayer(true);
72 model_view_->layer()->SetFillsBoundsOpaquely(false); 84 apps_view_->layer()->SetFillsBoundsOpaquely(false);
73 AddChildView(model_view_); 85 AddChildView(apps_view_);
74 86
75 views::Widget::InitParams widget_params( 87 views::Widget::InitParams widget_params(
76 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); 88 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
77 widget_params.delegate = this; 89 widget_params.delegate = this;
78 widget_params.transparent = true; 90 widget_params.transparent = true;
79 widget_params.parent = parent; 91 widget_params.parent = parent;
80 92
81 views::Widget* widget = new views::Widget; 93 views::Widget* widget = new views::Widget;
82 widget->Init(widget_params); 94 widget->Init(widget_params);
83 widget->SetContentsView(this); 95 widget->SetContentsView(this);
84 widget->SetBounds(screen_bounds); 96 widget->SetBounds(screen_bounds);
85 97
86 // Turns off default animation. 98 // Turns off default animation.
87 widget->SetVisibilityChangedAnimationsEnabled(false); 99 widget->SetVisibilityChangedAnimationsEnabled(false);
88 100
89 // Sets initial transform. AnimateShow changes it back to identity transform. 101 // Sets initial transform. AnimateShow changes it back to identity transform.
90 model_view_->SetTransform(GetScaleTransform(model_view_)); 102 apps_view_->SetTransform(GetScaleTransform(apps_view_));
91 UpdateModel(); 103 CreateModel();
92 } 104 }
93 105
94 void AppListView::InitAsBubble(gfx::NativeView parent, views::View* anchor) { 106 void AppListView::InitAsBubble(gfx::NativeView parent, views::View* anchor) {
95 bubble_style_ = true; 107 bubble_style_ = true;
96 set_background(NULL); 108 set_background(NULL);
97 109
98 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); 110 search_box_view_ = new SearchBoxView(this);
111 AddChildView(search_box_view_);
99 112
100 model_view_ = new AppListModelView(this, pagination_model_.get()); 113 apps_view_ = new AppsGridView(this, pagination_model_.get());
101 model_view_->SetLayout(kPreferredIconDimension, 114 apps_view_->SetLayout(kPreferredIconDimension,
102 kPreferredCols, 115 kPreferredCols,
103 kPreferredRows); 116 kPreferredRows);
104 AddChildView(model_view_); 117 AddChildView(apps_view_);
105 118
106 PageSwitcher* page_switcher = new PageSwitcher(pagination_model_.get()); 119 search_results_view_ = new SearchResultListView(this);
107 AddChildView(page_switcher); 120 search_results_view_->SetVisible(false);
121 AddChildView(search_results_view_);
122
123 page_switcher_view_ = new PageSwitcher(pagination_model_.get());
124 AddChildView(page_switcher_view_);
125
126 search_box_view_->set_grid_view(apps_view_);
127 search_box_view_->set_results_view(search_results_view_);
108 128
109 set_anchor_view(anchor); 129 set_anchor_view(anchor);
130 set_margin(0);
110 set_parent_window(parent); 131 set_parent_window(parent);
111 set_close_on_deactivate(false); 132 set_close_on_deactivate(false);
112 views::BubbleDelegateView::CreateBubble(this); 133 views::BubbleDelegateView::CreateBubble(this);
113 134
114 // Resets default background since AppListBubbleBorder paints background. 135 // Resets default background since AppListBubbleBorder paints background.
115 GetBubbleFrameView()->set_background(NULL); 136 GetBubbleFrameView()->set_background(NULL);
116 137
117 // Overrides border with AppListBubbleBorder. 138 // Overrides border with AppListBubbleBorder.
118 bubble_border_ = new AppListBubbleBorder(this); 139 bubble_border_ = new AppListBubbleBorder(this,
140 search_box_view_,
141 apps_view_,
142 search_results_view_);
119 GetBubbleFrameView()->SetBubbleBorder(bubble_border_); 143 GetBubbleFrameView()->SetBubbleBorder(bubble_border_);
120 SizeToContents(); // Recalcuates with new border. 144 SizeToContents(); // Recalcuates with new border.
121 145
122 UpdateModel(); 146 CreateModel();
123 } 147 }
124 148
125 void AppListView::AnimateShow(int duration_ms) { 149 void AppListView::AnimateShow(int duration_ms) {
126 if (bubble_style_) 150 if (bubble_style_)
127 return; 151 return;
128 152
129 ui::Layer* layer = model_view_->layer(); 153 ui::Layer* layer = apps_view_->layer();
130 ui::ScopedLayerAnimationSettings animation(layer->GetAnimator()); 154 ui::ScopedLayerAnimationSettings animation(layer->GetAnimator());
131 animation.SetTransitionDuration( 155 animation.SetTransitionDuration(
132 base::TimeDelta::FromMilliseconds(duration_ms)); 156 base::TimeDelta::FromMilliseconds(duration_ms));
133 animation.SetTweenType(ui::Tween::EASE_OUT); 157 animation.SetTweenType(ui::Tween::EASE_OUT);
134 model_view_->SetTransform(ui::Transform()); 158 apps_view_->SetTransform(ui::Transform());
135 } 159 }
136 160
137 void AppListView::AnimateHide(int duration_ms) { 161 void AppListView::AnimateHide(int duration_ms) {
138 if (bubble_style_) 162 if (bubble_style_)
139 return; 163 return;
140 164
141 ui::Layer* layer = model_view_->layer(); 165 ui::Layer* layer = apps_view_->layer();
142 ui::ScopedLayerAnimationSettings animation(layer->GetAnimator()); 166 ui::ScopedLayerAnimationSettings animation(layer->GetAnimator());
143 animation.SetTransitionDuration( 167 animation.SetTransitionDuration(
144 base::TimeDelta::FromMilliseconds(duration_ms)); 168 base::TimeDelta::FromMilliseconds(duration_ms));
145 animation.SetTweenType(ui::Tween::EASE_IN); 169 animation.SetTweenType(ui::Tween::EASE_IN);
146 model_view_->SetTransform(GetScaleTransform(model_view_)); 170 apps_view_->SetTransform(GetScaleTransform(apps_view_));
147 } 171 }
148 172
149 void AppListView::Close() { 173 void AppListView::Close() {
150 if (delegate_.get()) 174 if (delegate_.get())
151 delegate_->Close(); 175 delegate_->Close();
152 else 176 else
153 GetWidget()->Close(); 177 GetWidget()->Close();
154 } 178 }
155 179
156 void AppListView::UpdateBounds(const gfx::Rect& screen_bounds, 180 void AppListView::UpdateBounds(const gfx::Rect& screen_bounds,
157 const gfx::Rect& work_area) { 181 const gfx::Rect& work_area) {
158 if (bubble_style_) { 182 if (bubble_style_) {
159 SizeToContents(); 183 SizeToContents();
160 } else { 184 } else {
161 work_area_ = work_area; 185 work_area_ = work_area;
162 GetWidget()->SetBounds(screen_bounds); 186 GetWidget()->SetBounds(screen_bounds);
163 } 187 }
164 } 188 }
165 189
166 void AppListView::UpdateModel() { 190 void AppListView::CreateModel() {
167 if (delegate_.get()) { 191 if (delegate_.get()) {
192 // Creates a new model and update all references before releasing old one.
168 scoped_ptr<AppListModel> new_model(new AppListModel); 193 scoped_ptr<AppListModel> new_model(new AppListModel);
194
169 delegate_->SetModel(new_model.get()); 195 delegate_->SetModel(new_model.get());
170 delegate_->UpdateModel(std::string()); 196 apps_view_->SetModel(new_model->apps());
171 model_view_->SetModel(new_model.get()); 197
198 // search_box_view_ etc are not created for v1.
199 // TODO(xiyuan): Update this after v2 is ready.
200 if (search_box_view_)
201 search_box_view_->SetModel(new_model->search_box());
202 if (search_results_view_)
203 search_results_view_->SetResults(new_model->results());
204
172 model_.reset(new_model.release()); 205 model_.reset(new_model.release());
173 } 206 }
174 } 207 }
175 208
176 views::View* AppListView::GetInitiallyFocusedView() { 209 views::View* AppListView::GetInitiallyFocusedView() {
177 return model_view_; 210 if (bubble_style_)
211 return search_box_view_->search_box();
212 else
213 return apps_view_;
214 }
215
216 gfx::Size AppListView::GetPreferredSize() {
217 if (!bubble_style_)
218 return View::GetPreferredSize();
219
220 const int search_box_height = search_box_view_->GetPreferredSize().height();
221 const int grid_height = apps_view_->GetPreferredSize().height();
222 const int page_switcher_height =
223 page_switcher_view_->GetPreferredSize().height();
224 const int results_height = search_results_view_->GetPreferredSize().height();
225
226 int height = search_box_height + std::max(grid_height + page_switcher_height,
227 results_height);
228 return gfx::Size(kPreferredWidth, height);
178 } 229 }
179 230
180 void AppListView::Layout() { 231 void AppListView::Layout() {
181 gfx::Rect rect(GetContentsBounds()); 232 gfx::Rect rect(GetContentsBounds());
182 if (rect.IsEmpty()) 233 if (rect.IsEmpty())
183 return; 234 return;
184 235
185 if (bubble_style_) { 236 if (bubble_style_) {
186 views::View::Layout(); 237 rect.Inset(kInnerPadding, kInnerPadding);
238
239 const int x = rect.x();
240 const int width = rect.width();
241
242 // SeachBoxView, AppsGridView and PageSwitcher uses a vertical box layout.
243 int y = rect.y();
244 const int search_box_height = search_box_view_->GetPreferredSize().height();
245 gfx::Rect search_box_frame(gfx::Point(x, y),
246 gfx::Size(width, search_box_height));
247 search_box_view_->SetBoundsRect(rect.Intersect(search_box_frame));
248
249 y = search_box_view_->bounds().bottom();
250 const int grid_height = apps_view_->GetPreferredSize().height();
251 gfx::Rect grid_frame(gfx::Point(x, y), gfx::Size(width, grid_height));
252 apps_view_->SetBoundsRect(rect.Intersect(grid_frame));
253
254 y = apps_view_->bounds().bottom();
255 const int page_switcher_height = rect.bottom() - y;
256 gfx::Rect page_switcher_frame(gfx::Point(x, y),
257 gfx::Size(width, page_switcher_height));
258 page_switcher_view_->SetBoundsRect(rect.Intersect(page_switcher_frame));
259
260 // Results view is mutually exclusive with AppsGridView and PageSwitcher.
261 // It occupies the same space as those two views.
262 gfx::Rect results_frame(grid_frame.Union(page_switcher_frame));
263 search_results_view_->SetBoundsRect(rect.Intersect(results_frame));
187 } else { 264 } else {
188 // Gets work area rect, which is in screen coordinates. 265 // Gets work area rect, which is in screen coordinates.
189 gfx::Rect workarea(work_area_); 266 gfx::Rect workarea(work_area_);
190 267
191 // Converts |workarea| into view's coordinates. 268 // Converts |workarea| into view's coordinates.
192 gfx::Point origin(workarea.origin()); 269 gfx::Point origin(workarea.origin());
193 views::View::ConvertPointFromScreen(this, &origin); 270 views::View::ConvertPointFromScreen(this, &origin);
194 workarea.Offset(-origin.x(), -origin.y()); 271 workarea.Offset(-origin.x(), -origin.y());
195 272
196 rect = rect.Intersect(workarea); 273 rect = rect.Intersect(workarea);
197 model_view_->SetBoundsRect(rect); 274 apps_view_->SetBoundsRect(rect);
198 } 275 }
199 } 276 }
200 277
201 bool AppListView::OnKeyPressed(const views::KeyEvent& event) { 278 bool AppListView::OnKeyPressed(const views::KeyEvent& event) {
202 if (event.key_code() == ui::VKEY_ESCAPE) { 279 if (event.key_code() == ui::VKEY_ESCAPE) {
203 Close(); 280 Close();
204 return true; 281 return true;
205 } 282 }
206 283
207 return false; 284 return false;
208 } 285 }
209 286
210 bool AppListView::OnMousePressed(const views::MouseEvent& event) { 287 bool AppListView::OnMousePressed(const views::MouseEvent& event) {
211 // For full screen mode, if mouse click reaches us, this means user clicks 288 // For full screen mode, if mouse click reaches us, this means user clicks
212 // on blank area. So close. 289 // on blank area. So close.
213 if (!bubble_style_) 290 if (!bubble_style_)
214 Close(); 291 Close();
215 292
216 return true; 293 return true;
217 } 294 }
218 295
219 void AppListView::ButtonPressed(views::Button* sender, 296 void AppListView::ButtonPressed(views::Button* sender,
220 const views::Event& event) { 297 const views::Event& event) {
221 if (sender->GetClassName() != AppListItemView::kViewClassName) 298 if (sender->GetClassName() != AppListItemView::kViewClassName)
222 return; 299 return;
223 300
224 if (delegate_.get()) { 301 if (delegate_.get()) {
225 delegate_->OnAppListItemActivated( 302 delegate_->ActivateAppListItem(
226 static_cast<AppListItemView*>(sender)->model(), 303 static_cast<AppListItemView*>(sender)->model(),
227 event.flags()); 304 event.flags());
228 } 305 }
229 Close(); 306 Close();
230 } 307 }
231 308
232 gfx::Rect AppListView::GetBubbleBounds() { 309 gfx::Rect AppListView::GetBubbleBounds() {
233 // This happens before replacing the default border. 310 // This happens before replacing the default border.
234 if (!bubble_border_) 311 if (!bubble_border_)
235 return views::BubbleDelegateView::GetBubbleBounds(); 312 return views::BubbleDelegateView::GetBubbleBounds();
(...skipping 25 matching lines...) Expand all
261 // it points to the same position before the move. 338 // it points to the same position before the move.
262 bubble_border_->set_arrow_offset(-offset); 339 bubble_border_->set_arrow_offset(-offset);
263 340
264 // Repaints border if arrow offset is changed. 341 // Repaints border if arrow offset is changed.
265 if (bubble_border_->arrow_offset() != old_arrow_offset) 342 if (bubble_border_->arrow_offset() != old_arrow_offset)
266 GetBubbleFrameView()->SchedulePaint(); 343 GetBubbleFrameView()->SchedulePaint();
267 344
268 return bubble_rect; 345 return bubble_rect;
269 } 346 }
270 347
348 void AppListView::QueryChanged(SearchBoxView* sender) {
349 bool showing_search = search_results_view_->visible();
350 bool should_show_search = !model_->search_box()->text().empty();
351
352 if (delegate_.get()) {
353 if (should_show_search)
354 delegate_->StartSearch();
355 else
356 delegate_->StopSearch();
357 }
358
359 if (showing_search != should_show_search) {
360 // TODO(xiyuan): Animate this transition.
361 apps_view_->SetVisible(!should_show_search);
362 page_switcher_view_->SetVisible(!should_show_search);
363 search_results_view_->SetVisible(should_show_search);
364
365 // TODO(xiyuan): Highlight default match instead of the first.
366 if (search_results_view_->visible())
367 search_results_view_->SetSelectedIndex(0);
368
369 // Needs to repaint frame as well.
370 GetBubbleFrameView()->SchedulePaint();
371 }
372 }
373
374 void AppListView::OpenResult(const SearchResult& result, int event_flags) {
375 if (delegate_.get())
376 delegate_->OpenSearchResult(result, event_flags);
377 Close();
378 }
379
271 } // namespace app_list 380 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698