• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FolderImageSource(const Icons & icons,const gfx::Size & size)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 
~FolderImageSource()32   virtual ~FolderImageSource() {}
33 
34  private:
DrawIcon(gfx::Canvas * canvas,const gfx::ImageSkia & icon,const gfx::Size icon_size,int x,int y)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:
Draw(gfx::Canvas * canvas)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 
AppListFolderItem(const std::string & id,FolderType folder_type)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 
~AppListFolderItem()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 
UpdateIcon()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 
GetTopIcon(size_t item_index)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 
GetTargetIconRectInFolderForItem(AppListItem * item,const gfx::Rect & folder_icon_bounds)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 
Activate(int event_flags)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
GetTopIconsBounds(const gfx::Rect & folder_icon_bounds)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 
GetItemType() const169 const char* AppListFolderItem::GetItemType() const {
170   return AppListFolderItem::kItemType;
171 }
172 
GetContextMenuModel()173 ui::MenuModel* AppListFolderItem::GetContextMenuModel() {
174   // TODO(stevenjb/jennyz): Implement.
175   return NULL;
176 }
177 
FindChildItem(const std::string & id)178 AppListItem* AppListFolderItem::FindChildItem(const std::string& id) {
179   return item_list_->FindItem(id);
180 }
181 
ChildItemCount() const182 size_t AppListFolderItem::ChildItemCount() const {
183   return item_list_->item_count();
184 }
185 
OnExtensionPreferenceChanged()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 
CompareForTest(const AppListItem * other) const191 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 
GenerateId()206 std::string AppListFolderItem::GenerateId() {
207   return base::GenerateGUID();
208 }
209 
ItemIconChanged()210 void AppListFolderItem::ItemIconChanged() {
211   UpdateIcon();
212 }
213 
ItemNameChanged()214 void AppListFolderItem::ItemNameChanged() {
215 }
216 
ItemHighlightedChanged()217 void AppListFolderItem::ItemHighlightedChanged() {
218 }
219 
ItemIsInstallingChanged()220 void AppListFolderItem::ItemIsInstallingChanged() {
221 }
222 
ItemPercentDownloadedChanged()223 void AppListFolderItem::ItemPercentDownloadedChanged() {
224 }
225 
OnListItemAdded(size_t index,AppListItem * item)226 void AppListFolderItem::OnListItemAdded(size_t index,
227                                         AppListItem* item) {
228   if (index <= kNumFolderTopItems)
229     UpdateTopItems();
230 }
231 
OnListItemRemoved(size_t index,AppListItem * item)232 void AppListFolderItem::OnListItemRemoved(size_t index,
233                                           AppListItem* item) {
234   if (index <= kNumFolderTopItems)
235     UpdateTopItems();
236 }
237 
OnListItemMoved(size_t from_index,size_t to_index,AppListItem * item)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 
UpdateTopItems()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