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 "chrome/common/extensions/extension_action.h" | 5 #include "chrome/common/extensions/extension_action.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "chrome/common/badge_util.h" | 10 #include "chrome/common/badge_util.h" |
11 #include "googleurl/src/gurl.h" | 11 #include "googleurl/src/gurl.h" |
12 #include "grit/theme_resources.h" | 12 #include "grit/theme_resources.h" |
13 #include "grit/ui_resources.h" | 13 #include "grit/ui_resources.h" |
14 #include "third_party/skia/include/core/SkBitmap.h" | 14 #include "third_party/skia/include/core/SkBitmap.h" |
15 #include "third_party/skia/include/core/SkCanvas.h" | 15 #include "third_party/skia/include/core/SkCanvas.h" |
16 #include "third_party/skia/include/core/SkDevice.h" | 16 #include "third_party/skia/include/core/SkDevice.h" |
17 #include "third_party/skia/include/core/SkPaint.h" | 17 #include "third_party/skia/include/core/SkPaint.h" |
18 #include "third_party/skia/include/effects/SkGradientShader.h" | 18 #include "third_party/skia/include/effects/SkGradientShader.h" |
19 #include "ui/base/animation/animation_delegate.h" | 19 #include "ui/base/animation/animation_delegate.h" |
20 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
21 #include "ui/gfx/canvas.h" | 21 #include "ui/gfx/canvas.h" |
| 22 #include "ui/gfx/color_utils.h" |
22 #include "ui/gfx/rect.h" | 23 #include "ui/gfx/rect.h" |
| 24 #include "ui/gfx/image/image_skia_source.h" |
| 25 #include "ui/gfx/skbitmap_operations.h" |
23 | 26 |
24 namespace { | 27 namespace { |
25 | 28 |
26 // Different platforms need slightly different constants to look good. | 29 // Different platforms need slightly different constants to look good. |
27 #if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS) | 30 #if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS) |
28 const float kTextSize = 9.0; | 31 const float kTextSize = 9.0; |
29 const int kBottomMargin = 0; | 32 const int kBottomMargin = 0; |
30 const int kPadding = 2; | 33 const int kPadding = 2; |
31 const int kTopTextPadding = 0; | 34 const int kTopTextPadding = 0; |
32 #elif defined(OS_LINUX) && defined(TOOLKIT_VIEWS) | 35 #elif defined(OS_LINUX) && defined(TOOLKIT_VIEWS) |
(...skipping 19 matching lines...) Expand all Loading... |
52 // The minimum width for center-aligning the badge. | 55 // The minimum width for center-aligning the badge. |
53 const int kCenterAlignThreshold = 20; | 56 const int kCenterAlignThreshold = 20; |
54 | 57 |
55 | 58 |
56 int Width(const gfx::Image& image) { | 59 int Width(const gfx::Image& image) { |
57 if (image.IsEmpty()) | 60 if (image.IsEmpty()) |
58 return 0; | 61 return 0; |
59 return image.ToSkBitmap()->width(); | 62 return image.ToSkBitmap()->width(); |
60 } | 63 } |
61 | 64 |
| 65 class GetAttentionImageSource : public gfx::ImageSkiaSource { |
| 66 public: |
| 67 explicit GetAttentionImageSource(const gfx::Image& icon) |
| 68 : icon_(*icon.ToImageSkia()) {} |
| 69 |
| 70 // gfx::ImageSkiaSource overrides: |
| 71 virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) |
| 72 OVERRIDE { |
| 73 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale_factor); |
| 74 color_utils::HSL shift = {-1, 0, 0.5}; |
| 75 return gfx::ImageSkiaRep( |
| 76 SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.sk_bitmap(), shift), |
| 77 icon_rep.scale_factor()); |
| 78 } |
| 79 |
| 80 private: |
| 81 const gfx::ImageSkia icon_; |
| 82 }; |
| 83 |
62 } // namespace | 84 } // namespace |
63 | 85 |
64 // Wraps an IconAnimation and implements its ui::AnimationDelegate to delete | 86 // Wraps an IconAnimation and implements its ui::AnimationDelegate to delete |
65 // itself when the animation ends or is cancelled, causing its owned | 87 // itself when the animation ends or is cancelled, causing its owned |
66 // IconAnimation to be destroyed. | 88 // IconAnimation to be destroyed. |
67 class ExtensionAction::IconAnimationWrapper | 89 class ExtensionAction::IconAnimationWrapper |
68 : public ui::AnimationDelegate, | 90 : public ui::AnimationDelegate, |
69 public base::SupportsWeakPtr<IconAnimationWrapper> { | 91 public base::SupportsWeakPtr<IconAnimationWrapper> { |
70 public: | 92 public: |
71 IconAnimationWrapper() | 93 IconAnimationWrapper() |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 scoped_ptr<ExtensionAction> ExtensionAction::CopyForTest() const { | 184 scoped_ptr<ExtensionAction> ExtensionAction::CopyForTest() const { |
163 scoped_ptr<ExtensionAction> copy( | 185 scoped_ptr<ExtensionAction> copy( |
164 new ExtensionAction(extension_id_, action_type_)); | 186 new ExtensionAction(extension_id_, action_type_)); |
165 copy->popup_url_ = popup_url_; | 187 copy->popup_url_ = popup_url_; |
166 copy->title_ = title_; | 188 copy->title_ = title_; |
167 copy->icon_ = icon_; | 189 copy->icon_ = icon_; |
168 copy->icon_index_ = icon_index_; | 190 copy->icon_index_ = icon_index_; |
169 copy->badge_text_ = badge_text_; | 191 copy->badge_text_ = badge_text_; |
170 copy->badge_background_color_ = badge_background_color_; | 192 copy->badge_background_color_ = badge_background_color_; |
171 copy->badge_text_color_ = badge_text_color_; | 193 copy->badge_text_color_ = badge_text_color_; |
172 copy->visible_ = visible_; | 194 copy->appearance_ = appearance_; |
173 copy->icon_animation_ = icon_animation_; | 195 copy->icon_animation_ = icon_animation_; |
174 copy->default_icon_path_ = default_icon_path_; | 196 copy->default_icon_path_ = default_icon_path_; |
175 copy->id_ = id_; | 197 copy->id_ = id_; |
176 copy->icon_paths_ = icon_paths_; | 198 copy->icon_paths_ = icon_paths_; |
177 return copy.Pass(); | 199 return copy.Pass(); |
178 } | 200 } |
179 | 201 |
180 void ExtensionAction::SetPopupUrl(int tab_id, const GURL& url) { | 202 void ExtensionAction::SetPopupUrl(int tab_id, const GURL& url) { |
181 // We store |url| even if it is empty, rather than removing a URL from the | 203 // We store |url| even if it is empty, rather than removing a URL from the |
182 // map. If an extension has a default popup, and removes it for a tab via | 204 // map. If an extension has a default popup, and removes it for a tab via |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 std::map<std::string, gfx::Image>::const_iterator cached_icon = | 244 std::map<std::string, gfx::Image>::const_iterator cached_icon = |
223 path_to_icon_cache_.find(*path); | 245 path_to_icon_cache_.find(*path); |
224 if (cached_icon != path_to_icon_cache_.end()) { | 246 if (cached_icon != path_to_icon_cache_.end()) { |
225 icon = cached_icon->second; | 247 icon = cached_icon->second; |
226 } else { | 248 } else { |
227 icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( | 249 icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
228 IDR_EXTENSIONS_FAVICON); | 250 IDR_EXTENSIONS_FAVICON); |
229 } | 251 } |
230 } | 252 } |
231 | 253 |
| 254 if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION) { |
| 255 icon = gfx::Image(gfx::ImageSkia(new GetAttentionImageSource(icon), |
| 256 icon.ToImageSkia()->size())); |
| 257 } |
| 258 |
232 return ApplyIconAnimation(tab_id, icon); | 259 return ApplyIconAnimation(tab_id, icon); |
233 } | 260 } |
234 | 261 |
235 void ExtensionAction::SetIconIndex(int tab_id, int index) { | 262 void ExtensionAction::SetIconIndex(int tab_id, int index) { |
236 if (static_cast<size_t>(index) >= icon_paths_.size()) { | 263 if (static_cast<size_t>(index) >= icon_paths_.size()) { |
237 NOTREACHED(); | 264 NOTREACHED(); |
238 return; | 265 return; |
239 } | 266 } |
240 SetValue(&icon_index_, tab_id, index); | 267 SetValue(&icon_index_, tab_id, index); |
241 } | 268 } |
242 | 269 |
| 270 bool ExtensionAction::SetAppearance(int tab_id, Appearance new_appearance) { |
| 271 const Appearance old_appearance = GetValue(&appearance_, tab_id); |
| 272 |
| 273 if (old_appearance == new_appearance) |
| 274 return false; |
| 275 |
| 276 SetValue(&appearance_, tab_id, new_appearance); |
| 277 |
| 278 // When showing a badge for the first time on a web page, fade it |
| 279 // in. Other transitions happen instantly. |
| 280 if (old_appearance == INVISIBLE && tab_id != kDefaultTabId) { |
| 281 RunIconAnimation(tab_id); |
| 282 } |
| 283 |
| 284 return true; |
| 285 } |
| 286 |
243 void ExtensionAction::ClearAllValuesForTab(int tab_id) { | 287 void ExtensionAction::ClearAllValuesForTab(int tab_id) { |
244 popup_url_.erase(tab_id); | 288 popup_url_.erase(tab_id); |
245 title_.erase(tab_id); | 289 title_.erase(tab_id); |
246 icon_.erase(tab_id); | 290 icon_.erase(tab_id); |
247 icon_index_.erase(tab_id); | 291 icon_index_.erase(tab_id); |
248 badge_text_.erase(tab_id); | 292 badge_text_.erase(tab_id); |
249 badge_text_color_.erase(tab_id); | 293 badge_text_color_.erase(tab_id); |
250 badge_background_color_.erase(tab_id); | 294 badge_background_color_.erase(tab_id); |
251 visible_.erase(tab_id); | 295 appearance_.erase(tab_id); |
252 icon_animation_.erase(tab_id); | 296 icon_animation_.erase(tab_id); |
253 } | 297 } |
254 | 298 |
255 void ExtensionAction::PaintBadge(gfx::Canvas* canvas, | 299 void ExtensionAction::PaintBadge(gfx::Canvas* canvas, |
256 const gfx::Rect& bounds, | 300 const gfx::Rect& bounds, |
257 int tab_id) { | 301 int tab_id) { |
258 std::string text = GetBadgeText(tab_id); | 302 std::string text = GetBadgeText(tab_id); |
259 if (text.empty()) | 303 if (text.empty()) |
260 return; | 304 return; |
261 | 305 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 return orig; | 422 return orig; |
379 return gfx::Image(wrapper->animation()->Apply(*orig.ToSkBitmap())); | 423 return gfx::Image(wrapper->animation()->Apply(*orig.ToSkBitmap())); |
380 } | 424 } |
381 | 425 |
382 void ExtensionAction::RunIconAnimation(int tab_id) { | 426 void ExtensionAction::RunIconAnimation(int tab_id) { |
383 IconAnimationWrapper* icon_animation = | 427 IconAnimationWrapper* icon_animation = |
384 new IconAnimationWrapper(); | 428 new IconAnimationWrapper(); |
385 icon_animation_[tab_id] = icon_animation->AsWeakPtr(); | 429 icon_animation_[tab_id] = icon_animation->AsWeakPtr(); |
386 icon_animation->animation()->Start(); | 430 icon_animation->animation()->Start(); |
387 } | 431 } |
OLD | NEW |