Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / app_list / folder_image.cc
bloba542f553b1d103fcd9c1d46ba178304b81ee9160
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.
5 #include "ui/app_list/folder_image.h"
7 #include <vector>
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"
22 namespace app_list {
24 namespace {
26 const int kItemIconDimension = 16;
28 // Gets the size of a small app icon inside the folder icon.
29 gfx::Size ItemIconSize() {
30 return gfx::Size(kItemIconDimension, kItemIconDimension);
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;
38 FolderImageSource(const Icons& icons, const gfx::Size& size);
39 ~FolderImageSource() override;
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);
48 // gfx::CanvasImageSource overrides:
49 void Draw(gfx::Canvas* canvas) override;
51 Icons icons_;
52 gfx::Size size_;
54 DISALLOW_COPY_AND_ASSIGN(FolderImageSource);
57 FolderImageSource::FolderImageSource(const Icons& icons, const gfx::Size& size)
58 : gfx::CanvasImageSource(size, false), icons_(icons), size_(size) {
59 DCHECK(icons.size() <= kNumFolderTopItems);
62 FolderImageSource::~FolderImageSource() {
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;
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);
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);
95 if (icons_.size() == 0)
96 return;
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()));
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());
109 } // namespace
111 FolderImage::FolderImage(AppListItemList* item_list) : item_list_(item_list) {
112 item_list_->AddObserver(this);
115 FolderImage::~FolderImage() {
116 for (auto* item : top_items_)
117 item->RemoveObserver(this);
118 item_list_->RemoveObserver(this);
121 void FolderImage::UpdateIcon() {
122 for (auto* item : top_items_)
123 item->RemoveObserver(this);
124 top_items_.clear();
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);
132 RedrawIconAndNotify();
135 const gfx::ImageSkia& FolderImage::GetTopIcon(size_t item_index) const {
136 CHECK_LT(item_index, top_items_.size());
137 return top_items_[item_index]->icon();
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;
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);
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);
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);
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);
169 return top_icon_bounds;
172 gfx::Rect FolderImage::GetTargetIconRectInFolderForItem(
173 AppListItem* item,
174 const gfx::Rect& folder_icon_bounds) const {
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];
182 gfx::Rect target_rect(folder_icon_bounds);
183 target_rect.ClampToCenteredSize(ItemIconSize());
184 return target_rect;
187 void FolderImage::AddObserver(FolderImageObserver* observer) {
188 observers_.AddObserver(observer);
191 void FolderImage::RemoveObserver(FolderImageObserver* observer) {
192 observers_.RemoveObserver(observer);
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();
203 void FolderImage::OnListItemAdded(size_t index, AppListItem* item) {
204 if (index < kNumFolderTopItems)
205 UpdateIcon();
208 void FolderImage::OnListItemRemoved(size_t index, AppListItem* item) {
209 if (index < kNumFolderTopItems)
210 UpdateIcon();
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();
220 void FolderImage::RedrawIconAndNotify() {
221 FolderImageSource::Icons top_icons;
222 for (const auto* item : top_items_)
223 top_icons.push_back(item->icon());
225 const gfx::Size icon_size = gfx::Size(kGridIconDimension, kGridIconDimension);
226 icon_ =
227 gfx::ImageSkia(new FolderImageSource(top_icons, icon_size), icon_size);
229 FOR_EACH_OBSERVER(FolderImageObserver, observers_, OnFolderImageUpdated());
232 } // namespace app_list