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