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

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

Issue 316393002: App list uses PaginationModel to transition between pages. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase. Created 6 years, 6 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/contents_view.h" 5 #include "ui/app_list/views/contents_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "ui/app_list/app_list_constants.h" 10 #include "ui/app_list/app_list_constants.h"
11 #include "ui/app_list/app_list_switches.h" 11 #include "ui/app_list/app_list_switches.h"
12 #include "ui/app_list/app_list_view_delegate.h" 12 #include "ui/app_list/app_list_view_delegate.h"
13 #include "ui/app_list/pagination_model.h"
14 #include "ui/app_list/views/app_list_folder_view.h" 13 #include "ui/app_list/views/app_list_folder_view.h"
15 #include "ui/app_list/views/app_list_main_view.h" 14 #include "ui/app_list/views/app_list_main_view.h"
16 #include "ui/app_list/views/apps_container_view.h" 15 #include "ui/app_list/views/apps_container_view.h"
17 #include "ui/app_list/views/apps_grid_view.h" 16 #include "ui/app_list/views/apps_grid_view.h"
18 #include "ui/app_list/views/search_result_list_view.h" 17 #include "ui/app_list/views/search_result_list_view.h"
19 #include "ui/app_list/views/start_page_view.h" 18 #include "ui/app_list/views/start_page_view.h"
20 #include "ui/events/event.h" 19 #include "ui/events/event.h"
21 #include "ui/views/animation/bounds_animator.h"
22 #include "ui/views/view_model.h" 20 #include "ui/views/view_model.h"
23 #include "ui/views/view_model_utils.h" 21 #include "ui/views/view_model_utils.h"
24 22
25 namespace app_list { 23 namespace app_list {
26 24
27 namespace { 25 namespace {
28 26
29 const int kMinMouseWheelToSwitchPage = 20; 27 const int kMinMouseWheelToSwitchPage = 20;
30 const int kMinScrollToSwitchPage = 20; 28 const int kMinScrollToSwitchPage = 20;
31 const int kMinHorizVelocityToSwitchPage = 800; 29 const int kMinHorizVelocityToSwitchPage = 800;
32 30
33 const double kFinishTransitionThreshold = 0.33; 31 const double kFinishTransitionThreshold = 0.33;
34 32
35 } // namespace 33 } // namespace
36 34
37 ContentsView::ContentsView(AppListMainView* app_list_main_view, 35 ContentsView::ContentsView(AppListMainView* app_list_main_view,
38 AppListModel* model, 36 AppListModel* model,
39 AppListViewDelegate* view_delegate) 37 AppListViewDelegate* view_delegate)
40 : start_page_view_(NULL), 38 : start_page_view_(NULL),
41 app_list_main_view_(app_list_main_view), 39 app_list_main_view_(app_list_main_view),
42 view_model_(new views::ViewModel), 40 view_model_(new views::ViewModel) {
43 bounds_animator_(new views::BoundsAnimator(this)) {
44 DCHECK(model); 41 DCHECK(model);
45 42
46 search_results_view_ = 43 search_results_view_ =
47 new SearchResultListView(app_list_main_view, view_delegate); 44 new SearchResultListView(app_list_main_view, view_delegate);
48 AddLauncherPage(search_results_view_, NAMED_PAGE_SEARCH_RESULTS); 45 AddLauncherPage(search_results_view_, NAMED_PAGE_SEARCH_RESULTS);
49 46
50 if (app_list::switches::IsExperimentalAppListEnabled()) { 47 if (app_list::switches::IsExperimentalAppListEnabled()) {
51 start_page_view_ = new StartPageView(app_list_main_view, view_delegate); 48 start_page_view_ = new StartPageView(app_list_main_view, view_delegate);
52 AddLauncherPage(start_page_view_, NAMED_PAGE_START); 49 AddLauncherPage(start_page_view_, NAMED_PAGE_START);
53 } 50 }
54 51
55 apps_container_view_ = new AppsContainerView(app_list_main_view, model); 52 apps_container_view_ = new AppsContainerView(app_list_main_view, model);
56 active_page_ = AddLauncherPage(apps_container_view_, NAMED_PAGE_APPS); 53 int apps_page_index = AddLauncherPage(apps_container_view_, NAMED_PAGE_APPS);
57 54
58 search_results_view_->SetResults(model->results()); 55 search_results_view_->SetResults(model->results());
56
57 pagination_model_.SetTotalPages(view_model_->view_size());
58 pagination_model_.SelectPage(apps_page_index, false);
59 pagination_model_.AddObserver(this);
59 } 60 }
60 61
61 ContentsView::~ContentsView() { 62 ContentsView::~ContentsView() {
63 pagination_model_.RemoveObserver(this);
62 } 64 }
63 65
64 void ContentsView::CancelDrag() { 66 void ContentsView::CancelDrag() {
65 if (apps_container_view_->apps_grid_view()->has_dragged_view()) 67 if (apps_container_view_->apps_grid_view()->has_dragged_view())
66 apps_container_view_->apps_grid_view()->EndDrag(true); 68 apps_container_view_->apps_grid_view()->EndDrag(true);
67 if (apps_container_view_->app_list_folder_view() 69 if (apps_container_view_->app_list_folder_view()
68 ->items_grid_view() 70 ->items_grid_view()
69 ->has_dragged_view()) { 71 ->has_dragged_view()) {
70 apps_container_view_->app_list_folder_view()->items_grid_view()->EndDrag( 72 apps_container_view_->app_list_folder_view()->items_grid_view()->EndDrag(
71 true); 73 true);
72 } 74 }
73 } 75 }
74 76
75 void ContentsView::SetDragAndDropHostOfCurrentAppList( 77 void ContentsView::SetDragAndDropHostOfCurrentAppList(
76 ApplicationDragAndDropHost* drag_and_drop_host) { 78 ApplicationDragAndDropHost* drag_and_drop_host) {
77 apps_container_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); 79 apps_container_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host);
78 } 80 }
79 81
80 void ContentsView::SetActivePage(int page_index) { 82 void ContentsView::SetActivePage(int page_index) {
81 if (active_page_ == page_index) 83 if (GetActivePageIndex() == page_index)
82 return; 84 return;
83 85
84 active_page_ = page_index; 86 // Start animating to the new page.
87 pagination_model_.SelectPage(page_index, true);
85 ActivePageChanged(); 88 ActivePageChanged();
86 } 89 }
87 90
91 int ContentsView::GetActivePageIndex() const {
92 // The active page is changed at the beginning of an animation, not the end.
93 return pagination_model_.SelectedTargetPage();
94 }
95
88 bool ContentsView::IsNamedPageActive(NamedPage named_page) const { 96 bool ContentsView::IsNamedPageActive(NamedPage named_page) const {
89 std::map<NamedPage, int>::const_iterator it = 97 std::map<NamedPage, int>::const_iterator it =
90 named_page_to_view_.find(named_page); 98 named_page_to_view_.find(named_page);
91 if (it == named_page_to_view_.end()) 99 if (it == named_page_to_view_.end())
92 return false; 100 return false;
93 return it->second == active_page_; 101 return it->second == GetActivePageIndex();
94 } 102 }
95 103
96 int ContentsView::GetPageIndexForNamedPage(NamedPage named_page) const { 104 int ContentsView::GetPageIndexForNamedPage(NamedPage named_page) const {
97 // Find the index of the view corresponding to the given named_page. 105 // Find the index of the view corresponding to the given named_page.
98 std::map<NamedPage, int>::const_iterator it = 106 std::map<NamedPage, int>::const_iterator it =
99 named_page_to_view_.find(named_page); 107 named_page_to_view_.find(named_page);
100 // GetPageIndexForNamedPage should never be called on a named_page that does 108 // GetPageIndexForNamedPage should never be called on a named_page that does
101 // not have a corresponding view. 109 // not have a corresponding view.
102 DCHECK(it != named_page_to_view_.end()); 110 DCHECK(it != named_page_to_view_.end());
103 return it->second; 111 return it->second;
104 } 112 }
105 113
106 void ContentsView::ActivePageChanged() { 114 void ContentsView::ActivePageChanged() {
107 // TODO(xiyuan): Highlight default match instead of the first. 115 // TODO(xiyuan): Highlight default match instead of the first.
108 if (IsNamedPageActive(NAMED_PAGE_SEARCH_RESULTS) && 116 if (IsNamedPageActive(NAMED_PAGE_SEARCH_RESULTS) &&
109 search_results_view_->visible()) { 117 search_results_view_->visible()) {
110 search_results_view_->SetSelectedIndex(0); 118 search_results_view_->SetSelectedIndex(0);
111 } 119 }
112 search_results_view_->UpdateAutoLaunchState(); 120 search_results_view_->UpdateAutoLaunchState();
113 121
114 // Notify parent AppListMainView of the page change. 122 // Notify parent AppListMainView of the page change.
115 app_list_main_view_->OnContentsViewActivePageChanged(); 123 app_list_main_view_->OnContentsViewActivePageChanged();
116 124
117 if (IsNamedPageActive(NAMED_PAGE_START)) 125 if (IsNamedPageActive(NAMED_PAGE_START))
118 start_page_view_->Reset(); 126 start_page_view_->Reset();
119
120 AnimateToIdealBounds();
121 } 127 }
122 128
123 void ContentsView::CalculateIdealBounds() { 129 void ContentsView::CalculateAndSetBounds(bool ideal) {
124 gfx::Rect rect(GetContentsBounds()); 130 gfx::Rect rect(GetContentsBounds());
125 if (rect.IsEmpty()) 131 if (rect.IsEmpty())
126 return; 132 return;
127 133
128 if (app_list::switches::IsExperimentalAppListEnabled()) { 134 // The bounds calculations will potentially be mid-transition (depending on
129 gfx::Rect incoming_target(rect); 135 // the state of the PaginationModel).
130 gfx::Rect outgoing_target(rect); 136 int current_page = std::max(0, pagination_model_.selected_page());
calamity 2014/06/12 03:05:08 When can this be negative?
Matt Giuca 2014/06/16 00:59:05 pagination_model_.selected_page() is -1 by default
131 outgoing_target.set_x(-outgoing_target.width()); 137 int target_page = current_page;
132 138 double progress = 1;
133 for (int i = 0; i < view_model_->view_size(); ++i) { 139 if (pagination_model_.has_transition()) {
134 view_model_->set_ideal_bounds( 140 const PaginationModel::Transition& transition =
135 i, i == active_page_ ? incoming_target : outgoing_target); 141 pagination_model_.transition();
142 if (pagination_model_.is_valid_page(transition.target_page)) {
143 target_page = transition.target_page;
144 // If |ideal|, assume that any pending animation has already completed.
145 if (!ideal)
146 progress = transition.progress;
136 } 147 }
137 return;
138 } 148 }
139 149
140 gfx::Rect container_frame(rect); 150 gfx::Rect incoming_target(rect);
141 gfx::Rect results_frame(rect); 151 gfx::Rect outgoing_target(rect);
152 int dir = target_page > current_page ? -1 : 1;
142 153
143 // Offsets apps grid and result list based on |active_page_|. 154 if (app_list::switches::IsExperimentalAppListEnabled()) {
144 // SearchResultListView is on top of apps grid. Visible view is left in 155 // The experimental app list transitions horizontally.
145 // visible area and invisible ones is put out of the visible area. 156 int page_width = rect.width();
146 int contents_area_height = rect.height(); 157 int transition_offset = progress * page_width * dir;
147 if (IsNamedPageActive(NAMED_PAGE_APPS))
148 results_frame.Offset(0, -contents_area_height);
149 else if (IsNamedPageActive(NAMED_PAGE_SEARCH_RESULTS))
150 container_frame.Offset(0, contents_area_height);
151 else
152 NOTREACHED() << "Page " << active_page_ << " invalid in current app list.";
153 158
154 view_model_->set_ideal_bounds(GetPageIndexForNamedPage(NAMED_PAGE_APPS), 159 outgoing_target.set_x(transition_offset);
155 container_frame); 160 incoming_target.set_x(dir < 0 ? transition_offset + page_width
156 view_model_->set_ideal_bounds( 161 : transition_offset - page_width);
157 GetPageIndexForNamedPage(NAMED_PAGE_SEARCH_RESULTS), results_frame); 162 } else {
158 } 163 // The normal app list transitions vertically.
164 int page_height = rect.height();
165 int transition_offset = progress * page_height * dir;
159 166
160 void ContentsView::AnimateToIdealBounds() { 167 outgoing_target.set_y(transition_offset);
161 CalculateIdealBounds(); 168 incoming_target.set_y(dir < 0 ? transition_offset + page_height
162 for (int i = 0; i < view_model_->view_size(); ++i) { 169 : transition_offset - page_height);
163 bounds_animator_->AnimateViewTo(view_model_->view_at(i), 170 }
164 view_model_->ideal_bounds(i)); 171
172 if (ideal) {
173 view_model_->set_ideal_bounds(current_page, outgoing_target);
174 view_model_->set_ideal_bounds(target_page, incoming_target);
calamity 2014/06/12 03:05:08 It looks like ideal bounds aren't really used anyw
Matt Giuca 2014/06/16 00:59:05 I guess if something isn't used at all, but semant
175 } else {
176 view_model_->view_at(current_page)->SetBoundsRect(outgoing_target);
177 view_model_->view_at(target_page)->SetBoundsRect(incoming_target);
165 } 178 }
166 } 179 }
167 180
168 PaginationModel* ContentsView::GetAppsPaginationModel() { 181 PaginationModel* ContentsView::GetAppsPaginationModel() {
169 return apps_container_view_->apps_grid_view()->pagination_model(); 182 return apps_container_view_->apps_grid_view()->pagination_model();
170 } 183 }
171 184
172 void ContentsView::ShowSearchResults(bool show) { 185 void ContentsView::ShowSearchResults(bool show) {
173 NamedPage new_named_page = show ? NAMED_PAGE_SEARCH_RESULTS : NAMED_PAGE_APPS; 186 NamedPage new_named_page = show ? NAMED_PAGE_SEARCH_RESULTS : NAMED_PAGE_APPS;
174 SetActivePage(GetPageIndexForNamedPage(new_named_page)); 187 SetActivePage(GetPageIndexForNamedPage(new_named_page));
(...skipping 15 matching lines...) Expand all
190 view_model_->Add(view, page_index); 203 view_model_->Add(view, page_index);
191 return page_index; 204 return page_index;
192 } 205 }
193 206
194 int ContentsView::AddLauncherPage(views::View* view, NamedPage named_page) { 207 int ContentsView::AddLauncherPage(views::View* view, NamedPage named_page) {
195 int page_index = AddLauncherPage(view); 208 int page_index = AddLauncherPage(view);
196 named_page_to_view_.insert(std::pair<NamedPage, int>(named_page, page_index)); 209 named_page_to_view_.insert(std::pair<NamedPage, int>(named_page, page_index));
197 return page_index; 210 return page_index;
198 } 211 }
199 212
213 void ContentsView::FinishCurrentAnimationForTests() {
214 if (!pagination_model_.has_transition())
215 return;
calamity 2014/06/12 03:05:08 nit: blank line after early return.
Matt Giuca 2014/06/16 00:59:05 Done.
216 pagination_model_.SelectPage(pagination_model_.transition().target_page,
217 false);
218 }
219
200 gfx::Size ContentsView::GetPreferredSize() const { 220 gfx::Size ContentsView::GetPreferredSize() const {
201 const gfx::Size container_size = 221 const gfx::Size container_size =
202 apps_container_view_->apps_grid_view()->GetPreferredSize(); 222 apps_container_view_->apps_grid_view()->GetPreferredSize();
203 const gfx::Size results_size = search_results_view_->GetPreferredSize(); 223 const gfx::Size results_size = search_results_view_->GetPreferredSize();
204 224
205 int width = std::max(container_size.width(), results_size.width()); 225 int width = std::max(container_size.width(), results_size.width());
206 int height = std::max(container_size.height(), results_size.height()); 226 int height = std::max(container_size.height(), results_size.height());
207 return gfx::Size(width, height); 227 return gfx::Size(width, height);
208 } 228 }
209 229
210 void ContentsView::Layout() { 230 void ContentsView::Layout() {
211 CalculateIdealBounds(); 231 CalculateAndSetBounds(true);
212 views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); 232 views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_);
213 } 233 }
214 234
215 bool ContentsView::OnKeyPressed(const ui::KeyEvent& event) { 235 bool ContentsView::OnKeyPressed(const ui::KeyEvent& event) {
216 return view_model_->view_at(active_page_)->OnKeyPressed(event); 236 return view_model_->view_at(GetActivePageIndex())->OnKeyPressed(event);
217 } 237 }
218 238
219 bool ContentsView::OnMouseWheel(const ui::MouseWheelEvent& event) { 239 bool ContentsView::OnMouseWheel(const ui::MouseWheelEvent& event) {
220 if (!IsNamedPageActive(NAMED_PAGE_APPS)) 240 if (!IsNamedPageActive(NAMED_PAGE_APPS))
221 return false; 241 return false;
222 242
223 int offset; 243 int offset;
224 if (abs(event.x_offset()) > abs(event.y_offset())) 244 if (abs(event.x_offset()) > abs(event.y_offset()))
225 offset = event.x_offset(); 245 offset = event.x_offset();
226 else 246 else
227 offset = event.y_offset(); 247 offset = event.y_offset();
228 248
229 if (abs(offset) > kMinMouseWheelToSwitchPage) { 249 if (abs(offset) > kMinMouseWheelToSwitchPage) {
230 if (!GetAppsPaginationModel()->has_transition()) { 250 if (!GetAppsPaginationModel()->has_transition()) {
231 GetAppsPaginationModel()->SelectPageRelative(offset > 0 ? -1 : 1, true); 251 GetAppsPaginationModel()->SelectPageRelative(offset > 0 ? -1 : 1, true);
232 } 252 }
233 return true; 253 return true;
234 } 254 }
235 255
236 return false; 256 return false;
237 } 257 }
238 258
259 void ContentsView::TotalPagesChanged() {
260 }
261
262 void ContentsView::SelectedPageChanged(int old_selected, int new_selected) {
263 }
264
265 void ContentsView::TransitionStarted() {
266 }
267
268 void ContentsView::TransitionChanged() {
269 CalculateAndSetBounds(false);
270 }
271
239 void ContentsView::OnGestureEvent(ui::GestureEvent* event) { 272 void ContentsView::OnGestureEvent(ui::GestureEvent* event) {
240 if (!IsNamedPageActive(NAMED_PAGE_APPS)) 273 if (!IsNamedPageActive(NAMED_PAGE_APPS))
241 return; 274 return;
242 275
243 switch (event->type()) { 276 switch (event->type()) {
244 case ui::ET_GESTURE_SCROLL_BEGIN: 277 case ui::ET_GESTURE_SCROLL_BEGIN:
245 GetAppsPaginationModel()->StartScroll(); 278 GetAppsPaginationModel()->StartScroll();
246 event->SetHandled(); 279 event->SetHandled();
247 return; 280 return;
248 case ui::ET_GESTURE_SCROLL_UPDATE: 281 case ui::ET_GESTURE_SCROLL_UPDATE:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 if (std::abs(offset) > kMinScrollToSwitchPage) { 320 if (std::abs(offset) > kMinScrollToSwitchPage) {
288 if (!GetAppsPaginationModel()->has_transition()) { 321 if (!GetAppsPaginationModel()->has_transition()) {
289 GetAppsPaginationModel()->SelectPageRelative(offset > 0 ? -1 : 1, true); 322 GetAppsPaginationModel()->SelectPageRelative(offset > 0 ? -1 : 1, true);
290 } 323 }
291 event->SetHandled(); 324 event->SetHandled();
292 event->StopPropagation(); 325 event->StopPropagation();
293 } 326 }
294 } 327 }
295 328
296 } // namespace app_list 329 } // namespace app_list
OLDNEW
« ui/app_list/views/contents_view.h ('K') | « ui/app_list/views/contents_view.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698