| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/app_list/app_list_item_view.h" | 5 #include "ui/app_list/app_list_item_view.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | |
| 10 #include "base/message_loop.h" | |
| 11 #include "base/synchronization/cancellation_flag.h" | |
| 12 #include "base/threading/worker_pool.h" | |
| 13 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
| 14 #include "ui/app_list/app_list_constants.h" | 10 #include "ui/app_list/app_list_constants.h" |
| 15 #include "ui/app_list/app_list_item_model.h" | 11 #include "ui/app_list/app_list_item_model.h" |
| 16 #include "ui/app_list/apps_grid_view.h" | 12 #include "ui/app_list/apps_grid_view.h" |
| 17 #include "ui/app_list/drop_shadow_label.h" | 13 #include "ui/app_list/drop_shadow_label.h" |
| 18 #include "ui/app_list/icon_cache.h" | |
| 19 #include "ui/base/accessibility/accessible_view_state.h" | 14 #include "ui/base/accessibility/accessible_view_state.h" |
| 20 #include "ui/base/animation/throb_animation.h" | 15 #include "ui/base/animation/throb_animation.h" |
| 21 #include "ui/base/resource/resource_bundle.h" | 16 #include "ui/base/resource/resource_bundle.h" |
| 22 #include "ui/gfx/canvas.h" | 17 #include "ui/gfx/canvas.h" |
| 23 #include "ui/gfx/font.h" | 18 #include "ui/gfx/font.h" |
| 24 #include "ui/gfx/image/image_skia_operations.h" | 19 #include "ui/gfx/image/image_skia_operations.h" |
| 25 #include "ui/views/controls/image_view.h" | 20 #include "ui/views/controls/image_view.h" |
| 26 #include "ui/views/controls/menu/menu_item_view.h" | 21 #include "ui/views/controls/menu/menu_item_view.h" |
| 27 #include "ui/views/controls/menu/menu_model_adapter.h" | 22 #include "ui/views/controls/menu/menu_model_adapter.h" |
| 28 #include "ui/views/controls/menu/menu_runner.h" | 23 #include "ui/views/controls/menu/menu_runner.h" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 } | 69 } |
| 75 | 70 |
| 76 DISALLOW_COPY_AND_ASSIGN(StaticImageView); | 71 DISALLOW_COPY_AND_ASSIGN(StaticImageView); |
| 77 }; | 72 }; |
| 78 | 73 |
| 79 } // namespace | 74 } // namespace |
| 80 | 75 |
| 81 // static | 76 // static |
| 82 const char AppListItemView::kViewClassName[] = "ui/app_list/AppListItemView"; | 77 const char AppListItemView::kViewClassName[] = "ui/app_list/AppListItemView"; |
| 83 | 78 |
| 84 // AppListItemView::IconOperation wraps background icon processing. | |
| 85 class AppListItemView::IconOperation | |
| 86 : public base::RefCountedThreadSafe<AppListItemView::IconOperation> { | |
| 87 public: | |
| 88 IconOperation(const gfx::ImageSkia& image, | |
| 89 const gfx::Size& size, | |
| 90 const gfx::ShadowValues& shadows) | |
| 91 : image_(image), | |
| 92 size_(size), | |
| 93 shadows_(shadows) { | |
| 94 } | |
| 95 | |
| 96 static void Run(scoped_refptr<IconOperation> op) { | |
| 97 op->ResizeAndGenerateShadow(); | |
| 98 } | |
| 99 | |
| 100 void ResizeAndGenerateShadow() { | |
| 101 if (cancel_flag_.IsSet()) | |
| 102 return; | |
| 103 | |
| 104 gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage(image_, | |
| 105 skia::ImageOperations::RESIZE_BEST, size_)); | |
| 106 gfx::ImageSkia shadow( | |
| 107 gfx::ImageSkiaOperations::CreateImageWithDropShadow(resized, shadows_)); | |
| 108 image_ = shadow; | |
| 109 image_.MakeThreadSafe(); | |
| 110 } | |
| 111 | |
| 112 void Cancel() { | |
| 113 cancel_flag_.Set(); | |
| 114 } | |
| 115 | |
| 116 const gfx::ImageSkia& image() const { | |
| 117 return image_; | |
| 118 } | |
| 119 | |
| 120 private: | |
| 121 friend class base::RefCountedThreadSafe<AppListItemView::IconOperation>; | |
| 122 ~IconOperation() {} | |
| 123 | |
| 124 base::CancellationFlag cancel_flag_; | |
| 125 | |
| 126 gfx::ImageSkia image_; | |
| 127 const gfx::Size size_; | |
| 128 const gfx::ShadowValues shadows_; | |
| 129 | |
| 130 DISALLOW_COPY_AND_ASSIGN(IconOperation); | |
| 131 }; | |
| 132 | |
| 133 AppListItemView::AppListItemView(AppsGridView* apps_grid_view, | 79 AppListItemView::AppListItemView(AppsGridView* apps_grid_view, |
| 134 AppListItemModel* model, | 80 AppListItemModel* model, |
| 135 views::ButtonListener* listener) | 81 views::ButtonListener* listener) |
| 136 : CustomButton(listener), | 82 : CustomButton(listener), |
| 137 model_(model), | 83 model_(model), |
| 138 apps_grid_view_(apps_grid_view), | 84 apps_grid_view_(apps_grid_view), |
| 139 icon_(new StaticImageView), | 85 icon_(new StaticImageView), |
| 140 title_(new DropShadowLabel), | 86 title_(new DropShadowLabel) { |
| 141 ALLOW_THIS_IN_INITIALIZER_LIST(apply_shadow_factory_(this)) { | |
| 142 title_->SetBackgroundColor(kTitleBackgroundColor); | 87 title_->SetBackgroundColor(kTitleBackgroundColor); |
| 143 title_->SetEnabledColor(kTitleColor); | 88 title_->SetEnabledColor(kTitleColor); |
| 144 title_->SetFont(GetTitleFont()); | 89 title_->SetFont(GetTitleFont()); |
| 145 | 90 |
| 146 const gfx::ShadowValue kIconShadows[] = { | 91 const gfx::ShadowValue kIconShadows[] = { |
| 147 gfx::ShadowValue(gfx::Point(0, 2), 2, SkColorSetARGB(0x24, 0, 0, 0)), | 92 gfx::ShadowValue(gfx::Point(0, 2), 2, SkColorSetARGB(0x24, 0, 0, 0)), |
| 148 }; | 93 }; |
| 149 icon_shadows_.assign(kIconShadows, kIconShadows + arraysize(kIconShadows)); | 94 icon_shadows_.assign(kIconShadows, kIconShadows + arraysize(kIconShadows)); |
| 150 | 95 |
| 151 AddChildView(icon_); | 96 AddChildView(icon_); |
| 152 AddChildView(title_); | 97 AddChildView(title_); |
| 153 | 98 |
| 154 ItemIconChanged(); | 99 ItemIconChanged(); |
| 155 ItemTitleChanged(); | 100 ItemTitleChanged(); |
| 156 model_->AddObserver(this); | 101 model_->AddObserver(this); |
| 157 | 102 |
| 158 set_context_menu_controller(this); | 103 set_context_menu_controller(this); |
| 159 set_request_focus_on_press(false); | 104 set_request_focus_on_press(false); |
| 160 } | 105 } |
| 161 | 106 |
| 162 AppListItemView::~AppListItemView() { | 107 AppListItemView::~AppListItemView() { |
| 163 model_->RemoveObserver(this); | 108 model_->RemoveObserver(this); |
| 164 CancelPendingIconOperation(); | |
| 165 } | 109 } |
| 166 | 110 |
| 167 void AppListItemView::SetIconSize(const gfx::Size& size) { | 111 void AppListItemView::SetIconSize(const gfx::Size& size) { |
| 168 if (icon_size_ == size) | 112 if (icon_size_ == size) |
| 169 return; | 113 return; |
| 170 | 114 |
| 171 icon_size_ = size; | 115 icon_size_ = size; |
| 172 UpdateIcon(); | 116 UpdateIcon(); |
| 173 } | 117 } |
| 174 | 118 |
| 175 void AppListItemView::UpdateIcon() { | 119 void AppListItemView::UpdateIcon() { |
| 176 // Skip if |icon_size_| has not been determined. | 120 // Skip if |icon_size_| has not been determined. |
| 177 if (icon_size_.IsEmpty()) | 121 if (icon_size_.IsEmpty()) |
| 178 return; | 122 return; |
| 179 | 123 |
| 180 gfx::ImageSkia icon = model_->icon(); | 124 gfx::ImageSkia icon = model_->icon(); |
| 181 // Clear icon and bail out if model icon is empty. | 125 // Clear icon and bail out if model icon is empty. |
| 182 if (icon.isNull()) { | 126 if (icon.isNull()) { |
| 183 icon_->SetImage(NULL); | 127 icon_->SetImage(NULL); |
| 184 return; | 128 return; |
| 185 } | 129 } |
| 186 | 130 |
| 187 CancelPendingIconOperation(); | 131 gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage(icon, |
| 188 | 132 skia::ImageOperations::RESIZE_BEST, icon_size_)); |
| 189 gfx::ImageSkia shadow; | 133 gfx::ImageSkia shadow( |
| 190 if (IconCache::GetInstance()->Get(icon, icon_size_, &shadow)) { | 134 gfx::ImageSkiaOperations::CreateImageWithDropShadow(resized, |
| 191 icon_->SetImage(shadow); | 135 icon_shadows_)); |
| 192 } else { | 136 icon_->SetImage(shadow); |
| 193 // Schedule resize and shadow generation. | |
| 194 icon_op_ = new IconOperation(icon, icon_size_, icon_shadows_); | |
| 195 base::WorkerPool::PostTaskAndReply( | |
| 196 FROM_HERE, | |
| 197 base::Bind(&IconOperation::Run, icon_op_), | |
| 198 base::Bind(&AppListItemView::ApplyShadow, | |
| 199 apply_shadow_factory_.GetWeakPtr(), | |
| 200 icon_op_), | |
| 201 true /* task_is_slow */); | |
| 202 } | |
| 203 } | |
| 204 | |
| 205 void AppListItemView::CancelPendingIconOperation() { | |
| 206 // Set canceled flag of previous request to skip unneeded processing. | |
| 207 if (icon_op_.get()) | |
| 208 icon_op_->Cancel(); | |
| 209 | |
| 210 // Cancel reply callback for previous request. | |
| 211 apply_shadow_factory_.InvalidateWeakPtrs(); | |
| 212 } | |
| 213 | |
| 214 void AppListItemView::ApplyShadow(scoped_refptr<IconOperation> op) { | |
| 215 icon_->SetImage(op->image()); | |
| 216 IconCache::GetInstance()->Put(model_->icon(), icon_size_, op->image()); | |
| 217 | |
| 218 DCHECK(op.get() == icon_op_.get()); | |
| 219 icon_op_ = NULL; | |
| 220 } | 137 } |
| 221 | 138 |
| 222 void AppListItemView::ItemIconChanged() { | 139 void AppListItemView::ItemIconChanged() { |
| 223 UpdateIcon(); | 140 UpdateIcon(); |
| 224 } | 141 } |
| 225 | 142 |
| 226 void AppListItemView::ItemTitleChanged() { | 143 void AppListItemView::ItemTitleChanged() { |
| 227 title_->SetText(UTF8ToUTF16(model_->title())); | 144 title_->SetText(UTF8ToUTF16(model_->title())); |
| 228 } | 145 } |
| 229 | 146 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 bool AppListItemView::ShouldEnterPushedState(const ui::Event& event) { | 228 bool AppListItemView::ShouldEnterPushedState(const ui::Event& event) { |
| 312 // Don't enter pushed state for ET_GESTURE_TAP_DOWN so that hover gray | 229 // Don't enter pushed state for ET_GESTURE_TAP_DOWN so that hover gray |
| 313 // background does not show up during scroll. | 230 // background does not show up during scroll. |
| 314 if (event.type() == ui::ET_GESTURE_TAP_DOWN) | 231 if (event.type() == ui::ET_GESTURE_TAP_DOWN) |
| 315 return false; | 232 return false; |
| 316 | 233 |
| 317 return views::CustomButton::ShouldEnterPushedState(event); | 234 return views::CustomButton::ShouldEnterPushedState(event); |
| 318 } | 235 } |
| 319 | 236 |
| 320 } // namespace app_list | 237 } // namespace app_list |
| OLD | NEW |