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