Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: chrome/browser/download/download_shelf.cc

Issue 1236463002: Vectorize download shelf progress indicators (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix mac? Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. 5 #define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first.
6 6
7 #include "chrome/browser/download/download_shelf.h" 7 #include "chrome/browser/download/download_shelf.h"
8 8
9 #include <cmath> 9 #include <cmath>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/callback.h" 12 #include "base/callback.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/single_thread_task_runner.h" 14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
16 #include "base/thread_task_runner_handle.h" 16 #include "base/thread_task_runner_handle.h"
17 #include "base/time/time.h"
17 #include "chrome/browser/download/download_item_model.h" 18 #include "chrome/browser/download/download_item_model.h"
18 #include "chrome/browser/download/download_service.h" 19 #include "chrome/browser/download/download_service.h"
19 #include "chrome/browser/download/download_service_factory.h" 20 #include "chrome/browser/download/download_service_factory.h"
20 #include "chrome/browser/download/download_started_animation.h" 21 #include "chrome/browser/download/download_started_animation.h"
21 #include "chrome/browser/platform_util.h" 22 #include "chrome/browser/platform_util.h"
22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/themes/theme_properties.h"
23 #include "chrome/browser/ui/browser.h" 25 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h" 26 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/grit/locale_settings.h" 27 #include "chrome/grit/locale_settings.h"
26 #include "content/public/browser/browser_context.h" 28 #include "content/public/browser/browser_context.h"
27 #include "content/public/browser/download_item.h" 29 #include "content/public/browser/download_item.h"
28 #include "content/public/browser/download_manager.h" 30 #include "content/public/browser/download_manager.h"
29 #include "content/public/browser/web_contents.h" 31 #include "content/public/browser/web_contents.h"
30 #include "grit/theme_resources.h" 32 #include "grit/theme_resources.h"
33 #include "third_party/skia/include/core/SkPaint.h"
34 #include "third_party/skia/include/core/SkPath.h"
31 #include "ui/base/l10n/l10n_util.h" 35 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/base/resource/resource_bundle.h" 36 #include "ui/base/resource/resource_bundle.h"
37 #include "ui/base/theme_provider.h"
33 #include "ui/gfx/animation/animation.h" 38 #include "ui/gfx/animation/animation.h"
34 #include "ui/gfx/canvas.h" 39 #include "ui/gfx/canvas.h"
35 #include "ui/gfx/image/image_skia.h"
36 40
37 using content::DownloadItem; 41 using content::DownloadItem;
38 42
39 namespace { 43 namespace {
40 44
41 // Delay before we show a transient download. 45 // Delay before we show a transient download.
42 const int64 kDownloadShowDelayInSeconds = 2; 46 const int64 kDownloadShowDelayInSeconds = 2;
43 47
44 // Get the opacity based on |animation_progress|, with values in [0.0, 1.0]. 48 // Get the opacity based on |animation_progress|, with values in [0.0, 1.0].
45 // Range of return value is [0, 255]. 49 // Range of return value is [0, 255].
(...skipping 13 matching lines...) Expand all
59 DownloadShelf::DownloadShelf() 63 DownloadShelf::DownloadShelf()
60 : should_show_on_unhide_(false), 64 : should_show_on_unhide_(false),
61 is_hidden_(false), 65 is_hidden_(false),
62 weak_ptr_factory_(this) { 66 weak_ptr_factory_(this) {
63 } 67 }
64 68
65 DownloadShelf::~DownloadShelf() {} 69 DownloadShelf::~DownloadShelf() {}
66 70
67 // Download progress painting -------------------------------------------------- 71 // Download progress painting --------------------------------------------------
68 72
69 // Common images used for download progress animations. We load them once the
70 // first time we do a progress paint, then reuse them as they are always the
71 // same.
72 gfx::ImageSkia* g_foreground_16 = NULL;
73 gfx::ImageSkia* g_background_16 = NULL;
74
75 // static 73 // static
76 void DownloadShelf::PaintDownloadProgress( 74 void DownloadShelf::PaintDownloadProgress(
77 gfx::Canvas* canvas, 75 gfx::Canvas* canvas,
78 const BoundsAdjusterCallback& rtl_mirror, 76 const ui::ThemeProvider& theme_provider,
79 int origin_x, 77 const base::TimeTicks& progress_start_time,
80 int origin_y,
81 int start_angle,
82 int percent_done) { 78 int percent_done) {
83 // Load up our common images. 79 // Draw background (light blue circle).
84 if (!g_background_16) { 80 SkPaint bg_paint;
85 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 81 bg_paint.setStyle(SkPaint::kFill_Style);
86 g_foreground_16 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_16); 82 SkColor indicator_color =
87 g_background_16 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_BACKGROUND_16); 83 theme_provider.GetColor(ThemeProperties::COLOR_THROBBER_SPINNING);
88 DCHECK_EQ(g_foreground_16->width(), g_background_16->width()); 84 bg_paint.setColor(SkColorSetA(indicator_color, 0x33));
89 DCHECK_EQ(g_foreground_16->height(), g_background_16->height()); 85 bg_paint.setAntiAlias(true);
86 const SkScalar kCenterPoint = kProgressIndicatorSize / 2.f;
87 const SkScalar kRadius = 12.5f;
88 SkPath bg;
89 bg.addCircle(kCenterPoint, kCenterPoint, kRadius);
90 canvas->DrawPath(bg, bg_paint);
91
92 // Calculate progress.
93 SkScalar sweep_angle = 0.f;
94 // Start at 12 o'clock.
95 SkScalar start_pos = SkIntToScalar(270);
96 if (percent_done < 0) {
97 // For unknown size downloads, draw a 50 degree sweep that moves at
98 // 0.08 degrees per millisecond.
99 sweep_angle = 50.f;
100 start_pos += static_cast<SkScalar>(
101 (base::TimeTicks::Now() - progress_start_time).InMilliseconds() * 0.08);
102 } else if (percent_done > 0) {
103 sweep_angle = static_cast<SkScalar>(360 * percent_done / 100.0);
90 } 104 }
91 105
92 // We start by storing the bounds of the images so that it is easy to mirror 106 // Draw progress.
93 // the bounds if the UI layout is RTL. 107 SkPath progress;
94 gfx::Rect bounds(origin_x, origin_y, g_background_16->width(), 108 progress.addArc(SkRect::MakeLTRB(kCenterPoint - kRadius,
95 g_background_16->height()); 109 kCenterPoint - kRadius,
96 110 kCenterPoint + kRadius,
97 // Mirror the positions if necessary. 111 kCenterPoint + kRadius),
98 rtl_mirror.Run(&bounds); 112 start_pos, sweep_angle);
99 113 SkPaint progress_paint;
100 // Draw the background progress image. 114 progress_paint.setColor(indicator_color);
101 canvas->DrawImageInt(*g_background_16, bounds.x(), bounds.y()); 115 progress_paint.setStyle(SkPaint::kStroke_Style);
102 116 progress_paint.setStrokeWidth(1.7f);
103 // Layer the foreground progress image in an arc proportional to the download 117 progress_paint.setAntiAlias(true);
104 // progress. The arc grows clockwise, starting in the midnight position, as 118 canvas->DrawPath(progress, progress_paint);
105 // the download progresses. However, if the download does not have known total
106 // size (the server didn't give us one), then we just spin an arc around until
107 // we're done.
108 float sweep_angle = 0.0;
109 float start_pos = static_cast<float>(kStartAngleDegrees);
110 if (percent_done < 0) {
111 sweep_angle = kUnknownAngleDegrees;
112 start_pos = static_cast<float>(start_angle);
113 } else if (percent_done > 0) {
114 sweep_angle = static_cast<float>(kMaxDegrees / 100.0 * percent_done);
115 }
116
117 // Set up an arc clipping region for the foreground image. Don't bother using
118 // a clipping region if it would round to 360 (really 0) degrees, since that
119 // would eliminate the foreground completely and be quite confusing (it would
120 // look like 0% complete when it should be almost 100%).
121 canvas->Save();
122 if (sweep_angle < static_cast<float>(kMaxDegrees - 1)) {
123 SkRect oval;
124 oval.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()),
125 SkIntToScalar(bounds.x() + DownloadShelf::kSmallProgressIconSize),
126 SkIntToScalar(bounds.y() + DownloadShelf::kSmallProgressIconSize));
127 SkPath path;
128 path.arcTo(oval,
129 SkFloatToScalar(start_pos),
130 SkFloatToScalar(sweep_angle), false);
131 path.lineTo(
132 SkIntToScalar(bounds.x() + DownloadShelf::kSmallProgressIconSize / 2),
133 SkIntToScalar(bounds.y() + DownloadShelf::kSmallProgressIconSize / 2));
134
135 // gfx::Canvas::ClipPath does not provide for anti-aliasing.
136 canvas->sk_canvas()->clipPath(path, SkRegion::kIntersect_Op, true);
137 }
138
139 canvas->DrawImageInt(*g_foreground_16, bounds.x(), bounds.y());
140 canvas->Restore();
141 } 119 }
142 120
143 // static 121 // static
144 void DownloadShelf::PaintDownloadComplete( 122 void DownloadShelf::PaintDownloadComplete(
145 gfx::Canvas* canvas, 123 gfx::Canvas* canvas,
146 const BoundsAdjusterCallback& rtl_mirror, 124 const ui::ThemeProvider& theme_provider,
147 int origin_x,
148 int origin_y,
149 double animation_progress) { 125 double animation_progress) {
150 // Load up our common images.
151 if (!g_foreground_16) {
152 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
153 g_foreground_16 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_16);
154 }
155
156 gfx::Rect complete_bounds(origin_x, origin_y, g_foreground_16->width(),
157 g_foreground_16->height());
158 // Mirror the positions if necessary.
159 rtl_mirror.Run(&complete_bounds);
160
161 // Start at full opacity, then loop back and forth five times before ending 126 // Start at full opacity, then loop back and forth five times before ending
162 // at zero opacity. 127 // at zero opacity.
163 canvas->DrawImageInt(*g_foreground_16, complete_bounds.x(), 128 canvas->sk_canvas()->saveLayerAlpha(nullptr, GetOpacity(animation_progress));
164 complete_bounds.y(), GetOpacity(animation_progress)); 129 PaintDownloadProgress(canvas, theme_provider, base::TimeTicks(), 100);
130 canvas->sk_canvas()->restore();
165 } 131 }
166 132
167 // static 133 // static
168 void DownloadShelf::PaintDownloadInterrupted( 134 void DownloadShelf::PaintDownloadInterrupted(
169 gfx::Canvas* canvas, 135 gfx::Canvas* canvas,
170 const BoundsAdjusterCallback& rtl_mirror, 136 const ui::ThemeProvider& theme_provider,
171 int origin_x,
172 int origin_y,
173 double animation_progress) { 137 double animation_progress) {
174 // Start at zero opacity, then loop back and forth five times before ending 138 // Start at zero opacity, then loop back and forth five times before ending
175 // at full opacity. 139 // at full opacity.
176 PaintDownloadComplete(canvas, rtl_mirror, origin_x, origin_y, 140 PaintDownloadComplete(canvas, theme_provider, 1.0 - animation_progress);
177 1.0 - animation_progress);
178 } 141 }
179 142
180 void DownloadShelf::AddDownload(DownloadItem* download) { 143 void DownloadShelf::AddDownload(DownloadItem* download) {
181 DCHECK(download); 144 DCHECK(download);
182 if (DownloadItemModel(download).ShouldRemoveFromShelfWhenComplete()) { 145 if (DownloadItemModel(download).ShouldRemoveFromShelfWhenComplete()) {
183 // If we are going to remove the download from the shelf upon completion, 146 // If we are going to remove the download from the shelf upon completion,
184 // wait a few seconds to see if it completes quickly. If it's a small 147 // wait a few seconds to see if it completes quickly. If it's a small
185 // download, then the user won't have time to interact with it. 148 // download, then the user won't have time to interact with it.
186 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 149 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
187 FROM_HERE, 150 FROM_HERE,
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 content::DownloadManager* download_manager = GetDownloadManager(); 237 content::DownloadManager* download_manager = GetDownloadManager();
275 if (!download_manager) 238 if (!download_manager)
276 return; 239 return;
277 240
278 DownloadItem* download = download_manager->GetDownload(download_id); 241 DownloadItem* download = download_manager->GetDownload(download_id);
279 if (!download) 242 if (!download)
280 return; 243 return;
281 244
282 ShowDownload(download); 245 ShowDownload(download);
283 } 246 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698