Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / ui / app_list / folder_image.cc
1 // Copyright 2014 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/folder_image.h"
6
7 #include <vector>
8
9 #include "ui/app_list/app_list_constants.h"
10 #include "ui/app_list/app_list_item.h"
11 #include "ui/app_list/app_list_item_list.h"
12 #include "ui/base/l10n/l10n_util.h"
13 #include "ui/gfx/canvas.h"
14 #include "ui/gfx/geometry/point.h"
15 #include "ui/gfx/geometry/rect.h"
16 #include "ui/gfx/geometry/size.h"
17 #include "ui/gfx/image/canvas_image_source.h"
18 #include "ui/gfx/image/image_skia.h"
19 #include "ui/gfx/image/image_skia_operations.h"
20 #include "ui/strings/grit/ui_strings.h"
21
22 namespace app_list {
23
24 namespace {
25
26 const int kItemIconDimension = 16;
27
28 // Gets the size of a small app icon inside the folder icon.
29 gfx::Size ItemIconSize() {
30   return gfx::Size(kItemIconDimension, kItemIconDimension);
31 }
32
33 // Generates the folder icon with the top 4 child item icons laid in 2x2 tile.
34 class FolderImageSource : public gfx::CanvasImageSource {
35  public:
36   typedef std::vector<gfx::ImageSkia> Icons;
37
38   FolderImageSource(const Icons& icons, const gfx::Size& size);
39   ~FolderImageSource() override;
40
41  private:
42   void DrawIcon(gfx::Canvas* canvas,
43                 const gfx::ImageSkia& icon,
44                 const gfx::Size icon_size,
45                 int x,
46                 int y);
47
48   // gfx::CanvasImageSource overrides:
49   void Draw(gfx::Canvas* canvas) override;
50
51   Icons icons_;
52   gfx::Size size_;
53
54   DISALLOW_COPY_AND_ASSIGN(FolderImageSource);
55 };
56
57 FolderImageSource::FolderImageSource(const Icons& icons, const gfx::Size& size)
58     : gfx::CanvasImageSource(size, false), icons_(icons), size_(size) {
59   DCHECK(icons.size() <= kNumFolderTopItems);
60 }
61
62 FolderImageSource::~FolderImageSource() {
63 }
64
65 void FolderImageSource::DrawIcon(gfx::Canvas* canvas,
66                                  const gfx::ImageSkia& icon,
67                                  const gfx::Size icon_size,
68                                  int x,
69                                  int y) {
70   if (icon.isNull())
71     return;
72
73   gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage(
74       icon, skia::ImageOperations::RESIZE_BEST, icon_size));
75   canvas->DrawImageInt(resized, 0, 0, resized.width(), resized.height(), x, y,
76                        resized.width(), resized.height(), true);
77 }
78
79 void FolderImageSource::Draw(gfx::Canvas* canvas) {
80   // Draw circle for folder shadow.
81   gfx::PointF shadow_center(size().width() / 2, size().height() / 2);
82   SkPaint paint;
83   paint.setStyle(SkPaint::kFill_Style);
84   paint.setAntiAlias(true);
85   paint.setColor(kFolderShadowColor);
86   canvas->sk_canvas()->drawCircle(shadow_center.x(), shadow_center.y(),
87                                   kFolderShadowRadius, paint);
88   // Draw circle for folder bubble.
89   gfx::PointF bubble_center(shadow_center);
90   bubble_center.Offset(0, -kFolderShadowOffsetY);
91   paint.setColor(kFolderBubbleColor);
92   canvas->sk_canvas()->drawCircle(bubble_center.x(), bubble_center.y(),
93                                   kFolderBubbleRadius, paint);
94
95   if (icons_.size() == 0)
96     return;
97
98   // Draw top items' icons.
99   const gfx::Size item_icon_size(ItemIconSize());
100   std::vector<gfx::Rect> top_icon_bounds =
101       FolderImage::GetTopIconsBounds(gfx::Rect(size()));
102
103   for (size_t i = 0; i < kNumFolderTopItems && i < icons_.size(); ++i) {
104     DrawIcon(canvas, icons_[i], item_icon_size, top_icon_bounds[i].x(),
105              top_icon_bounds[i].y());
106   }
107 }
108
109 }  // namespace
110
111 FolderImage::FolderImage(AppListItemList* item_list) : item_list_(item_list) {
112   item_list_->AddObserver(this);
113 }
114
115 FolderImage::~FolderImage() {
116   for (auto* item : top_items_)
117     item->RemoveObserver(this);
118   item_list_->RemoveObserver(this);
119 }
120
121 void FolderImage::UpdateIcon() {
122   for (auto* item : top_items_)
123     item->RemoveObserver(this);
124   top_items_.clear();
125
126   for (size_t i = 0; i < kNumFolderTopItems && i < item_list_->item_count();
127        ++i) {
128     AppListItem* item = item_list_->item_at(i);
129     item->AddObserver(this);
130     top_items_.push_back(item);
131   }
132   RedrawIconAndNotify();
133 }
134
135 const gfx::ImageSkia& FolderImage::GetTopIcon(size_t item_index) {
136   CHECK_LT(item_index, top_items_.size());
137   return top_items_[item_index]->icon();
138 }
139
140 // static
141 std::vector<gfx::Rect> FolderImage::GetTopIconsBounds(
142     const gfx::Rect& folder_icon_bounds) {
143   const int delta_to_center = 1;
144   gfx::Point icon_center = folder_icon_bounds.CenterPoint();
145   std::vector<gfx::Rect> top_icon_bounds;
146
147   // Get the top left icon bounds.
148   int left_x = icon_center.x() - kItemIconDimension - delta_to_center;
149   int top_y = icon_center.y() - kItemIconDimension - delta_to_center;
150   gfx::Rect top_left(left_x, top_y, kItemIconDimension, kItemIconDimension);
151   top_icon_bounds.push_back(top_left);
152
153   // Get the top right icon bounds.
154   int right_x = icon_center.x() + delta_to_center;
155   gfx::Rect top_right(right_x, top_y, kItemIconDimension, kItemIconDimension);
156   top_icon_bounds.push_back(top_right);
157
158   // Get the bottom left icon bounds.
159   int bottom_y = icon_center.y() + delta_to_center;
160   gfx::Rect bottom_left(left_x, bottom_y, kItemIconDimension,
161                         kItemIconDimension);
162   top_icon_bounds.push_back(bottom_left);
163
164   // Get the bottom right icon bounds.
165   gfx::Rect bottom_right(right_x, bottom_y, kItemIconDimension,
166                          kItemIconDimension);
167   top_icon_bounds.push_back(bottom_right);
168
169   return top_icon_bounds;
170 }
171
172 gfx::Rect FolderImage::GetTargetIconRectInFolderForItem(
173     AppListItem* item,
174     const gfx::Rect& folder_icon_bounds) {
175   for (size_t i = 0; i < top_items_.size(); ++i) {
176     if (item->id() == top_items_[i]->id()) {
177       std::vector<gfx::Rect> rects = GetTopIconsBounds(folder_icon_bounds);
178       return rects[i];
179     }
180   }
181
182   gfx::Rect target_rect(folder_icon_bounds);
183   target_rect.ClampToCenteredSize(ItemIconSize());
184   return target_rect;
185 }
186
187 void FolderImage::AddObserver(FolderImageObserver* observer) {
188   observers_.AddObserver(observer);
189 }
190
191 void FolderImage::RemoveObserver(FolderImageObserver* observer) {
192   observers_.RemoveObserver(observer);
193 }
194
195 void FolderImage::ItemIconChanged() {
196   // Note: Must update the image only (cannot simply call UpdateIcon), because
197   // UpdateIcon removes and re-adds the FolderImage as an observer of the
198   // AppListItems, which causes the current iterator to call ItemIconChanged
199   // again, and goes into an infinite loop.
200   RedrawIconAndNotify();
201 }
202
203 void FolderImage::OnListItemAdded(size_t index, AppListItem* item) {
204   if (index < kNumFolderTopItems)
205     UpdateIcon();
206 }
207
208 void FolderImage::OnListItemRemoved(size_t index, AppListItem* item) {
209   if (index < kNumFolderTopItems)
210     UpdateIcon();
211 }
212
213 void FolderImage::OnListItemMoved(size_t from_index,
214                                   size_t to_index,
215                                   AppListItem* item) {
216   if (from_index < kNumFolderTopItems || to_index < kNumFolderTopItems)
217     UpdateIcon();
218 }
219
220 void FolderImage::RedrawIconAndNotify() {
221   FolderImageSource::Icons top_icons;
222   for (const auto* item : top_items_)
223     top_icons.push_back(item->icon());
224
225   const gfx::Size icon_size = gfx::Size(kGridIconDimension, kGridIconDimension);
226   icon_ =
227       gfx::ImageSkia(new FolderImageSource(top_icons, icon_size), icon_size);
228
229   FOR_EACH_OBSERVER(FolderImageObserver, observers_, OnFolderImageUpdated());
230 }
231
232 }  // namespace app_list