// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/app_list/views/apps_container_view.h" #include #include #include "base/command_line.h" #include "ui/app_list/app_list_constants.h" #include "ui/app_list/app_list_folder_item.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/views/app_list_folder_view.h" #include "ui/app_list/views/app_list_item_view.h" #include "ui/app_list/views/app_list_main_view.h" #include "ui/app_list/views/apps_grid_view.h" #include "ui/app_list/views/folder_background_view.h" #include "ui/events/event.h" namespace app_list { AppsContainerView::AppsContainerView(AppListMainView* app_list_main_view, AppListModel* model) : model_(model), show_state_(SHOW_NONE), top_icon_animation_pending_count_(0) { apps_grid_view_ = new AppsGridView(app_list_main_view); int cols = kPreferredCols; int rows = kPreferredRows; // ShouldCenterWindow also implies that it is wide instead of tall. if (app_list_main_view->ShouldCenterWindow()) { cols = kExperimentalPreferredCols; rows = kExperimentalPreferredRows; } apps_grid_view_->SetLayout(kPreferredIconDimension, cols, rows); AddChildView(apps_grid_view_); folder_background_view_ = new FolderBackgroundView(); AddChildView(folder_background_view_); app_list_folder_view_ = new AppListFolderView(this, model, app_list_main_view); // The folder view is initially hidden. app_list_folder_view_->SetVisible(false); AddChildView(app_list_folder_view_); apps_grid_view_->SetModel(model_); apps_grid_view_->SetItemList(model_->top_level_item_list()); SetShowState(SHOW_APPS, false); /* show apps without animation */ } AppsContainerView::~AppsContainerView() { } void AppsContainerView::ShowActiveFolder(AppListFolderItem* folder_item) { // Prevent new animations from starting if there are currently animations // pending. This fixes crbug.com/357099. if (top_icon_animation_pending_count_) return; app_list_folder_view_->SetAppListFolderItem(folder_item); SetShowState(SHOW_ACTIVE_FOLDER, false); CreateViewsForFolderTopItemsAnimation(folder_item, true); } void AppsContainerView::ShowApps(AppListFolderItem* folder_item) { if (top_icon_animation_pending_count_) return; PrepareToShowApps(folder_item); SetShowState(SHOW_APPS, true); /* show apps with animation */ } void AppsContainerView::ResetForShowApps() { SetShowState(SHOW_APPS, false /* show apps without animation */); folder_background_view_->UpdateFolderContainerBubble( FolderBackgroundView::NO_BUBBLE); } void AppsContainerView::SetDragAndDropHostOfCurrentAppList( ApplicationDragAndDropHost* drag_and_drop_host) { apps_grid_view()->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); app_list_folder_view()->items_grid_view()-> SetDragAndDropHostOfCurrentAppList(drag_and_drop_host); } void AppsContainerView::ReparentFolderItemTransit( AppListFolderItem* folder_item) { if (top_icon_animation_pending_count_) return; PrepareToShowApps(folder_item); SetShowState(SHOW_ITEM_REPARENT, false); } bool AppsContainerView::IsInFolderView() const { return show_state_ == SHOW_ACTIVE_FOLDER; } gfx::Size AppsContainerView::GetPreferredSize() const { const gfx::Size grid_size = apps_grid_view_->GetPreferredSize(); const gfx::Size folder_view_size = app_list_folder_view_->GetPreferredSize(); int width = std::max(grid_size.width(), folder_view_size.width()); int height = std::max(grid_size.height(), folder_view_size.height()); return gfx::Size(width, height); } void AppsContainerView::Layout() { gfx::Rect rect(GetContentsBounds()); if (rect.IsEmpty()) return; switch (show_state_) { case SHOW_APPS: apps_grid_view_->SetBoundsRect(rect); break; case SHOW_ACTIVE_FOLDER: folder_background_view_->SetBoundsRect(rect); app_list_folder_view_->SetBoundsRect(rect); break; case SHOW_ITEM_REPARENT: break; default: NOTREACHED(); } } bool AppsContainerView::OnKeyPressed(const ui::KeyEvent& event) { if (show_state_ == SHOW_APPS) return apps_grid_view_->OnKeyPressed(event); else return app_list_folder_view_->OnKeyPressed(event); } void AppsContainerView::OnTopIconAnimationsComplete() { --top_icon_animation_pending_count_; if (!top_icon_animation_pending_count_) { // Clean up the transitional views used for top item icon animation. top_icon_views_.clear(); // Show the folder icon when closing the folder. if ((show_state_ == SHOW_APPS || show_state_ == SHOW_ITEM_REPARENT) && apps_grid_view_->activated_folder_item_view()) { apps_grid_view_->activated_folder_item_view()->SetVisible(true); } } } void AppsContainerView::SetShowState(ShowState show_state, bool show_apps_with_animation) { if (show_state_ == show_state) return; show_state_ = show_state; switch (show_state_) { case SHOW_APPS: folder_background_view_->SetVisible(false); if (show_apps_with_animation) { app_list_folder_view_->ScheduleShowHideAnimation(false, false); apps_grid_view_->ScheduleShowHideAnimation(true); } else { app_list_folder_view_->HideViewImmediately(); apps_grid_view_->ResetForShowApps(); } break; case SHOW_ACTIVE_FOLDER: folder_background_view_->SetVisible(true); apps_grid_view_->ScheduleShowHideAnimation(false); app_list_folder_view_->ScheduleShowHideAnimation(true, false); break; case SHOW_ITEM_REPARENT: folder_background_view_->SetVisible(false); folder_background_view_->UpdateFolderContainerBubble( FolderBackgroundView::NO_BUBBLE); app_list_folder_view_->ScheduleShowHideAnimation(false, true); apps_grid_view_->ScheduleShowHideAnimation(true); break; default: NOTREACHED(); } Layout(); } Rects AppsContainerView::GetTopItemIconBoundsInActiveFolder() { // Get the active folder's icon bounds relative to AppsContainerView. AppListItemView* folder_item_view = apps_grid_view_->activated_folder_item_view(); gfx::Rect to_grid_view = folder_item_view->ConvertRectToParent( folder_item_view->GetIconBounds()); gfx::Rect to_container = apps_grid_view_->ConvertRectToParent(to_grid_view); return AppListFolderItem::GetTopIconsBounds(to_container); } void AppsContainerView::CreateViewsForFolderTopItemsAnimation( AppListFolderItem* active_folder, bool open_folder) { top_icon_views_.clear(); std::vector top_items_bounds = GetTopItemIconBoundsInActiveFolder(); top_icon_animation_pending_count_ = std::min(kNumFolderTopItems, active_folder->item_list()->item_count()); for (size_t i = 0; i < top_icon_animation_pending_count_; ++i) { if (active_folder->GetTopIcon(i).isNull()) continue; TopIconAnimationView* icon_view = new TopIconAnimationView( active_folder->GetTopIcon(i), top_items_bounds[i], open_folder); icon_view->AddObserver(this); top_icon_views_.push_back(icon_view); // Add the transitional views into child views, and set its bounds to the // same location of the item in the folder list view. AddChildView(top_icon_views_[i]); top_icon_views_[i]->SetBoundsRect( app_list_folder_view_->ConvertRectToParent( app_list_folder_view_->GetItemIconBoundsAt(i))); static_cast(top_icon_views_[i])->TransformView(); } } void AppsContainerView::PrepareToShowApps(AppListFolderItem* folder_item) { if (folder_item) CreateViewsForFolderTopItemsAnimation(folder_item, false); // Hide the active folder item until the animation completes. if (apps_grid_view_->activated_folder_item_view()) apps_grid_view_->activated_folder_item_view()->SetVisible(false); } } // namespace app_list