1 // Copyright 2013 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. 4 5 #include "ui/app_list/views/apps_container_view.h" 6 7 #include <algorithm> 8 #include <vector> 9 10 #include "base/command_line.h" 11 #include "ui/app_list/app_list_constants.h" 12 #include "ui/app_list/app_list_folder_item.h" 13 #include "ui/app_list/app_list_switches.h" 14 #include "ui/app_list/views/app_list_folder_view.h" 15 #include "ui/app_list/views/app_list_item_view.h" 16 #include "ui/app_list/views/app_list_main_view.h" 17 #include "ui/app_list/views/apps_grid_view.h" 18 #include "ui/app_list/views/folder_background_view.h" 19 #include "ui/events/event.h" 20 21 namespace app_list { 22 23 AppsContainerView::AppsContainerView(AppListMainView* app_list_main_view, 24 AppListModel* model) 25 : model_(model), 26 show_state_(SHOW_NONE), 27 top_icon_animation_pending_count_(0) { 28 apps_grid_view_ = new AppsGridView(app_list_main_view); 29 int cols; 30 int rows; 31 if (switches::IsExperimentalAppListEnabled()) { 32 cols = kExperimentalPreferredCols; 33 rows = kExperimentalPreferredRows; 34 } else if (app_list_main_view->ShouldCenterWindow()) { 35 cols = kCenteredPreferredCols; 36 rows = kCenteredPreferredRows; 37 } else { 38 cols = kPreferredCols; 39 rows = kPreferredRows; 40 } 41 apps_grid_view_->SetLayout(cols, rows); 42 AddChildView(apps_grid_view_); 43 44 folder_background_view_ = new FolderBackgroundView(); 45 AddChildView(folder_background_view_); 46 47 app_list_folder_view_ = 48 new AppListFolderView(this, model, app_list_main_view); 49 // The folder view is initially hidden. 50 app_list_folder_view_->SetVisible(false); 51 AddChildView(app_list_folder_view_); 52 53 apps_grid_view_->SetModel(model_); 54 apps_grid_view_->SetItemList(model_->top_level_item_list()); 55 SetShowState(SHOW_APPS, 56 false); /* show apps without animation */ 57 } 58 59 AppsContainerView::~AppsContainerView() { 60 } 61 62 void AppsContainerView::ShowActiveFolder(AppListFolderItem* folder_item) { 63 // Prevent new animations from starting if there are currently animations 64 // pending. This fixes crbug.com/357099. 65 if (top_icon_animation_pending_count_) 66 return; 67 68 app_list_folder_view_->SetAppListFolderItem(folder_item); 69 SetShowState(SHOW_ACTIVE_FOLDER, false); 70 71 CreateViewsForFolderTopItemsAnimation(folder_item, true); 72 } 73 74 void AppsContainerView::ShowApps(AppListFolderItem* folder_item) { 75 if (top_icon_animation_pending_count_) 76 return; 77 78 PrepareToShowApps(folder_item); 79 SetShowState(SHOW_APPS, 80 true); /* show apps with animation */ 81 } 82 83 void AppsContainerView::ResetForShowApps() { 84 SetShowState(SHOW_APPS, false /* show apps without animation */); 85 folder_background_view_->UpdateFolderContainerBubble( 86 FolderBackgroundView::NO_BUBBLE); 87 } 88 89 void AppsContainerView::SetDragAndDropHostOfCurrentAppList( 90 ApplicationDragAndDropHost* drag_and_drop_host) { 91 apps_grid_view()->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); 92 app_list_folder_view()->items_grid_view()-> 93 SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); 94 } 95 96 void AppsContainerView::ReparentFolderItemTransit( 97 AppListFolderItem* folder_item) { 98 if (top_icon_animation_pending_count_) 99 return; 100 101 PrepareToShowApps(folder_item); 102 SetShowState(SHOW_ITEM_REPARENT, false); 103 } 104 105 bool AppsContainerView::IsInFolderView() const { 106 return show_state_ == SHOW_ACTIVE_FOLDER; 107 } 108 109 gfx::Size AppsContainerView::GetPreferredSize() const { 110 const gfx::Size grid_size = apps_grid_view_->GetPreferredSize(); 111 const gfx::Size folder_view_size = app_list_folder_view_->GetPreferredSize(); 112 113 int width = std::max(grid_size.width(), folder_view_size.width()); 114 int height = std::max(grid_size.height(), folder_view_size.height()); 115 return gfx::Size(width, height); 116 } 117 118 void AppsContainerView::Layout() { 119 gfx::Rect rect(GetContentsBounds()); 120 if (rect.IsEmpty()) 121 return; 122 123 switch (show_state_) { 124 case SHOW_APPS: 125 apps_grid_view_->SetBoundsRect(rect); 126 break; 127 case SHOW_ACTIVE_FOLDER: 128 folder_background_view_->SetBoundsRect(rect); 129 app_list_folder_view_->SetBoundsRect(rect); 130 break; 131 case SHOW_ITEM_REPARENT: 132 break; 133 default: 134 NOTREACHED(); 135 } 136 } 137 138 bool AppsContainerView::OnKeyPressed(const ui::KeyEvent& event) { 139 if (show_state_ == SHOW_APPS) 140 return apps_grid_view_->OnKeyPressed(event); 141 else 142 return app_list_folder_view_->OnKeyPressed(event); 143 } 144 145 void AppsContainerView::OnTopIconAnimationsComplete() { 146 --top_icon_animation_pending_count_; 147 148 if (!top_icon_animation_pending_count_) { 149 // Clean up the transitional views used for top item icon animation. 150 top_icon_views_.clear(); 151 152 // Show the folder icon when closing the folder. 153 if ((show_state_ == SHOW_APPS || show_state_ == SHOW_ITEM_REPARENT) && 154 apps_grid_view_->activated_folder_item_view()) { 155 apps_grid_view_->activated_folder_item_view()->SetVisible(true); 156 } 157 } 158 } 159 160 void AppsContainerView::SetShowState(ShowState show_state, 161 bool show_apps_with_animation) { 162 if (show_state_ == show_state) 163 return; 164 165 show_state_ = show_state; 166 167 switch (show_state_) { 168 case SHOW_APPS: 169 folder_background_view_->SetVisible(false); 170 if (show_apps_with_animation) { 171 app_list_folder_view_->ScheduleShowHideAnimation(false, false); 172 apps_grid_view_->ScheduleShowHideAnimation(true); 173 } else { 174 app_list_folder_view_->HideViewImmediately(); 175 apps_grid_view_->ResetForShowApps(); 176 } 177 break; 178 case SHOW_ACTIVE_FOLDER: 179 folder_background_view_->SetVisible(true); 180 apps_grid_view_->ScheduleShowHideAnimation(false); 181 app_list_folder_view_->ScheduleShowHideAnimation(true, false); 182 break; 183 case SHOW_ITEM_REPARENT: 184 folder_background_view_->SetVisible(false); 185 folder_background_view_->UpdateFolderContainerBubble( 186 FolderBackgroundView::NO_BUBBLE); 187 app_list_folder_view_->ScheduleShowHideAnimation(false, true); 188 apps_grid_view_->ScheduleShowHideAnimation(true); 189 break; 190 default: 191 NOTREACHED(); 192 } 193 194 Layout(); 195 } 196 197 Rects AppsContainerView::GetTopItemIconBoundsInActiveFolder() { 198 // Get the active folder's icon bounds relative to AppsContainerView. 199 AppListItemView* folder_item_view = 200 apps_grid_view_->activated_folder_item_view(); 201 gfx::Rect to_grid_view = folder_item_view->ConvertRectToParent( 202 folder_item_view->GetIconBounds()); 203 gfx::Rect to_container = apps_grid_view_->ConvertRectToParent(to_grid_view); 204 205 return AppListFolderItem::GetTopIconsBounds(to_container); 206 } 207 208 void AppsContainerView::CreateViewsForFolderTopItemsAnimation( 209 AppListFolderItem* active_folder, 210 bool open_folder) { 211 top_icon_views_.clear(); 212 std::vector<gfx::Rect> top_items_bounds = 213 GetTopItemIconBoundsInActiveFolder(); 214 top_icon_animation_pending_count_ = 215 std::min(kNumFolderTopItems, active_folder->item_list()->item_count()); 216 for (size_t i = 0; i < top_icon_animation_pending_count_; ++i) { 217 if (active_folder->GetTopIcon(i).isNull()) 218 continue; 219 220 TopIconAnimationView* icon_view = new TopIconAnimationView( 221 active_folder->GetTopIcon(i), top_items_bounds[i], open_folder); 222 icon_view->AddObserver(this); 223 top_icon_views_.push_back(icon_view); 224 225 // Add the transitional views into child views, and set its bounds to the 226 // same location of the item in the folder list view. 227 AddChildView(top_icon_views_[i]); 228 top_icon_views_[i]->SetBoundsRect( 229 app_list_folder_view_->ConvertRectToParent( 230 app_list_folder_view_->GetItemIconBoundsAt(i))); 231 static_cast<TopIconAnimationView*>(top_icon_views_[i])->TransformView(); 232 } 233 } 234 235 void AppsContainerView::PrepareToShowApps(AppListFolderItem* folder_item) { 236 if (folder_item) 237 CreateViewsForFolderTopItemsAnimation(folder_item, false); 238 239 // Hide the active folder item until the animation completes. 240 if (apps_grid_view_->activated_folder_item_view()) 241 apps_grid_view_->activated_folder_item_view()->SetVisible(false); 242 } 243 244 } // namespace app_list 245