Home | History | Annotate | Download | only in app_list
      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/app_list_folder_item.h"
      6 
      7 #include "base/guid.h"
      8 #include "ui/app_list/app_list_constants.h"
      9 #include "ui/app_list/app_list_item_list.h"
     10 #include "ui/gfx/canvas.h"
     11 #include "ui/gfx/image/canvas_image_source.h"
     12 #include "ui/gfx/image/image_skia_operations.h"
     13 
     14 namespace app_list {
     15 
     16 namespace {
     17 
     18 const int kItemIconDimension = 16;
     19 
     20 // Generates the folder icon with the top 4 child item icons laid in 2x2 tile.
     21 class FolderImageSource : public gfx::CanvasImageSource {
     22  public:
     23   typedef std::vector<gfx::ImageSkia> Icons;
     24 
     25   FolderImageSource(const Icons& icons, const gfx::Size& size)
     26       : gfx::CanvasImageSource(size, false),
     27         icons_(icons),
     28         size_(size) {
     29     DCHECK(icons.size() <= kNumFolderTopItems);
     30   }
     31 
     32   virtual ~FolderImageSource() {}
     33 
     34  private:
     35   void DrawIcon(gfx::Canvas* canvas,
     36                 const gfx::ImageSkia& icon,
     37                 const gfx::Size icon_size,
     38                 int x, int y) {
     39     if (icon.isNull())
     40       return;
     41 
     42     gfx::ImageSkia resized(
     43         gfx::ImageSkiaOperations::CreateResizedImage(
     44             icon, skia::ImageOperations::RESIZE_BEST, icon_size));
     45     canvas->DrawImageInt(resized, 0, 0, resized.width(), resized.height(),
     46         x, y, resized.width(), resized.height(), true);
     47   }
     48 
     49   // gfx::CanvasImageSource overrides:
     50   virtual void Draw(gfx::Canvas* canvas) OVERRIDE {
     51     // Draw folder circle.
     52     gfx::Point center = gfx::Point(size().width() / 2 , size().height() / 2);
     53     SkPaint paint;
     54     paint.setStyle(SkPaint::kFill_Style);
     55     paint.setAntiAlias(true);
     56     paint.setColor(kFolderBubbleColor);
     57     canvas->DrawCircle(center, size().width() / 2, paint);
     58 
     59     if (icons_.size() == 0)
     60       return;
     61 
     62     // Draw top items' icons.
     63     const gfx::Size item_icon_size =
     64         gfx::Size(kItemIconDimension, kItemIconDimension);
     65     Rects top_icon_bounds =
     66         AppListFolderItem::GetTopIconsBounds(gfx::Rect(size()));
     67 
     68     for (size_t i= 0; i < kNumFolderTopItems && i < icons_.size(); ++i) {
     69       DrawIcon(canvas, icons_[i], item_icon_size,
     70                top_icon_bounds[i].x(), top_icon_bounds[i].y());
     71     }
     72   }
     73 
     74   Icons icons_;
     75   gfx::Size size_;
     76 
     77   DISALLOW_COPY_AND_ASSIGN(FolderImageSource);
     78 };
     79 
     80 }  // namespace
     81 
     82 AppListFolderItem::AppListFolderItem(const std::string& id,
     83                                      FolderType folder_type)
     84     : AppListItem(id),
     85       folder_type_(folder_type),
     86       item_list_(new AppListItemList) {
     87   item_list_->AddObserver(this);
     88 }
     89 
     90 AppListFolderItem::~AppListFolderItem() {
     91   for (size_t i = 0; i < top_items_.size(); ++i)
     92     top_items_[i]->RemoveObserver(this);
     93   item_list_->RemoveObserver(this);
     94 }
     95 
     96 void AppListFolderItem::UpdateIcon() {
     97   FolderImageSource::Icons top_icons;
     98   for (size_t i = 0; i < top_items_.size(); ++i)
     99     top_icons.push_back(top_items_[i]->icon());
    100 
    101   const gfx::Size icon_size =
    102       gfx::Size(kPreferredIconDimension, kPreferredIconDimension);
    103   gfx::ImageSkia icon = gfx::ImageSkia(
    104       new FolderImageSource(top_icons, icon_size),
    105       icon_size);
    106   SetIcon(icon, false);
    107 }
    108 
    109 const gfx::ImageSkia& AppListFolderItem::GetTopIcon(size_t item_index) {
    110   DCHECK(item_index <= top_items_.size());
    111   return top_items_[item_index]->icon();
    112 }
    113 
    114 gfx::Rect AppListFolderItem::GetTargetIconRectInFolderForItem(
    115     AppListItem* item,
    116     const gfx::Rect& folder_icon_bounds) {
    117   for (size_t i = 0; i < top_items_.size(); ++i) {
    118     if (item->id() == top_items_[i]->id()) {
    119       Rects rects = AppListFolderItem::GetTopIconsBounds(folder_icon_bounds);
    120       return rects[i];
    121     }
    122   }
    123 
    124   gfx::Rect target_rect(folder_icon_bounds);
    125   target_rect.ClampToCenteredSize(
    126       gfx::Size(kItemIconDimension, kItemIconDimension));
    127   return target_rect;
    128 }
    129 
    130 void AppListFolderItem::Activate(int event_flags) {
    131   // Folder handling is implemented by the View, so do nothing.
    132 }
    133 
    134 // static
    135 const char AppListFolderItem::kItemType[] = "FolderItem";
    136 
    137 // static
    138 Rects AppListFolderItem::GetTopIconsBounds(
    139     const gfx::Rect& folder_icon_bounds) {
    140   const int delta_to_center = 1;
    141   gfx::Point icon_center = folder_icon_bounds.CenterPoint();
    142   Rects top_icon_bounds;
    143 
    144   // Get the top left icon bounds.
    145   int left_x = icon_center.x() - kItemIconDimension - delta_to_center;
    146   int top_y = icon_center.y() - kItemIconDimension - delta_to_center;
    147   gfx::Rect top_left(left_x, top_y, kItemIconDimension, kItemIconDimension);
    148   top_icon_bounds.push_back(top_left);
    149 
    150   // Get the top right icon bounds.
    151   int right_x = icon_center.x() + delta_to_center;
    152   gfx::Rect top_right(right_x, top_y, kItemIconDimension, kItemIconDimension);
    153   top_icon_bounds.push_back(top_right);
    154 
    155   // Get the bottom left icon bounds.
    156   int bottom_y = icon_center.y() + delta_to_center;
    157   gfx::Rect bottom_left(
    158       left_x, bottom_y, kItemIconDimension, kItemIconDimension);
    159   top_icon_bounds.push_back(bottom_left);
    160 
    161   // Get the bottom right icon bounds.
    162   gfx::Rect bottom_right(
    163       right_x, bottom_y, kItemIconDimension, kItemIconDimension);
    164   top_icon_bounds.push_back(bottom_right);
    165 
    166   return top_icon_bounds;
    167 }
    168 
    169 const char* AppListFolderItem::GetItemType() const {
    170   return AppListFolderItem::kItemType;
    171 }
    172 
    173 ui::MenuModel* AppListFolderItem::GetContextMenuModel() {
    174   // TODO(stevenjb/jennyz): Implement.
    175   return NULL;
    176 }
    177 
    178 AppListItem* AppListFolderItem::FindChildItem(const std::string& id) {
    179   return item_list_->FindItem(id);
    180 }
    181 
    182 size_t AppListFolderItem::ChildItemCount() const {
    183   return item_list_->item_count();
    184 }
    185 
    186 void AppListFolderItem::OnExtensionPreferenceChanged() {
    187   for (size_t i = 0; i < item_list_->item_count(); ++i)
    188     item_list_->item_at(i)->OnExtensionPreferenceChanged();
    189 }
    190 
    191 bool AppListFolderItem::CompareForTest(const AppListItem* other) const {
    192   if (!AppListItem::CompareForTest(other))
    193     return false;
    194   const AppListFolderItem* other_folder =
    195       static_cast<const AppListFolderItem*>(other);
    196   if (other_folder->item_list()->item_count() != item_list_->item_count())
    197     return false;
    198   for (size_t i = 0; i < item_list_->item_count(); ++i) {
    199     if (!item_list()->item_at(i)->CompareForTest(
    200             other_folder->item_list()->item_at(i)))
    201       return false;
    202   }
    203   return true;
    204 }
    205 
    206 std::string AppListFolderItem::GenerateId() {
    207   return base::GenerateGUID();
    208 }
    209 
    210 void AppListFolderItem::ItemIconChanged() {
    211   UpdateIcon();
    212 }
    213 
    214 void AppListFolderItem::ItemNameChanged() {
    215 }
    216 
    217 void AppListFolderItem::ItemHighlightedChanged() {
    218 }
    219 
    220 void AppListFolderItem::ItemIsInstallingChanged() {
    221 }
    222 
    223 void AppListFolderItem::ItemPercentDownloadedChanged() {
    224 }
    225 
    226 void AppListFolderItem::OnListItemAdded(size_t index,
    227                                         AppListItem* item) {
    228   if (index <= kNumFolderTopItems)
    229     UpdateTopItems();
    230 }
    231 
    232 void AppListFolderItem::OnListItemRemoved(size_t index,
    233                                           AppListItem* item) {
    234   if (index <= kNumFolderTopItems)
    235     UpdateTopItems();
    236 }
    237 
    238 void AppListFolderItem::OnListItemMoved(size_t from_index,
    239                                         size_t to_index,
    240                                         AppListItem* item) {
    241   if (from_index <= kNumFolderTopItems || to_index <= kNumFolderTopItems)
    242     UpdateTopItems();
    243 }
    244 
    245 void AppListFolderItem::UpdateTopItems() {
    246   for (size_t i = 0; i < top_items_.size(); ++i)
    247     top_items_[i]->RemoveObserver(this);
    248   top_items_.clear();
    249 
    250   for (size_t i = 0;
    251        i < kNumFolderTopItems && i < item_list_->item_count(); ++i) {
    252     AppListItem* item = item_list_->item_at(i);
    253     item->AddObserver(this);
    254     top_items_.push_back(item);
    255   }
    256   UpdateIcon();
    257 }
    258 
    259 }  // namespace app_list
    260