Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" | 13 #include "ui/app_list/pagination_model.h" |
| 14 #include "ui/app_list/views/app_list_folder_view.h" | 14 #include "ui/app_list/views/app_list_folder_view.h" |
| 15 #include "ui/app_list/views/app_list_main_view.h" | 15 #include "ui/app_list/views/app_list_main_view.h" |
| 16 #include "ui/app_list/views/apps_container_view.h" | 16 #include "ui/app_list/views/apps_container_view.h" |
| 17 #include "ui/app_list/views/apps_grid_view.h" | 17 #include "ui/app_list/views/apps_grid_view.h" |
| 18 #include "ui/app_list/views/search_result_list_view.h" | 18 #include "ui/app_list/views/search_result_list_view.h" |
| 19 #include "ui/app_list/views/start_page_view.h" | 19 #include "ui/app_list/views/start_page_view.h" |
| 20 #include "ui/events/event.h" | 20 #include "ui/events/event.h" |
| 21 #include "ui/views/animation/bounds_animator.h" | 21 #include "ui/views/animation/bounds_animator.h" |
| 22 #include "ui/views/view_model.h" | 22 #include "ui/views/view_model.h" |
| 23 #include "ui/views/view_model_utils.h" | 23 #include "ui/views/view_model_utils.h" |
| 24 | 24 |
| 25 namespace app_list { | 25 namespace app_list { |
| 26 | 26 |
| 27 namespace { | 27 namespace { |
| 28 | 28 |
| 29 // Indexes of interesting views in ViewModel of ContentsView. | |
| 30 const int kIndexAppsContainer = 0; | |
| 31 const int kIndexSearchResults = 1; | |
| 32 const int kIndexStartPage = 2; | |
| 33 | |
| 34 const int kMinMouseWheelToSwitchPage = 20; | 29 const int kMinMouseWheelToSwitchPage = 20; |
| 35 const int kMinScrollToSwitchPage = 20; | 30 const int kMinScrollToSwitchPage = 20; |
| 36 const int kMinHorizVelocityToSwitchPage = 800; | 31 const int kMinHorizVelocityToSwitchPage = 800; |
| 37 | 32 |
| 38 const double kFinishTransitionThreshold = 0.33; | 33 const double kFinishTransitionThreshold = 0.33; |
| 39 | 34 |
| 40 } // namespace | 35 } // namespace |
| 41 | 36 |
| 42 ContentsView::ContentsView(AppListMainView* app_list_main_view, | 37 ContentsView::ContentsView(AppListMainView* app_list_main_view, |
| 43 AppListModel* model, | 38 AppListModel* model, |
| 44 AppListViewDelegate* view_delegate) | 39 AppListViewDelegate* view_delegate) |
| 45 : show_state_(SHOW_APPS), | 40 : start_page_view_(NULL), |
| 46 start_page_view_(NULL), | |
| 47 app_list_main_view_(app_list_main_view), | 41 app_list_main_view_(app_list_main_view), |
| 48 view_model_(new views::ViewModel), | 42 view_model_(new views::ViewModel), |
| 49 bounds_animator_(new views::BoundsAnimator(this)) { | 43 bounds_animator_(new views::BoundsAnimator(this)) { |
| 50 DCHECK(model); | 44 DCHECK(model); |
| 51 | 45 |
| 52 apps_container_view_ = new AppsContainerView(app_list_main_view, model); | |
| 53 AddChildView(apps_container_view_); | |
| 54 view_model_->Add(apps_container_view_, kIndexAppsContainer); | |
| 55 | |
| 56 search_results_view_ = | 46 search_results_view_ = |
| 57 new SearchResultListView(app_list_main_view, view_delegate); | 47 new SearchResultListView(app_list_main_view, view_delegate); |
| 58 AddChildView(search_results_view_); | 48 AddLauncherPage(search_results_view_, SHOW_SEARCH_RESULTS); |
| 59 view_model_->Add(search_results_view_, kIndexSearchResults); | |
| 60 | 49 |
| 61 if (app_list::switches::IsExperimentalAppListEnabled()) { | 50 if (app_list::switches::IsExperimentalAppListEnabled()) { |
| 62 start_page_view_ = new StartPageView(app_list_main_view, view_delegate); | 51 start_page_view_ = new StartPageView(app_list_main_view, view_delegate); |
| 63 AddChildView(start_page_view_); | 52 AddLauncherPage(start_page_view_, SHOW_START_PAGE); |
| 64 view_model_->Add(start_page_view_, kIndexStartPage); | |
| 65 } | 53 } |
| 66 | 54 |
| 55 apps_container_view_ = new AppsContainerView(app_list_main_view, model); | |
| 56 AddLauncherPage(apps_container_view_, SHOW_APPS); | |
| 57 | |
| 58 active_page_ = GetPageIndexForNamedPage(SHOW_APPS); | |
| 67 search_results_view_->SetResults(model->results()); | 59 search_results_view_->SetResults(model->results()); |
| 68 } | 60 } |
| 69 | 61 |
| 70 ContentsView::~ContentsView() { | 62 ContentsView::~ContentsView() { |
| 71 } | 63 } |
| 72 | 64 |
| 73 void ContentsView::CancelDrag() { | 65 void ContentsView::CancelDrag() { |
| 74 if (apps_container_view_->apps_grid_view()->has_dragged_view()) | 66 if (apps_container_view_->apps_grid_view()->has_dragged_view()) |
| 75 apps_container_view_->apps_grid_view()->EndDrag(true); | 67 apps_container_view_->apps_grid_view()->EndDrag(true); |
| 76 if (apps_container_view_->app_list_folder_view() | 68 if (apps_container_view_->app_list_folder_view() |
| 77 ->items_grid_view() | 69 ->items_grid_view() |
| 78 ->has_dragged_view()) { | 70 ->has_dragged_view()) { |
| 79 apps_container_view_->app_list_folder_view()->items_grid_view()->EndDrag( | 71 apps_container_view_->app_list_folder_view()->items_grid_view()->EndDrag( |
| 80 true); | 72 true); |
| 81 } | 73 } |
| 82 } | 74 } |
| 83 | 75 |
| 84 void ContentsView::SetDragAndDropHostOfCurrentAppList( | 76 void ContentsView::SetDragAndDropHostOfCurrentAppList( |
| 85 ApplicationDragAndDropHost* drag_and_drop_host) { | 77 ApplicationDragAndDropHost* drag_and_drop_host) { |
| 86 apps_container_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); | 78 apps_container_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); |
| 87 } | 79 } |
| 88 | 80 |
| 89 void ContentsView::SetShowState(ShowState show_state) { | 81 void ContentsView::SetActivePage(int page_index) { |
| 90 if (show_state_ == show_state) | 82 if (active_page_ == page_index) |
| 91 return; | 83 return; |
| 92 | 84 |
| 93 show_state_ = show_state; | 85 active_page_ = page_index; |
| 94 ShowStateChanged(); | 86 ActivePageChanged(); |
| 95 } | 87 } |
| 96 | 88 |
| 97 void ContentsView::ShowStateChanged() { | 89 bool ContentsView::IsNamedPageActive(NamedPage named_page) const { |
| 90 std::map<NamedPage, int>::const_iterator it = | |
| 91 named_page_to_view_.find(named_page); | |
| 92 if (it == named_page_to_view_.end()) | |
| 93 return false; | |
| 94 return it->second == active_page_; | |
| 95 } | |
| 96 | |
| 97 int ContentsView::GetPageIndexForNamedPage(NamedPage named_page) const { | |
| 98 // Find the index of the view corresponding to the given named_page. | |
| 99 std::map<NamedPage, int>::const_iterator it = | |
| 100 named_page_to_view_.find(named_page); | |
| 101 // GetPageIndexForNamedPage should never be called on a named_page that does | |
| 102 // not have a corresponding view. | |
| 103 DCHECK(it != named_page_to_view_.end()); | |
| 104 return it->second; | |
| 105 } | |
| 106 | |
| 107 void ContentsView::ActivePageChanged() { | |
| 98 // TODO(xiyuan): Highlight default match instead of the first. | 108 // TODO(xiyuan): Highlight default match instead of the first. |
| 99 if (show_state_ == SHOW_SEARCH_RESULTS && search_results_view_->visible()) | 109 if (IsNamedPageActive(SHOW_SEARCH_RESULTS) && search_results_view_->visible()) |
| 100 search_results_view_->SetSelectedIndex(0); | 110 search_results_view_->SetSelectedIndex(0); |
| 101 search_results_view_->UpdateAutoLaunchState(); | 111 search_results_view_->UpdateAutoLaunchState(); |
| 102 | 112 |
| 103 // Notify parent AppListMainView of show state change. | 113 // Notify parent AppListMainView of the page change. |
| 104 app_list_main_view_->OnContentsViewShowStateChanged(); | 114 app_list_main_view_->OnContentsViewActivePageChanged(); |
| 105 | 115 |
| 106 if (show_state_ == SHOW_START_PAGE) | 116 if (IsNamedPageActive(SHOW_START_PAGE)) |
| 107 start_page_view_->Reset(); | 117 start_page_view_->Reset(); |
| 108 | 118 |
| 109 AnimateToIdealBounds(); | 119 AnimateToIdealBounds(); |
| 110 } | 120 } |
| 111 | 121 |
| 112 void ContentsView::CalculateIdealBounds() { | 122 void ContentsView::CalculateIdealBounds() { |
| 113 gfx::Rect rect(GetContentsBounds()); | 123 gfx::Rect rect(GetContentsBounds()); |
| 114 if (rect.IsEmpty()) | 124 if (rect.IsEmpty()) |
| 115 return; | 125 return; |
| 116 | 126 |
| 117 if (app_list::switches::IsExperimentalAppListEnabled()) { | 127 if (app_list::switches::IsExperimentalAppListEnabled()) { |
| 118 int incoming_view_index = 0; | |
| 119 switch (show_state_) { | |
| 120 case SHOW_APPS: | |
| 121 incoming_view_index = kIndexAppsContainer; | |
| 122 break; | |
| 123 case SHOW_SEARCH_RESULTS: | |
| 124 incoming_view_index = kIndexSearchResults; | |
| 125 break; | |
| 126 case SHOW_START_PAGE: | |
| 127 incoming_view_index = kIndexStartPage; | |
| 128 break; | |
| 129 default: | |
| 130 NOTREACHED(); | |
| 131 } | |
| 132 | |
| 133 gfx::Rect incoming_target(rect); | 128 gfx::Rect incoming_target(rect); |
| 134 gfx::Rect outgoing_target(rect); | 129 gfx::Rect outgoing_target(rect); |
| 135 outgoing_target.set_x(-outgoing_target.width()); | 130 outgoing_target.set_x(-outgoing_target.width()); |
| 136 | 131 |
| 137 for (int i = 0; i < view_model_->view_size(); ++i) { | 132 for (int i = 0; i < view_model_->view_size(); ++i) { |
| 138 view_model_->set_ideal_bounds(i, | 133 view_model_->set_ideal_bounds( |
| 139 i == incoming_view_index ? incoming_target | 134 i, i == active_page_ ? incoming_target : outgoing_target); |
| 140 : outgoing_target); | |
| 141 } | 135 } |
| 142 return; | 136 return; |
| 143 } | 137 } |
| 144 | 138 |
| 145 gfx::Rect container_frame(rect); | 139 gfx::Rect container_frame(rect); |
| 146 gfx::Rect results_frame(rect); | 140 gfx::Rect results_frame(rect); |
| 147 | 141 |
| 148 // Offsets apps grid and result list based on |show_state_|. | 142 // Offsets apps grid and result list based on |active_page_|. |
| 149 // SearchResultListView is on top of apps grid. Visible view is left in | 143 // SearchResultListView is on top of apps grid. Visible view is left in |
| 150 // visible area and invisible ones is put out of the visible area. | 144 // visible area and invisible ones is put out of the visible area. |
| 151 int contents_area_height = rect.height(); | 145 int contents_area_height = rect.height(); |
| 152 switch (show_state_) { | 146 if (IsNamedPageActive(SHOW_APPS)) |
| 153 case SHOW_APPS: | 147 results_frame.Offset(0, -contents_area_height); |
| 154 results_frame.Offset(0, -contents_area_height); | 148 else if (IsNamedPageActive(SHOW_SEARCH_RESULTS)) |
| 155 break; | 149 container_frame.Offset(0, contents_area_height); |
| 156 case SHOW_SEARCH_RESULTS: | 150 else |
| 157 container_frame.Offset(0, contents_area_height); | 151 NOTREACHED() << "Page " << active_page_ << " invalid in current app list."; |
| 158 break; | |
| 159 default: | |
| 160 NOTREACHED() << "Unknown show_state_ " << show_state_; | |
| 161 break; | |
| 162 } | |
| 163 | 152 |
| 164 view_model_->set_ideal_bounds(kIndexAppsContainer, container_frame); | 153 view_model_->set_ideal_bounds(GetPageIndexForNamedPage(SHOW_APPS), |
| 165 view_model_->set_ideal_bounds(kIndexSearchResults, results_frame); | 154 container_frame); |
| 155 view_model_->set_ideal_bounds(GetPageIndexForNamedPage(SHOW_SEARCH_RESULTS), | |
| 156 results_frame); | |
| 166 } | 157 } |
| 167 | 158 |
| 168 void ContentsView::AnimateToIdealBounds() { | 159 void ContentsView::AnimateToIdealBounds() { |
| 169 CalculateIdealBounds(); | 160 CalculateIdealBounds(); |
| 170 for (int i = 0; i < view_model_->view_size(); ++i) { | 161 for (int i = 0; i < view_model_->view_size(); ++i) { |
| 171 bounds_animator_->AnimateViewTo(view_model_->view_at(i), | 162 bounds_animator_->AnimateViewTo(view_model_->view_at(i), |
| 172 view_model_->ideal_bounds(i)); | 163 view_model_->ideal_bounds(i)); |
| 173 } | 164 } |
| 174 } | 165 } |
| 175 | 166 |
| 176 PaginationModel* ContentsView::GetAppsPaginationModel() { | 167 PaginationModel* ContentsView::GetAppsPaginationModel() { |
| 177 return apps_container_view_->apps_grid_view()->pagination_model(); | 168 return apps_container_view_->apps_grid_view()->pagination_model(); |
| 178 } | 169 } |
| 179 | 170 |
| 180 void ContentsView::ShowSearchResults(bool show) { | 171 void ContentsView::ShowSearchResults(bool show) { |
| 181 SetShowState(show ? SHOW_SEARCH_RESULTS : SHOW_APPS); | 172 NamedPage new_named_page = show ? SHOW_SEARCH_RESULTS : SHOW_APPS; |
| 173 SetActivePage(GetPageIndexForNamedPage(new_named_page)); | |
| 182 } | 174 } |
| 183 | 175 |
| 184 void ContentsView::ShowFolderContent(AppListFolderItem* item) { | 176 void ContentsView::ShowFolderContent(AppListFolderItem* item) { |
| 185 apps_container_view_->ShowActiveFolder(item); | 177 apps_container_view_->ShowActiveFolder(item); |
| 186 } | 178 } |
| 187 | 179 |
| 188 void ContentsView::Prerender() { | 180 void ContentsView::Prerender() { |
| 189 const int selected_page = | 181 const int selected_page = |
| 190 std::max(0, GetAppsPaginationModel()->selected_page()); | 182 std::max(0, GetAppsPaginationModel()->selected_page()); |
| 191 apps_container_view_->apps_grid_view()->Prerender(selected_page); | 183 apps_container_view_->apps_grid_view()->Prerender(selected_page); |
| 192 } | 184 } |
| 193 | 185 |
| 186 void ContentsView::AddLauncherPage(views::View* view) { | |
| 187 int page_index = view_model_->view_size(); | |
| 188 AddChildView(view); | |
| 189 view_model_->Add(view, page_index); | |
| 190 } | |
| 191 | |
| 192 void ContentsView::AddLauncherPage(views::View* view, NamedPage named_page) { | |
| 193 int page_index = view_model_->view_size(); | |
| 194 AddChildView(view); | |
| 195 view_model_->Add(view, page_index); | |
|
benwells
2014/06/06 06:12:29
Lines are duplicated. Should this just call AddLau
Matt Giuca
2014/06/10 04:01:19
Done.
| |
| 196 named_page_to_view_.insert(std::pair<NamedPage, int>(named_page, page_index)); | |
| 197 } | |
| 198 | |
| 194 gfx::Size ContentsView::GetPreferredSize() const { | 199 gfx::Size ContentsView::GetPreferredSize() const { |
| 195 const gfx::Size container_size = | 200 const gfx::Size container_size = |
| 196 apps_container_view_->apps_grid_view()->GetPreferredSize(); | 201 apps_container_view_->apps_grid_view()->GetPreferredSize(); |
| 197 const gfx::Size results_size = search_results_view_->GetPreferredSize(); | 202 const gfx::Size results_size = search_results_view_->GetPreferredSize(); |
| 198 | 203 |
| 199 int width = std::max(container_size.width(), results_size.width()); | 204 int width = std::max(container_size.width(), results_size.width()); |
| 200 int height = std::max(container_size.height(), results_size.height()); | 205 int height = std::max(container_size.height(), results_size.height()); |
| 201 return gfx::Size(width, height); | 206 return gfx::Size(width, height); |
| 202 } | 207 } |
| 203 | 208 |
| 204 void ContentsView::Layout() { | 209 void ContentsView::Layout() { |
| 205 CalculateIdealBounds(); | 210 CalculateIdealBounds(); |
| 206 views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); | 211 views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); |
| 207 } | 212 } |
| 208 | 213 |
| 209 bool ContentsView::OnKeyPressed(const ui::KeyEvent& event) { | 214 bool ContentsView::OnKeyPressed(const ui::KeyEvent& event) { |
| 210 switch (show_state_) { | 215 return view_model_->view_at(active_page_)->OnKeyPressed(event); |
| 211 case SHOW_APPS: | |
| 212 return apps_container_view_->OnKeyPressed(event); | |
| 213 case SHOW_SEARCH_RESULTS: | |
| 214 return search_results_view_->OnKeyPressed(event); | |
| 215 case SHOW_START_PAGE: | |
| 216 return start_page_view_->OnKeyPressed(event); | |
| 217 default: | |
| 218 NOTREACHED() << "Unknown show state " << show_state_; | |
| 219 } | |
| 220 return false; | |
| 221 } | 216 } |
| 222 | 217 |
| 223 bool ContentsView::OnMouseWheel(const ui::MouseWheelEvent& event) { | 218 bool ContentsView::OnMouseWheel(const ui::MouseWheelEvent& event) { |
| 224 if (show_state_ != SHOW_APPS) | 219 if (!IsNamedPageActive(SHOW_APPS)) |
| 225 return false; | 220 return false; |
| 226 | 221 |
| 227 int offset; | 222 int offset; |
| 228 if (abs(event.x_offset()) > abs(event.y_offset())) | 223 if (abs(event.x_offset()) > abs(event.y_offset())) |
| 229 offset = event.x_offset(); | 224 offset = event.x_offset(); |
| 230 else | 225 else |
| 231 offset = event.y_offset(); | 226 offset = event.y_offset(); |
| 232 | 227 |
| 233 if (abs(offset) > kMinMouseWheelToSwitchPage) { | 228 if (abs(offset) > kMinMouseWheelToSwitchPage) { |
| 234 if (!GetAppsPaginationModel()->has_transition()) { | 229 if (!GetAppsPaginationModel()->has_transition()) { |
| 235 GetAppsPaginationModel()->SelectPageRelative(offset > 0 ? -1 : 1, true); | 230 GetAppsPaginationModel()->SelectPageRelative(offset > 0 ? -1 : 1, true); |
| 236 } | 231 } |
| 237 return true; | 232 return true; |
| 238 } | 233 } |
| 239 | 234 |
| 240 return false; | 235 return false; |
| 241 } | 236 } |
| 242 | 237 |
| 243 void ContentsView::OnGestureEvent(ui::GestureEvent* event) { | 238 void ContentsView::OnGestureEvent(ui::GestureEvent* event) { |
| 244 if (show_state_ != SHOW_APPS) | 239 if (!IsNamedPageActive(SHOW_APPS)) |
| 245 return; | 240 return; |
| 246 | 241 |
| 247 switch (event->type()) { | 242 switch (event->type()) { |
| 248 case ui::ET_GESTURE_SCROLL_BEGIN: | 243 case ui::ET_GESTURE_SCROLL_BEGIN: |
| 249 GetAppsPaginationModel()->StartScroll(); | 244 GetAppsPaginationModel()->StartScroll(); |
| 250 event->SetHandled(); | 245 event->SetHandled(); |
| 251 return; | 246 return; |
| 252 case ui::ET_GESTURE_SCROLL_UPDATE: | 247 case ui::ET_GESTURE_SCROLL_UPDATE: |
| 253 // event->details.scroll_x() > 0 means moving contents to right. That is, | 248 // event->details.scroll_x() > 0 means moving contents to right. That is, |
| 254 // transitioning to previous page. | 249 // transitioning to previous page. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 270 } | 265 } |
| 271 event->SetHandled(); | 266 event->SetHandled(); |
| 272 return; | 267 return; |
| 273 } | 268 } |
| 274 default: | 269 default: |
| 275 break; | 270 break; |
| 276 } | 271 } |
| 277 } | 272 } |
| 278 | 273 |
| 279 void ContentsView::OnScrollEvent(ui::ScrollEvent* event) { | 274 void ContentsView::OnScrollEvent(ui::ScrollEvent* event) { |
| 280 if (show_state_ != SHOW_APPS || | 275 if (!IsNamedPageActive(SHOW_APPS) || |
| 281 event->type() == ui::ET_SCROLL_FLING_CANCEL) { | 276 event->type() == ui::ET_SCROLL_FLING_CANCEL) { |
| 282 return; | 277 return; |
| 283 } | 278 } |
| 284 | 279 |
| 285 float offset; | 280 float offset; |
| 286 if (std::abs(event->x_offset()) > std::abs(event->y_offset())) | 281 if (std::abs(event->x_offset()) > std::abs(event->y_offset())) |
| 287 offset = event->x_offset(); | 282 offset = event->x_offset(); |
| 288 else | 283 else |
| 289 offset = event->y_offset(); | 284 offset = event->y_offset(); |
| 290 | 285 |
| 291 if (std::abs(offset) > kMinScrollToSwitchPage) { | 286 if (std::abs(offset) > kMinScrollToSwitchPage) { |
| 292 if (!GetAppsPaginationModel()->has_transition()) { | 287 if (!GetAppsPaginationModel()->has_transition()) { |
| 293 GetAppsPaginationModel()->SelectPageRelative(offset > 0 ? -1 : 1, true); | 288 GetAppsPaginationModel()->SelectPageRelative(offset > 0 ? -1 : 1, true); |
| 294 } | 289 } |
| 295 event->SetHandled(); | 290 event->SetHandled(); |
| 296 event->StopPropagation(); | 291 event->StopPropagation(); |
| 297 } | 292 } |
| 298 } | 293 } |
| 299 | 294 |
| 300 } // namespace app_list | 295 } // namespace app_list |
| OLD | NEW |