Chromium Code Reviews| Index: ui/app_list/views/contents_view.cc |
| diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc |
| index 188926076b313d92e5dc8440bac2a86997721e88..148a8e573506e7a703651c28010c6998f8f99e63 100644 |
| --- a/ui/app_list/views/contents_view.cc |
| +++ b/ui/app_list/views/contents_view.cc |
| @@ -10,7 +10,6 @@ |
| #include "ui/app_list/app_list_constants.h" |
| #include "ui/app_list/app_list_switches.h" |
| #include "ui/app_list/app_list_view_delegate.h" |
| -#include "ui/app_list/pagination_model.h" |
| #include "ui/app_list/views/app_list_folder_view.h" |
| #include "ui/app_list/views/app_list_main_view.h" |
| #include "ui/app_list/views/apps_container_view.h" |
| @@ -18,7 +17,6 @@ |
| #include "ui/app_list/views/search_result_list_view.h" |
| #include "ui/app_list/views/start_page_view.h" |
| #include "ui/events/event.h" |
| -#include "ui/views/animation/bounds_animator.h" |
| #include "ui/views/view_model.h" |
| #include "ui/views/view_model_utils.h" |
| @@ -40,8 +38,7 @@ ContentsView::ContentsView(AppListMainView* app_list_main_view, |
| : search_results_view_(NULL), |
| start_page_view_(NULL), |
| app_list_main_view_(app_list_main_view), |
| - view_model_(new views::ViewModel), |
| - bounds_animator_(new views::BoundsAnimator(this)) { |
| + view_model_(new views::ViewModel) { |
| DCHECK(model); |
| if (app_list::switches::IsExperimentalAppListEnabled()) { |
| @@ -55,11 +52,14 @@ ContentsView::ContentsView(AppListMainView* app_list_main_view, |
| } |
| apps_container_view_ = new AppsContainerView(app_list_main_view, model); |
| - active_page_ = AddLauncherPage(apps_container_view_, NAMED_PAGE_APPS); |
| + int apps_page_index = AddLauncherPage(apps_container_view_, NAMED_PAGE_APPS); |
| + pagination_model_.SelectPage(apps_page_index, false); |
| + pagination_model_.AddObserver(this); |
| } |
| ContentsView::~ContentsView() { |
| + pagination_model_.RemoveObserver(this); |
| } |
| void ContentsView::CancelDrag() { |
| @@ -79,19 +79,25 @@ void ContentsView::SetDragAndDropHostOfCurrentAppList( |
| } |
| void ContentsView::SetActivePage(int page_index) { |
| - if (active_page_ == page_index) |
| + if (GetActivePageIndex() == page_index) |
| return; |
| - active_page_ = page_index; |
| + // Start animating to the new page. |
| + pagination_model_.SelectPage(page_index, true); |
| ActivePageChanged(); |
| } |
| +int ContentsView::GetActivePageIndex() const { |
| + // The active page is changed at the beginning of an animation, not the end. |
| + return pagination_model_.SelectedTargetPage(); |
| +} |
| + |
| bool ContentsView::IsNamedPageActive(NamedPage named_page) const { |
| std::map<NamedPage, int>::const_iterator it = |
| named_page_to_view_.find(named_page); |
| if (it == named_page_to_view_.end()) |
| return false; |
| - return it->second == active_page_; |
| + return it->second == GetActivePageIndex(); |
| } |
| int ContentsView::GetPageIndexForNamedPage(NamedPage named_page) const { |
| @@ -104,6 +110,10 @@ int ContentsView::GetPageIndexForNamedPage(NamedPage named_page) const { |
| return it->second; |
| } |
| +int ContentsView::NumLauncherPages() const { |
| + return pagination_model_.total_pages(); |
| +} |
| + |
| void ContentsView::ActivePageChanged() { |
| // TODO(xiyuan): Highlight default match instead of the first. |
| if (IsNamedPageActive(NAMED_PAGE_SEARCH_RESULTS) && |
| @@ -118,8 +128,6 @@ void ContentsView::ActivePageChanged() { |
| // Notify parent AppListMainView of the page change. |
| app_list_main_view_->UpdateSearchBoxVisibility(); |
| - |
| - AnimateToIdealBounds(); |
| } |
| void ContentsView::ShowSearchResults(bool show) { |
| @@ -145,49 +153,49 @@ bool ContentsView::IsShowingSearchResults() const { |
| : IsNamedPageActive(NAMED_PAGE_SEARCH_RESULTS); |
| } |
| -void ContentsView::CalculateIdealBounds() { |
| +void ContentsView::UpdatePageBounds() { |
| gfx::Rect rect(GetContentsBounds()); |
| if (rect.IsEmpty()) |
| return; |
| - if (app_list::switches::IsExperimentalAppListEnabled()) { |
| - gfx::Rect incoming_target(rect); |
| - gfx::Rect outgoing_target(rect); |
| - outgoing_target.set_x(-outgoing_target.width()); |
| - |
| - for (int i = 0; i < view_model_->view_size(); ++i) { |
| - view_model_->set_ideal_bounds( |
| - i, i == active_page_ ? incoming_target : outgoing_target); |
| + // The bounds calculations will potentially be mid-transition (depending on |
| + // the state of the PaginationModel). |
|
calamity
2014/06/17 05:43:45
This comment is a bit weird now since this is only
Matt Giuca
2014/06/17 06:04:07
To the second point: thought about it, but I think
|
| + int current_page = std::max(0, pagination_model_.selected_page()); |
| + int target_page = current_page; |
| + double progress = 1; |
| + if (pagination_model_.has_transition()) { |
| + const PaginationModel::Transition& transition = |
| + pagination_model_.transition(); |
| + if (pagination_model_.is_valid_page(transition.target_page)) { |
| + target_page = transition.target_page; |
| + progress = transition.progress; |
| } |
| - return; |
| } |
| - gfx::Rect container_frame(rect); |
| - gfx::Rect results_frame(rect); |
| - |
| - // Offsets apps grid and result list based on |active_page_|. |
| - // SearchResultListView is on top of apps grid. Visible view is left in |
| - // visible area and invisible ones is put out of the visible area. |
| - int contents_area_height = rect.height(); |
| - if (IsNamedPageActive(NAMED_PAGE_APPS)) |
| - results_frame.Offset(0, -contents_area_height); |
| - else if (IsNamedPageActive(NAMED_PAGE_SEARCH_RESULTS)) |
| - container_frame.Offset(0, contents_area_height); |
| - else |
| - NOTREACHED() << "Page " << active_page_ << " invalid in current app list."; |
| + gfx::Rect incoming_target(rect); |
| + gfx::Rect outgoing_target(rect); |
| + int dir = target_page > current_page ? -1 : 1; |
| - view_model_->set_ideal_bounds(GetPageIndexForNamedPage(NAMED_PAGE_APPS), |
| - container_frame); |
| - view_model_->set_ideal_bounds( |
| - GetPageIndexForNamedPage(NAMED_PAGE_SEARCH_RESULTS), results_frame); |
| -} |
| + if (app_list::switches::IsExperimentalAppListEnabled()) { |
| + // The experimental app list transitions horizontally. |
| + int page_width = rect.width(); |
| + int transition_offset = progress * page_width * dir; |
| -void ContentsView::AnimateToIdealBounds() { |
| - CalculateIdealBounds(); |
| - for (int i = 0; i < view_model_->view_size(); ++i) { |
| - bounds_animator_->AnimateViewTo(view_model_->view_at(i), |
| - view_model_->ideal_bounds(i)); |
| + outgoing_target.set_x(transition_offset); |
| + incoming_target.set_x(dir < 0 ? transition_offset + page_width |
| + : transition_offset - page_width); |
| + } else { |
| + // The normal app list transitions vertically. |
| + int page_height = rect.height(); |
| + int transition_offset = progress * page_height * dir; |
| + |
| + outgoing_target.set_y(transition_offset); |
| + incoming_target.set_y(dir < 0 ? transition_offset + page_height |
| + : transition_offset - page_height); |
| } |
| + |
| + view_model_->view_at(current_page)->SetBoundsRect(outgoing_target); |
| + view_model_->view_at(target_page)->SetBoundsRect(incoming_target); |
| } |
| PaginationModel* ContentsView::GetAppsPaginationModel() { |
| @@ -204,10 +212,19 @@ void ContentsView::Prerender() { |
| apps_container_view_->apps_grid_view()->Prerender(selected_page); |
| } |
| +views::View* ContentsView::GetPageView(int index) { |
| + return view_model_->view_at(index); |
| +} |
| + |
| +void ContentsView::AddBlankPageForTesting() { |
| + AddLauncherPage(new views::View); |
| +} |
| + |
| int ContentsView::AddLauncherPage(views::View* view) { |
| int page_index = view_model_->view_size(); |
| AddChildView(view); |
| view_model_->Add(view, page_index); |
| + pagination_model_.SetTotalPages(view_model_->view_size()); |
| return page_index; |
| } |
| @@ -230,12 +247,30 @@ gfx::Size ContentsView::GetPreferredSize() const { |
| } |
| void ContentsView::Layout() { |
| - CalculateIdealBounds(); |
| - views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); |
| + // Immediately finish all current animations. |
| + pagination_model_.FinishAnimation(); |
| + |
| + // Move the current view onto the screen, and all other views off screen to |
| + // the left. (Since we are not animating, we don't need to be careful about |
| + // which side we place the off-screen views onto.) |
| + gfx::Rect rect(GetContentsBounds()); |
| + if (rect.IsEmpty()) |
| + return; |
| + |
| + gfx::Rect offscreen_target(rect); |
| + offscreen_target.set_x(-rect.width()); |
| + |
| + for (int i = 0; i < view_model_->view_size(); ++i) { |
| + views::View* view = view_model_->view_at(i); |
| + if (i == pagination_model_.SelectedTargetPage()) |
| + view->SetBoundsRect(rect); |
| + else |
| + view->SetBoundsRect(offscreen_target); |
|
calamity
2014/06/17 05:43:45
Consider ternary operator.
Matt Giuca
2014/06/17 06:04:07
Done.
|
| + } |
| } |
| bool ContentsView::OnKeyPressed(const ui::KeyEvent& event) { |
| - return view_model_->view_at(active_page_)->OnKeyPressed(event); |
| + return view_model_->view_at(GetActivePageIndex())->OnKeyPressed(event); |
| } |
| bool ContentsView::OnMouseWheel(const ui::MouseWheelEvent& event) { |
| @@ -258,6 +293,19 @@ bool ContentsView::OnMouseWheel(const ui::MouseWheelEvent& event) { |
| return false; |
| } |
| +void ContentsView::TotalPagesChanged() { |
| +} |
| + |
| +void ContentsView::SelectedPageChanged(int old_selected, int new_selected) { |
| +} |
| + |
| +void ContentsView::TransitionStarted() { |
| +} |
| + |
| +void ContentsView::TransitionChanged() { |
| + UpdatePageBounds(); |
| +} |
| + |
| void ContentsView::OnGestureEvent(ui::GestureEvent* event) { |
| if (!IsNamedPageActive(NAMED_PAGE_APPS)) |
| return; |