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;
     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