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
3 // found in the LICENSE file.
5 #include "ui/app_list/views/contents_view.h"
10 #include "base/logging.h"
11 #include "ui/app_list/app_list_constants.h"
12 #include "ui/app_list/app_list_switches.h"
13 #include "ui/app_list/app_list_view_delegate.h"
14 #include "ui/app_list/views/app_list_folder_view.h"
15 #include "ui/app_list/views/app_list_main_view.h"
16 #include "ui/app_list/views/apps_container_view.h"
17 #include "ui/app_list/views/apps_grid_view.h"
18 #include "ui/app_list/views/contents_switcher_view.h"
19 #include "ui/app_list/views/search_result_list_view.h"
20 #include "ui/app_list/views/start_page_view.h"
21 #include "ui/events/event.h"
22 #include "ui/gfx/animation/tween.h"
23 #include "ui/resources/grit/ui_resources.h"
24 #include "ui/views/view_model.h"
25 #include "ui/views/view_model_utils.h"
29 ContentsView::ContentsView(AppListMainView* app_list_main_view)
30 : search_results_view_(NULL),
31 start_page_view_(NULL),
32 app_list_main_view_(app_list_main_view),
33 contents_switcher_view_(NULL),
34 view_model_(new views::ViewModel),
35 page_before_search_(0) {
36 pagination_model_.SetTransitionDurations(kPageTransitionDurationInMs,
37 kOverscrollPageTransitionDurationMs);
38 pagination_model_.AddObserver(this);
41 ContentsView::~ContentsView() {
42 pagination_model_.RemoveObserver(this);
43 if (contents_switcher_view_)
44 pagination_model_.RemoveObserver(contents_switcher_view_);
47 void ContentsView::InitNamedPages(AppListModel* model,
48 AppListViewDelegate* view_delegate) {
51 if (app_list::switches::IsExperimentalAppListEnabled()) {
52 std::vector<views::View*> custom_page_views =
53 view_delegate->CreateCustomPageWebViews(GetLocalBounds().size());
54 for (std::vector<views::View*>::const_iterator it =
55 custom_page_views.begin();
56 it != custom_page_views.end();
58 AddLauncherPage(*it, IDR_APP_LIST_NOTIFICATIONS_ICON);
61 start_page_view_ = new StartPageView(app_list_main_view_, view_delegate);
63 start_page_view_, IDR_APP_LIST_SEARCH_ICON, NAMED_PAGE_START);
65 search_results_view_ =
66 new SearchResultListView(app_list_main_view_, view_delegate);
67 AddLauncherPage(search_results_view_, 0, NAMED_PAGE_SEARCH_RESULTS);
68 search_results_view_->SetResults(model->results());
71 apps_container_view_ = new AppsContainerView(app_list_main_view_, model);
74 apps_container_view_, IDR_APP_LIST_APPS_ICON, NAMED_PAGE_APPS);
76 int initial_page_index = app_list::switches::IsExperimentalAppListEnabled()
77 ? GetPageIndexForNamedPage(NAMED_PAGE_START)
78 : GetPageIndexForNamedPage(NAMED_PAGE_APPS);
79 DCHECK_GE(initial_page_index, 0);
81 page_before_search_ = initial_page_index;
82 pagination_model_.SelectPage(initial_page_index, false);
84 // Needed to update the main search box visibility.
85 ActivePageChanged(false);
88 void ContentsView::CancelDrag() {
89 if (apps_container_view_->apps_grid_view()->has_dragged_view())
90 apps_container_view_->apps_grid_view()->EndDrag(true);
91 if (apps_container_view_->app_list_folder_view()
93 ->has_dragged_view()) {
94 apps_container_view_->app_list_folder_view()->items_grid_view()->EndDrag(
99 void ContentsView::SetDragAndDropHostOfCurrentAppList(
100 ApplicationDragAndDropHost* drag_and_drop_host) {
101 apps_container_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host);
104 void ContentsView::SetContentsSwitcherView(
105 ContentsSwitcherView* contents_switcher_view) {
106 DCHECK(!contents_switcher_view_);
107 contents_switcher_view_ = contents_switcher_view;
108 if (contents_switcher_view_)
109 pagination_model_.AddObserver(contents_switcher_view_);
112 void ContentsView::SetActivePage(int page_index) {
113 if (GetActivePageIndex() == page_index)
116 SetActivePageInternal(page_index, false);
119 int ContentsView::GetActivePageIndex() const {
120 // The active page is changed at the beginning of an animation, not the end.
121 return pagination_model_.SelectedTargetPage();
124 bool ContentsView::IsNamedPageActive(NamedPage named_page) const {
125 int active_page_index = GetActivePageIndex();
126 return active_page_index >= 0 &&
127 GetPageIndexForNamedPage(named_page) == active_page_index;
130 int ContentsView::GetPageIndexForNamedPage(NamedPage named_page) const {
131 // Find the index of the view corresponding to the given named_page.
132 std::map<NamedPage, int>::const_iterator it =
133 named_page_to_view_.find(named_page);
134 if (it == named_page_to_view_.end())
140 int ContentsView::NumLauncherPages() const {
141 return pagination_model_.total_pages();
144 void ContentsView::SetActivePageInternal(int page_index,
145 bool show_search_results) {
146 if (!show_search_results)
147 page_before_search_ = page_index;
148 // Start animating to the new page.
149 pagination_model_.SelectPage(page_index, true);
150 ActivePageChanged(show_search_results);
153 void ContentsView::ActivePageChanged(bool show_search_results) {
154 // TODO(xiyuan): Highlight default match instead of the first.
155 if (IsNamedPageActive(NAMED_PAGE_SEARCH_RESULTS) &&
156 search_results_view_->visible()) {
157 search_results_view_->SetSelectedIndex(0);
159 if (search_results_view_)
160 search_results_view_->UpdateAutoLaunchState();
162 if (IsNamedPageActive(NAMED_PAGE_START)) {
163 if (show_search_results)
164 start_page_view_->ShowSearchResults();
166 start_page_view_->Reset();
169 // Notify parent AppListMainView of the page change.
170 app_list_main_view_->UpdateSearchBoxVisibility();
173 void ContentsView::ShowSearchResults(bool show) {
174 int search_page = GetPageIndexForNamedPage(
175 app_list::switches::IsExperimentalAppListEnabled()
177 : NAMED_PAGE_SEARCH_RESULTS);
178 DCHECK_GE(search_page, 0);
180 SetActivePageInternal(show ? search_page : page_before_search_, show);
183 bool ContentsView::IsShowingSearchResults() const {
184 return app_list::switches::IsExperimentalAppListEnabled()
185 ? IsNamedPageActive(NAMED_PAGE_START) &&
186 start_page_view_->IsShowingSearchResults()
187 : IsNamedPageActive(NAMED_PAGE_SEARCH_RESULTS);
190 gfx::Rect ContentsView::GetOffscreenPageBounds(int page_index) const {
191 gfx::Rect bounds(GetContentsBounds());
192 // The start page and search page origins are above; all other pages' origins
194 int page_height = bounds.height();
196 GetPageIndexForNamedPage(NAMED_PAGE_START) == page_index ||
197 GetPageIndexForNamedPage(NAMED_PAGE_SEARCH_RESULTS) == page_index;
198 bounds.set_y(origin_above ? -page_height : page_height);
202 void ContentsView::UpdatePageBounds() {
203 // The bounds calculations will potentially be mid-transition (depending on
204 // the state of the PaginationModel).
205 int current_page = std::max(0, pagination_model_.selected_page());
206 int target_page = current_page;
208 if (pagination_model_.has_transition()) {
209 const PaginationModel::Transition& transition =
210 pagination_model_.transition();
211 if (pagination_model_.is_valid_page(transition.target_page)) {
212 target_page = transition.target_page;
213 progress = transition.progress;
217 // Move |current_page| from 0 to its origin. Move |target_page| from its
219 gfx::Rect on_screen(GetContentsBounds());
220 gfx::Rect current_page_origin(GetOffscreenPageBounds(current_page));
221 gfx::Rect target_page_origin(GetOffscreenPageBounds(target_page));
222 gfx::Rect current_page_rect(
223 gfx::Tween::RectValueBetween(progress, on_screen, current_page_origin));
224 gfx::Rect target_page_rect(
225 gfx::Tween::RectValueBetween(progress, target_page_origin, on_screen));
227 view_model_->view_at(current_page)->SetBoundsRect(current_page_rect);
228 view_model_->view_at(target_page)->SetBoundsRect(target_page_rect);
231 PaginationModel* ContentsView::GetAppsPaginationModel() {
232 return apps_container_view_->apps_grid_view()->pagination_model();
235 void ContentsView::ShowFolderContent(AppListFolderItem* item) {
236 apps_container_view_->ShowActiveFolder(item);
239 void ContentsView::Prerender() {
240 apps_container_view_->apps_grid_view()->Prerender();
243 views::View* ContentsView::GetPageView(int index) {
244 return view_model_->view_at(index);
247 void ContentsView::AddBlankPageForTesting() {
248 AddLauncherPage(new views::View, 0);
251 int ContentsView::AddLauncherPage(views::View* view, int resource_id) {
252 int page_index = view_model_->view_size();
254 view_model_->Add(view, page_index);
255 if (contents_switcher_view_ && resource_id)
256 contents_switcher_view_->AddSwitcherButton(resource_id, page_index);
257 pagination_model_.SetTotalPages(view_model_->view_size());
261 int ContentsView::AddLauncherPage(views::View* view,
263 NamedPage named_page) {
264 int page_index = AddLauncherPage(view, resource_id);
265 named_page_to_view_.insert(std::pair<NamedPage, int>(named_page, page_index));
269 gfx::Size ContentsView::GetPreferredSize() const {
270 const gfx::Size container_size =
271 apps_container_view_->apps_grid_view()->GetPreferredSize();
272 const gfx::Size results_size = search_results_view_
273 ? search_results_view_->GetPreferredSize()
276 int width = std::max(container_size.width(), results_size.width());
277 int height = std::max(container_size.height(), results_size.height());
278 return gfx::Size(width, height);
281 void ContentsView::Layout() {
282 // Immediately finish all current animations.
283 pagination_model_.FinishAnimation();
285 // Move the current view onto the screen, and all other views off screen to
286 // the left. (Since we are not animating, we don't need to be careful about
287 // which side we place the off-screen views onto.)
288 gfx::Rect rect(GetContentsBounds());
292 gfx::Rect offscreen_target(rect);
293 offscreen_target.set_x(-rect.width());
295 for (int i = 0; i < view_model_->view_size(); ++i) {
296 view_model_->view_at(i)->SetBoundsRect(
297 i == pagination_model_.SelectedTargetPage() ? rect : offscreen_target);
301 bool ContentsView::OnKeyPressed(const ui::KeyEvent& event) {
302 return view_model_->view_at(GetActivePageIndex())->OnKeyPressed(event);
305 void ContentsView::TotalPagesChanged() {
308 void ContentsView::SelectedPageChanged(int old_selected, int new_selected) {
311 void ContentsView::TransitionStarted() {
314 void ContentsView::TransitionChanged() {
318 } // namespace app_list