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/resources/grit/ui_resources.h"
23 #include "ui/views/view_model.h"
24 #include "ui/views/view_model_utils.h"
28 ContentsView::ContentsView(AppListMainView
* app_list_main_view
)
29 : search_results_view_(NULL
),
30 start_page_view_(NULL
),
31 app_list_main_view_(app_list_main_view
),
32 contents_switcher_view_(NULL
),
33 view_model_(new views::ViewModel
),
34 page_before_search_(0) {
35 pagination_model_
.AddObserver(this);
38 ContentsView::~ContentsView() {
39 pagination_model_
.RemoveObserver(this);
40 if (contents_switcher_view_
)
41 pagination_model_
.RemoveObserver(contents_switcher_view_
);
44 void ContentsView::InitNamedPages(AppListModel
* model
,
45 AppListViewDelegate
* view_delegate
) {
48 if (app_list::switches::IsExperimentalAppListEnabled()) {
49 start_page_view_
= new StartPageView(app_list_main_view_
, view_delegate
);
50 AddLauncherPage(start_page_view_
, 0, NAMED_PAGE_START
);
52 search_results_view_
=
53 new SearchResultListView(app_list_main_view_
, view_delegate
);
54 AddLauncherPage(search_results_view_
, 0, NAMED_PAGE_SEARCH_RESULTS
);
55 search_results_view_
->SetResults(model
->results());
58 apps_container_view_
= new AppsContainerView(app_list_main_view_
, model
);
61 apps_container_view_
, IDR_APP_LIST_APPS_ICON
, NAMED_PAGE_APPS
);
63 if (app_list::switches::IsExperimentalAppListEnabled()) {
64 std::vector
<views::View
*> custom_page_views
=
65 view_delegate
->CreateCustomPageWebViews(GetLocalBounds().size());
66 for (std::vector
<views::View
*>::const_iterator it
=
67 custom_page_views
.begin();
68 it
!= custom_page_views
.end();
70 AddLauncherPage(*it
, IDR_APP_LIST_NOTIFICATIONS_ICON
);
74 int initial_page_index
= app_list::switches::IsExperimentalAppListEnabled()
75 ? GetPageIndexForNamedPage(NAMED_PAGE_START
)
76 : GetPageIndexForNamedPage(NAMED_PAGE_APPS
);
78 page_before_search_
= initial_page_index
;
79 pagination_model_
.SelectPage(initial_page_index
, false);
81 // Needed to update the main search box visibility.
82 ActivePageChanged(false);
85 void ContentsView::CancelDrag() {
86 if (apps_container_view_
->apps_grid_view()->has_dragged_view())
87 apps_container_view_
->apps_grid_view()->EndDrag(true);
88 if (apps_container_view_
->app_list_folder_view()
90 ->has_dragged_view()) {
91 apps_container_view_
->app_list_folder_view()->items_grid_view()->EndDrag(
96 void ContentsView::SetDragAndDropHostOfCurrentAppList(
97 ApplicationDragAndDropHost
* drag_and_drop_host
) {
98 apps_container_view_
->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host
);
101 void ContentsView::SetContentsSwitcherView(
102 ContentsSwitcherView
* contents_switcher_view
) {
103 DCHECK(!contents_switcher_view_
);
104 contents_switcher_view_
= contents_switcher_view
;
105 if (contents_switcher_view_
)
106 pagination_model_
.AddObserver(contents_switcher_view_
);
109 void ContentsView::SetActivePage(int page_index
) {
110 if (GetActivePageIndex() == page_index
)
113 SetActivePageInternal(page_index
, false);
116 int ContentsView::GetActivePageIndex() const {
117 // The active page is changed at the beginning of an animation, not the end.
118 return pagination_model_
.SelectedTargetPage();
121 bool ContentsView::IsNamedPageActive(NamedPage named_page
) const {
122 std::map
<NamedPage
, int>::const_iterator it
=
123 named_page_to_view_
.find(named_page
);
124 if (it
== named_page_to_view_
.end())
126 return it
->second
== GetActivePageIndex();
129 int ContentsView::GetPageIndexForNamedPage(NamedPage named_page
) const {
130 // Find the index of the view corresponding to the given named_page.
131 std::map
<NamedPage
, int>::const_iterator it
=
132 named_page_to_view_
.find(named_page
);
133 // GetPageIndexForNamedPage should never be called on a named_page that does
134 // not have a corresponding view.
135 DCHECK(it
!= named_page_to_view_
.end());
139 int ContentsView::NumLauncherPages() const {
140 return pagination_model_
.total_pages();
143 void ContentsView::SetActivePageInternal(int page_index
,
144 bool show_search_results
) {
145 if (!show_search_results
)
146 page_before_search_
= page_index
;
147 // Start animating to the new page.
148 pagination_model_
.SelectPage(page_index
, true);
149 ActivePageChanged(show_search_results
);
152 void ContentsView::ActivePageChanged(bool show_search_results
) {
153 // TODO(xiyuan): Highlight default match instead of the first.
154 if (IsNamedPageActive(NAMED_PAGE_SEARCH_RESULTS
) &&
155 search_results_view_
->visible()) {
156 search_results_view_
->SetSelectedIndex(0);
158 if (search_results_view_
)
159 search_results_view_
->UpdateAutoLaunchState();
161 if (IsNamedPageActive(NAMED_PAGE_START
)) {
162 if (show_search_results
)
163 start_page_view_
->ShowSearchResults();
165 start_page_view_
->Reset();
168 // Notify parent AppListMainView of the page change.
169 app_list_main_view_
->UpdateSearchBoxVisibility();
172 void ContentsView::ShowSearchResults(bool show
) {
173 int search_page
= GetPageIndexForNamedPage(
174 app_list::switches::IsExperimentalAppListEnabled()
176 : NAMED_PAGE_SEARCH_RESULTS
);
178 SetActivePageInternal(show
? search_page
: page_before_search_
, show
);
181 bool ContentsView::IsShowingSearchResults() const {
182 return app_list::switches::IsExperimentalAppListEnabled()
183 ? IsNamedPageActive(NAMED_PAGE_START
) &&
184 start_page_view_
->IsShowingSearchResults()
185 : IsNamedPageActive(NAMED_PAGE_SEARCH_RESULTS
);
188 void ContentsView::UpdatePageBounds() {
189 gfx::Rect
rect(GetContentsBounds());
193 // The bounds calculations will potentially be mid-transition (depending on
194 // the state of the PaginationModel).
195 int current_page
= std::max(0, pagination_model_
.selected_page());
196 int target_page
= current_page
;
198 if (pagination_model_
.has_transition()) {
199 const PaginationModel::Transition
& transition
=
200 pagination_model_
.transition();
201 if (pagination_model_
.is_valid_page(transition
.target_page
)) {
202 target_page
= transition
.target_page
;
203 progress
= transition
.progress
;
207 gfx::Rect
incoming_target(rect
);
208 gfx::Rect
outgoing_target(rect
);
209 int dir
= target_page
> current_page
? -1 : 1;
211 // Pages transition vertically.
212 int page_height
= rect
.height();
213 int transition_offset
= progress
* page_height
* dir
;
215 outgoing_target
.set_y(transition_offset
);
216 incoming_target
.set_y(dir
< 0 ? transition_offset
+ page_height
217 : transition_offset
- page_height
);
219 view_model_
->view_at(current_page
)->SetBoundsRect(outgoing_target
);
220 view_model_
->view_at(target_page
)->SetBoundsRect(incoming_target
);
223 PaginationModel
* ContentsView::GetAppsPaginationModel() {
224 return apps_container_view_
->apps_grid_view()->pagination_model();
227 void ContentsView::ShowFolderContent(AppListFolderItem
* item
) {
228 apps_container_view_
->ShowActiveFolder(item
);
231 void ContentsView::Prerender() {
232 apps_container_view_
->apps_grid_view()->Prerender();
235 views::View
* ContentsView::GetPageView(int index
) {
236 return view_model_
->view_at(index
);
239 void ContentsView::AddBlankPageForTesting() {
240 AddLauncherPage(new views::View
, 0);
243 int ContentsView::AddLauncherPage(views::View
* view
, int resource_id
) {
244 int page_index
= view_model_
->view_size();
246 view_model_
->Add(view
, page_index
);
247 if (contents_switcher_view_
&& resource_id
)
248 contents_switcher_view_
->AddSwitcherButton(resource_id
, page_index
);
249 pagination_model_
.SetTotalPages(view_model_
->view_size());
253 int ContentsView::AddLauncherPage(views::View
* view
,
255 NamedPage named_page
) {
256 int page_index
= AddLauncherPage(view
, resource_id
);
257 named_page_to_view_
.insert(std::pair
<NamedPage
, int>(named_page
, page_index
));
261 gfx::Size
ContentsView::GetPreferredSize() const {
262 const gfx::Size container_size
=
263 apps_container_view_
->apps_grid_view()->GetPreferredSize();
264 const gfx::Size results_size
= search_results_view_
265 ? search_results_view_
->GetPreferredSize()
268 int width
= std::max(container_size
.width(), results_size
.width());
269 int height
= std::max(container_size
.height(), results_size
.height());
270 return gfx::Size(width
, height
);
273 void ContentsView::Layout() {
274 // Immediately finish all current animations.
275 pagination_model_
.FinishAnimation();
277 // Move the current view onto the screen, and all other views off screen to
278 // the left. (Since we are not animating, we don't need to be careful about
279 // which side we place the off-screen views onto.)
280 gfx::Rect
rect(GetContentsBounds());
284 gfx::Rect
offscreen_target(rect
);
285 offscreen_target
.set_x(-rect
.width());
287 for (int i
= 0; i
< view_model_
->view_size(); ++i
) {
288 view_model_
->view_at(i
)->SetBoundsRect(
289 i
== pagination_model_
.SelectedTargetPage() ? rect
: offscreen_target
);
293 bool ContentsView::OnKeyPressed(const ui::KeyEvent
& event
) {
294 return view_model_
->view_at(GetActivePageIndex())->OnKeyPressed(event
);
297 void ContentsView::TotalPagesChanged() {
300 void ContentsView::SelectedPageChanged(int old_selected
, int new_selected
) {
303 void ContentsView::TransitionStarted() {
306 void ContentsView::TransitionChanged() {
310 } // namespace app_list