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

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: . 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"
23 #include "chrome/browser/ui/browser.h" 24 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h" 25 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/grit/locale_settings.h" 26 #include "chrome/grit/locale_settings.h"
26 #include "content/public/browser/browser_context.h" 27 #include "content/public/browser/browser_context.h"
27 #include "content/public/browser/download_item.h" 28 #include "content/public/browser/download_item.h"
28 #include "content/public/browser/download_manager.h" 29 #include "content/public/browser/download_manager.h"
29 #include "content/public/browser/web_contents.h" 30 #include "content/public/browser/web_contents.h"
30 #include "grit/theme_resources.h" 31 #include "grit/theme_resources.h"
32 #include "third_party/skia/include/core/SkPaint.h"
33 #include "third_party/skia/include/core/SkPath.h"
31 #include "ui/base/l10n/l10n_util.h" 34 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/base/resource/resource_bundle.h" 35 #include "ui/base/resource/resource_bundle.h"
33 #include "ui/gfx/animation/animation.h" 36 #include "ui/gfx/animation/animation.h"
34 #include "ui/gfx/canvas.h" 37 #include "ui/gfx/canvas.h"
35 #include "ui/gfx/image/image_skia.h"
36 38
37 using content::DownloadItem; 39 using content::DownloadItem;
38 40
39 namespace { 41 namespace {
40 42
41 // Delay before we show a transient download. 43 // Delay before we show a transient download.
42 const int64 kDownloadShowDelayInSeconds = 2; 44 const int64 kDownloadShowDelayInSeconds = 2;
43 45
44 // Get the opacity based on |animation_progress|, with values in [0.0, 1.0]. 46 // Get the opacity based on |animation_progress|, with values in [0.0, 1.0].
45 // Range of return value is [0, 255]. 47 // Range of return value is [0, 255].
(...skipping 13 matching lines...) Expand all
59 DownloadShelf::DownloadShelf() 61 DownloadShelf::DownloadShelf()
60 : should_show_on_unhide_(false), 62 : should_show_on_unhide_(false),
61 is_hidden_(false), 63 is_hidden_(false),
62 weak_ptr_factory_(this) { 64 weak_ptr_factory_(this) {
63 } 65 }
64 66
65 DownloadShelf::~DownloadShelf() {} 67 DownloadShelf::~DownloadShelf() {}
66 68
67 // Download progress painting -------------------------------------------------- 69 // Download progress painting --------------------------------------------------
68 70
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 71 // static
76 void DownloadShelf::PaintDownloadProgress( 72 void DownloadShelf::PaintDownloadProgress(
77 gfx::Canvas* canvas, 73 gfx::Canvas* canvas,
78 const BoundsAdjusterCallback& rtl_mirror, 74 const base::TimeTicks& progress_start_time,
79 int origin_x,
80 int origin_y,
81 int start_angle,
82 int percent_done) { 75 int percent_done) {
83 // Load up our common images. 76 // Draw background (light blue circle).
84 if (!g_background_16) { 77 SkPaint bg_paint;
85 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 78 bg_paint.setStyle(SkPaint::kFill_Style);
86 g_foreground_16 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_16); 79 bg_paint.setColor(SkColorSetRGB(0xD7, 0xE4, 0xFA));
87 g_background_16 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_BACKGROUND_16); 80 bg_paint.setAntiAlias(true);
88 DCHECK_EQ(g_foreground_16->width(), g_background_16->width()); 81 SkPath bg;
89 DCHECK_EQ(g_foreground_16->height(), g_background_16->height()); 82 bg.addCircle(20, 20, 13);
83 canvas->DrawPath(bg, bg_paint);
84
85 // Calculate progress.
86 SkScalar sweep_angle = 0.f;
87 // Start at 12 o'clock.
88 SkScalar start_pos = SkIntToScalar(270);
89 if (percent_done < 0) {
90 // For unknown size downloads, draw a 50 degree sweep that moves at
91 // 0.08 degrees per millisecond.
92 sweep_angle = 50.f;
93 start_pos += static_cast<SkScalar>(
94 (base::TimeTicks::Now() - progress_start_time).InMilliseconds() * 0.08);
95 } else if (percent_done > 0) {
96 sweep_angle = static_cast<SkScalar>(360 * percent_done / 100.0);
90 } 97 }
91 98
92 // We start by storing the bounds of the images so that it is easy to mirror 99 // Draw progress.
93 // the bounds if the UI layout is RTL. 100 SkPath progress;
94 gfx::Rect bounds(origin_x, origin_y, g_background_16->width(), 101 progress.addArc(SkRect::MakeXYWH(7, 7, 25, 25), start_pos, sweep_angle);
95 g_background_16->height()); 102 SkPaint progress_paint;
96 103 progress_paint.setColor(SkColorSetRGB(0x41, 0x84, 0xF4));
97 // Mirror the positions if necessary. 104 progress_paint.setStyle(SkPaint::kStroke_Style);
98 rtl_mirror.Run(&bounds); 105 progress_paint.setStrokeWidth(1.7f);
99 106 progress_paint.setAntiAlias(true);
100 // Draw the background progress image. 107 canvas->DrawPath(progress, progress_paint);
101 canvas->DrawImageInt(*g_background_16, bounds.x(), bounds.y());
102
103 // Layer the foreground progress image in an arc proportional to the download
104 // progress. The arc grows clockwise, starting in the midnight position, as
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 } 108 }
142 109
143 // static 110 // static
144 void DownloadShelf::PaintDownloadComplete( 111 void DownloadShelf::PaintDownloadComplete(
145 gfx::Canvas* canvas, 112 gfx::Canvas* canvas,
146 const BoundsAdjusterCallback& rtl_mirror,
147 int origin_x,
148 int origin_y,
149 double animation_progress) { 113 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 114 // Start at full opacity, then loop back and forth five times before ending
162 // at zero opacity. 115 // at zero opacity.
163 canvas->DrawImageInt(*g_foreground_16, complete_bounds.x(), 116 canvas->sk_canvas()->saveLayerAlpha(nullptr, GetOpacity(animation_progress));
164 complete_bounds.y(), GetOpacity(animation_progress)); 117 PaintDownloadProgress(canvas, base::TimeTicks(), 100);
118 canvas->sk_canvas()->restore();
165 } 119 }
166 120
167 // static 121 // static
168 void DownloadShelf::PaintDownloadInterrupted( 122 void DownloadShelf::PaintDownloadInterrupted(
169 gfx::Canvas* canvas, 123 gfx::Canvas* canvas,
170 const BoundsAdjusterCallback& rtl_mirror,
171 int origin_x,
172 int origin_y,
173 double animation_progress) { 124 double animation_progress) {
174 // Start at zero opacity, then loop back and forth five times before ending 125 // Start at zero opacity, then loop back and forth five times before ending
175 // at full opacity. 126 // at full opacity.
176 PaintDownloadComplete(canvas, rtl_mirror, origin_x, origin_y, 127 PaintDownloadComplete(canvas, 1.0 - animation_progress);
177 1.0 - animation_progress);
178 } 128 }
179 129
180 void DownloadShelf::AddDownload(DownloadItem* download) { 130 void DownloadShelf::AddDownload(DownloadItem* download) {
181 DCHECK(download); 131 DCHECK(download);
182 if (DownloadItemModel(download).ShouldRemoveFromShelfWhenComplete()) { 132 if (DownloadItemModel(download).ShouldRemoveFromShelfWhenComplete()) {
183 // If we are going to remove the download from the shelf upon completion, 133 // 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 134 // 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. 135 // download, then the user won't have time to interact with it.
186 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 136 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
187 FROM_HERE, 137 FROM_HERE,
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 content::DownloadManager* download_manager = GetDownloadManager(); 224 content::DownloadManager* download_manager = GetDownloadManager();
275 if (!download_manager) 225 if (!download_manager)
276 return; 226 return;
277 227
278 DownloadItem* download = download_manager->GetDownload(download_id); 228 DownloadItem* download = download_manager->GetDownload(download_id);
279 if (!download) 229 if (!download)
280 return; 230 return;
281 231
282 ShowDownload(download); 232 ShowDownload(download);
283 } 233 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698