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 4c40b448ed9e2e1ba302d9d53c0c9d7ba4b1e148..8bfcd12f9e0214764ded66dd185fb16a209b6cb2 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,18 +79,23 @@ void ContentsView::SetDragAndDropHostOfCurrentAppList( |
} |
void ContentsView::SetActivePage(int page_index) { |
- if (active_page_ == page_index) |
+ if (GetActivePageIndex() == page_index) |
return; |
SetActivePageInternal(page_index, false); |
} |
+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 { |
@@ -103,9 +108,14 @@ int ContentsView::GetPageIndexForNamedPage(NamedPage named_page) const { |
return it->second; |
} |
+int ContentsView::NumLauncherPages() const { |
+ return pagination_model_.total_pages(); |
+} |
+ |
void ContentsView::SetActivePageInternal(int page_index, |
bool show_search_results) { |
- active_page_ = page_index; |
+ // Start animating to the new page. |
+ pagination_model_.SelectPage(page_index, true); |
ActivePageChanged(show_search_results); |
} |
@@ -127,8 +137,6 @@ void ContentsView::ActivePageChanged(bool show_search_results) { |
// Notify parent AppListMainView of the page change. |
app_list_main_view_->UpdateSearchBoxVisibility(); |
- |
- AnimateToIdealBounds(); |
} |
void ContentsView::ShowSearchResults(bool show) { |
@@ -146,49 +154,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). |
+ 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() { |
@@ -205,10 +213,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; |
} |
@@ -231,12 +248,27 @@ 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) { |
+ view_model_->view_at(i)->SetBoundsRect( |
+ i == pagination_model_.SelectedTargetPage() ? rect : offscreen_target); |
+ } |
} |
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) { |
@@ -259,6 +291,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; |